From af8501174805444b37bb92721390be08d3c90912 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Mon, 29 Sep 2025 19:08:35 +0900 Subject: [PATCH 01/88] =?UTF-8?q?[SETTING]=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=EC=A1=B0=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/sampoom/android/data/local/database/.gitkeep | 0 .../main/java/com/sampoom/android/data/local/preferences/.gitkeep | 0 app/src/main/java/com/sampoom/android/data/mapper/.gitkeep | 0 app/src/main/java/com/sampoom/android/data/remote/api/.gitkeep | 0 app/src/main/java/com/sampoom/android/data/remote/dto/.gitkeep | 0 app/src/main/java/com/sampoom/android/data/repository/.gitkeep | 0 app/src/main/java/com/sampoom/android/domain/model/.gitkeep | 0 app/src/main/java/com/sampoom/android/domain/repository/.gitkeep | 0 app/src/main/java/com/sampoom/android/domain/usecase/.gitkeep | 0 app/src/main/java/com/sampoom/android/ui/component/.gitkeep | 0 app/src/main/java/com/sampoom/android/ui/navigation/.gitkeep | 0 app/src/main/java/com/sampoom/android/ui/screen/.gitkeep | 0 12 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/data/local/database/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/data/local/preferences/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/data/mapper/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/data/remote/api/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/data/remote/dto/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/data/repository/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/domain/model/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/domain/repository/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/domain/usecase/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/ui/component/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/ui/navigation/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/ui/screen/.gitkeep diff --git a/app/src/main/java/com/sampoom/android/data/local/database/.gitkeep b/app/src/main/java/com/sampoom/android/data/local/database/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/data/local/preferences/.gitkeep b/app/src/main/java/com/sampoom/android/data/local/preferences/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/data/mapper/.gitkeep b/app/src/main/java/com/sampoom/android/data/mapper/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/data/remote/api/.gitkeep b/app/src/main/java/com/sampoom/android/data/remote/api/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/data/remote/dto/.gitkeep b/app/src/main/java/com/sampoom/android/data/remote/dto/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/data/repository/.gitkeep b/app/src/main/java/com/sampoom/android/data/repository/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/domain/model/.gitkeep b/app/src/main/java/com/sampoom/android/domain/model/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/domain/repository/.gitkeep b/app/src/main/java/com/sampoom/android/domain/repository/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/domain/usecase/.gitkeep b/app/src/main/java/com/sampoom/android/domain/usecase/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/ui/component/.gitkeep b/app/src/main/java/com/sampoom/android/ui/component/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/ui/navigation/.gitkeep b/app/src/main/java/com/sampoom/android/ui/navigation/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/ui/screen/.gitkeep b/app/src/main/java/com/sampoom/android/ui/screen/.gitkeep new file mode 100644 index 0000000..e69de29 From d6c087ab5036e6ae29e0e744ee26678d3ff6edee Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Tue, 30 Sep 2025 10:51:35 +0900 Subject: [PATCH 02/88] =?UTF-8?q?[REFAC]=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=EC=A1=B0=20Pakage=20by=20Layer=20->=20Pak?= =?UTF-8?q?age=20by=20Feature=20=EB=B3=80=EA=B2=BD=20/=20=EC=83=98?= =?UTF-8?q?=ED=94=8C=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 25 +++++++- app/src/main/AndroidManifest.xml | 2 +- .../java/com/sampoom/android/MainActivity.kt | 30 +++------ .../com/sampoom/android/app/Application.kt | 7 +++ .../com/sampoom/android/app/di/AppModule.kt | 16 +++++ .../android/app/navigation/AppNavHost.kt | 20 ++++++ .../sampoom/android/core/common/AppResult.kt | 12 ++++ .../android/core/common/DispatcherProvider.kt | 17 +++++ .../{data/local => core}/database/.gitkeep | 0 .../android/core/network/NetworkModule.kt | 24 +++++++ .../ui/component}/.gitkeep | 0 .../android/{ => core}/ui/theme/Color.kt | 2 +- .../android/{ => core}/ui/theme/Theme.kt | 3 +- .../android/{ => core}/ui/theme/Type.kt | 2 +- .../auth/data/local/database}/.gitkeep | 0 .../data/local/preferences/AuthPreferences.kt | 21 +++++++ .../feature/auth/data/mapper/AuthMappers.kt | 6 ++ .../feature/auth/data/remote/api/AuthApi.kt | 11 ++++ .../auth/data/remote/dto/LoginRequestDto.kt | 6 ++ .../feature/auth/data/remote/dto/UserDto.kt | 8 +++ .../data/repository/AuthRepositoryImpl.kt | 30 +++++++++ .../android/feature/auth/di/AuthModules.kt | 26 ++++++++ .../android/feature/auth/domain/model/User.kt | 8 +++ .../auth/domain/repository/AuthRepository.kt | 9 +++ .../auth/domain/usecase/SignInUseCase.kt | 11 ++++ .../android/feature/auth/ui/LoginScreen.kt | 63 +++++++++++++++++++ .../android/feature/auth/ui/LoginUiEvent.kt | 7 +++ .../android/feature/auth/ui/LoginUiState.kt | 9 +++ .../android/feature/auth/ui/LoginViewModel.kt | 35 +++++++++++ .../sample/data/local/database}/.gitkeep | 0 .../sample/data/local/preferences}/.gitkeep | 0 .../sample/data/mapper}/.gitkeep | 0 .../sample/data/remote/api}/.gitkeep | 0 .../sample/data/remote/dto}/.gitkeep | 0 .../sample/data/repository}/.gitkeep | 0 .../component => feature/sample/di}/.gitkeep | 0 .../sample/domain/model}/.gitkeep | 0 .../sample/domain/repository}/.gitkeep | 0 .../feature/sample/domain/usecase/.gitkeep | 0 .../android/feature/sample/ui/.gitkeep | 0 build.gradle.kts | 2 + gradle/libs.versions.toml | 15 ++++- 42 files changed, 394 insertions(+), 33 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/app/Application.kt create mode 100644 app/src/main/java/com/sampoom/android/app/di/AppModule.kt create mode 100644 app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt create mode 100644 app/src/main/java/com/sampoom/android/core/common/AppResult.kt create mode 100644 app/src/main/java/com/sampoom/android/core/common/DispatcherProvider.kt rename app/src/main/java/com/sampoom/android/{data/local => core}/database/.gitkeep (100%) create mode 100644 app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt rename app/src/main/java/com/sampoom/android/{data/local/preferences => core/ui/component}/.gitkeep (100%) rename app/src/main/java/com/sampoom/android/{ => core}/ui/theme/Color.kt (85%) rename app/src/main/java/com/sampoom/android/{ => core}/ui/theme/Theme.kt (96%) rename app/src/main/java/com/sampoom/android/{ => core}/ui/theme/Type.kt (95%) rename app/src/main/java/com/sampoom/android/{data/mapper => feature/auth/data/local/database}/.gitkeep (100%) create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/data/local/preferences/AuthPreferences.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginRequestDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UserDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/di/AuthModules.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignInUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiEvent.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiState.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt rename app/src/main/java/com/sampoom/android/{data/remote/api => feature/sample/data/local/database}/.gitkeep (100%) rename app/src/main/java/com/sampoom/android/{data/remote/dto => feature/sample/data/local/preferences}/.gitkeep (100%) rename app/src/main/java/com/sampoom/android/{data/repository => feature/sample/data/mapper}/.gitkeep (100%) rename app/src/main/java/com/sampoom/android/{domain/model => feature/sample/data/remote/api}/.gitkeep (100%) rename app/src/main/java/com/sampoom/android/{domain/repository => feature/sample/data/remote/dto}/.gitkeep (100%) rename app/src/main/java/com/sampoom/android/{domain/usecase => feature/sample/data/repository}/.gitkeep (100%) rename app/src/main/java/com/sampoom/android/{ui/component => feature/sample/di}/.gitkeep (100%) rename app/src/main/java/com/sampoom/android/{ui/navigation => feature/sample/domain/model}/.gitkeep (100%) rename app/src/main/java/com/sampoom/android/{ui/screen => feature/sample/domain/repository}/.gitkeep (100%) create mode 100644 app/src/main/java/com/sampoom/android/feature/sample/domain/usecase/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/sample/ui/.gitkeep diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5eb1bb8..396151f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,10 +1,13 @@ import java.io.FileInputStream import java.util.Properties +import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.compose) + id("com.google.devtools.ksp") + id("com.google.dagger.hilt.android") } // Keystore.properties @@ -49,15 +52,31 @@ android { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } - kotlinOptions { - jvmTarget = "11" - } buildFeatures { compose = true } } +// Kotlin compiler options migrated to Compiler Options DSL +kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_11) + } +} + dependencies { + // hilt + implementation(libs.hilt.android) + ksp(libs.hilt.android.compiler) + implementation(libs.androidx.hilt.lifecycle.viewmodel.compose) + implementation(libs.androidx.hilt.navigation.compose) + + // Navigation + implementation(libs.androidx.navigation.compose) + + // Retrofit + implementation(libs.retrofit) + implementation(libs.converter.gson) implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.ktx) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 510906a..647ee15 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ xmlns:tools="http://schemas.android.com/tools"> diff --git a/app/src/main/java/com/sampoom/android/MainActivity.kt b/app/src/main/java/com/sampoom/android/MainActivity.kt index 3042527..8823d78 100644 --- a/app/src/main/java/com/sampoom/android/MainActivity.kt +++ b/app/src/main/java/com/sampoom/android/MainActivity.kt @@ -11,37 +11,21 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview -import com.sampoom.android.ui.theme.SampoomManagementTheme +import androidx.navigation.compose.rememberNavController +import com.sampoom.android.app.navigation.AppNavHost +import com.sampoom.android.core.ui.theme.SampoomManagementTheme +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { SampoomManagementTheme { - Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> - Greeting( - name = "Android", - modifier = Modifier.padding(innerPadding) - ) - } + val navController = rememberNavController() + AppNavHost(navController) } } } -} - -@Composable -fun Greeting(name: String, modifier: Modifier = Modifier) { - Text( - text = "Hello $name!", - modifier = modifier - ) -} - -@Preview(showBackground = true) -@Composable -fun GreetingPreview() { - SampoomManagementTheme { - Greeting("Android") - } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/app/Application.kt b/app/src/main/java/com/sampoom/android/app/Application.kt new file mode 100644 index 0000000..bb91835 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/app/Application.kt @@ -0,0 +1,7 @@ +package com.sampoom.android.app + +import android.app.Application +import dagger.hilt.android.HiltAndroidApp + +@HiltAndroidApp +class Application : Application() \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/app/di/AppModule.kt b/app/src/main/java/com/sampoom/android/app/di/AppModule.kt new file mode 100644 index 0000000..f49417e --- /dev/null +++ b/app/src/main/java/com/sampoom/android/app/di/AppModule.kt @@ -0,0 +1,16 @@ +package com.sampoom.android.app.di + +import com.sampoom.android.core.common.DispatcherProvider +import com.sampoom.android.core.common.DispatcherProviderImpl +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +abstract class AppModule { + @Binds @Singleton + abstract fun bindDispatchers(impl: DispatcherProviderImpl): DispatcherProvider +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt new file mode 100644 index 0000000..39897c6 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -0,0 +1,20 @@ +package com.sampoom.android.app.navigation + +import androidx.compose.runtime.Composable +import androidx.navigation.NavHostController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import com.sampoom.android.feature.auth.ui.LoginScreen + +const val ROUTE_LOGIN = "login" + +@Composable +fun AppNavHost(navController: NavHostController) { + NavHost(navController, startDestination = ROUTE_LOGIN) { + composable(ROUTE_LOGIN) { LoginScreen(onSuccess = { +// navController.navigate("main") { +// popUpTo(ROUTE_LOGIN) { inclusive = true } // 로그인 화면 스택 제거 +// } + }) } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/common/AppResult.kt b/app/src/main/java/com/sampoom/android/core/common/AppResult.kt new file mode 100644 index 0000000..f05e748 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/common/AppResult.kt @@ -0,0 +1,12 @@ +package com.sampoom.android.core.common + +sealed class AppResult { + data class Success(val value: T) : AppResult() + data class Error(val throwable: Throwable) : AppResult() +} + +inline fun appRunCatching(block: () -> T): AppResult = try { + AppResult.Success(block()) +} catch (t: Throwable) { + AppResult.Error(t) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/common/DispatcherProvider.kt b/app/src/main/java/com/sampoom/android/core/common/DispatcherProvider.kt new file mode 100644 index 0000000..d5ae202 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/common/DispatcherProvider.kt @@ -0,0 +1,17 @@ +package com.sampoom.android.core.common + +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import javax.inject.Inject + +interface DispatcherProvider { + val io: CoroutineDispatcher + val main: CoroutineDispatcher + val default: CoroutineDispatcher +} + +class DispatcherProviderImpl @Inject constructor() : DispatcherProvider { + override val io = Dispatchers.IO + override val main = Dispatchers.Main + override val default = Dispatchers.Default +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/data/local/database/.gitkeep b/app/src/main/java/com/sampoom/android/core/database/.gitkeep similarity index 100% rename from app/src/main/java/com/sampoom/android/data/local/database/.gitkeep rename to app/src/main/java/com/sampoom/android/core/database/.gitkeep diff --git a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt new file mode 100644 index 0000000..2708b90 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt @@ -0,0 +1,24 @@ +package com.sampoom.android.core.network + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import okhttp3.OkHttpClient +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +object NetworkModule { + @Provides @Singleton fun provideOkHttp(): OkHttpClient = OkHttpClient.Builder().build() + + @Provides @Singleton + fun provideRetrofit(client: OkHttpClient): Retrofit = + Retrofit.Builder() + .baseUrl("http://10.0.2.2:8080/") + .client(client) + .addConverterFactory(GsonConverterFactory.create()) + .build() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/data/local/preferences/.gitkeep b/app/src/main/java/com/sampoom/android/core/ui/component/.gitkeep similarity index 100% rename from app/src/main/java/com/sampoom/android/data/local/preferences/.gitkeep rename to app/src/main/java/com/sampoom/android/core/ui/component/.gitkeep diff --git a/app/src/main/java/com/sampoom/android/ui/theme/Color.kt b/app/src/main/java/com/sampoom/android/core/ui/theme/Color.kt similarity index 85% rename from app/src/main/java/com/sampoom/android/ui/theme/Color.kt rename to app/src/main/java/com/sampoom/android/core/ui/theme/Color.kt index c7ef588..14c8259 100644 --- a/app/src/main/java/com/sampoom/android/ui/theme/Color.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/theme/Color.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.ui.theme +package com.sampoom.android.core.ui.theme import androidx.compose.ui.graphics.Color diff --git a/app/src/main/java/com/sampoom/android/ui/theme/Theme.kt b/app/src/main/java/com/sampoom/android/core/ui/theme/Theme.kt similarity index 96% rename from app/src/main/java/com/sampoom/android/ui/theme/Theme.kt rename to app/src/main/java/com/sampoom/android/core/ui/theme/Theme.kt index cd4d75c..26b2837 100644 --- a/app/src/main/java/com/sampoom/android/ui/theme/Theme.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/theme/Theme.kt @@ -1,6 +1,5 @@ -package com.sampoom.android.ui.theme +package com.sampoom.android.core.ui.theme -import android.app.Activity import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.MaterialTheme diff --git a/app/src/main/java/com/sampoom/android/ui/theme/Type.kt b/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt similarity index 95% rename from app/src/main/java/com/sampoom/android/ui/theme/Type.kt rename to app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt index 9724dcf..6a3a086 100644 --- a/app/src/main/java/com/sampoom/android/ui/theme/Type.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.ui.theme +package com.sampoom.android.core.ui.theme import androidx.compose.material3.Typography import androidx.compose.ui.text.TextStyle diff --git a/app/src/main/java/com/sampoom/android/data/mapper/.gitkeep b/app/src/main/java/com/sampoom/android/feature/auth/data/local/database/.gitkeep similarity index 100% rename from app/src/main/java/com/sampoom/android/data/mapper/.gitkeep rename to app/src/main/java/com/sampoom/android/feature/auth/data/local/database/.gitkeep diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/local/preferences/AuthPreferences.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/local/preferences/AuthPreferences.kt new file mode 100644 index 0000000..8345a3f --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/local/preferences/AuthPreferences.kt @@ -0,0 +1,21 @@ +package com.sampoom.android.feature.auth.data.local.preferences + +import android.content.Context +import dagger.hilt.android.qualifiers.ApplicationContext +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class AuthPreferences @Inject constructor( + @ApplicationContext private val context: Context +){ + private val sharedPreferences = context.getSharedPreferences("auth", Context.MODE_PRIVATE) + + fun saveToken(token: String) { + sharedPreferences.edit().putString("token", token) + } + fun clear() { + sharedPreferences.edit().clear().apply() + } + fun hasToken(): Boolean = !sharedPreferences.getString("token", null).isNullOrEmpty() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt new file mode 100644 index 0000000..c6bf3b0 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt @@ -0,0 +1,6 @@ +package com.sampoom.android.feature.auth.data.mapper + +import com.sampoom.android.feature.auth.data.remote.dto.UserDto +import com.sampoom.android.feature.auth.domain.model.User + +fun UserDto.toModel(): User = User(id, name, email, token) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt new file mode 100644 index 0000000..ce4be9b --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.auth.data.remote.api + +import com.sampoom.android.feature.auth.data.remote.dto.LoginRequestDto +import com.sampoom.android.feature.auth.data.remote.dto.UserDto +import retrofit2.http.Body +import retrofit2.http.POST + +interface AuthApi { + @POST("auth/login") + suspend fun login(@Body body: LoginRequestDto): UserDto +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginRequestDto.kt new file mode 100644 index 0000000..136b9ac --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginRequestDto.kt @@ -0,0 +1,6 @@ +package com.sampoom.android.feature.auth.data.remote.dto + +data class LoginRequestDto( + val email: String, + val password: String +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UserDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UserDto.kt new file mode 100644 index 0000000..38f07e2 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UserDto.kt @@ -0,0 +1,8 @@ +package com.sampoom.android.feature.auth.data.remote.dto + +data class UserDto( + val id: String, + val name: String, + val email: String, + val token: String +) diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt new file mode 100644 index 0000000..1d72da4 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt @@ -0,0 +1,30 @@ +package com.sampoom.android.feature.auth.data.repository + +import com.sampoom.android.feature.auth.data.local.preferences.AuthPreferences +import com.sampoom.android.feature.auth.data.mapper.toModel +import com.sampoom.android.feature.auth.data.remote.api.AuthApi +import com.sampoom.android.feature.auth.data.remote.dto.LoginRequestDto +import com.sampoom.android.feature.auth.domain.model.User +import com.sampoom.android.feature.auth.domain.repository.AuthRepository +import javax.inject.Inject + +class AuthRepositoryImpl @Inject constructor( + private val api: AuthApi, + private val preferences: AuthPreferences +) : AuthRepository { + override suspend fun signIn( + email: String, + password: String + ): User { + val dto = api.login(LoginRequestDto(email, password)) + preferences.saveToken(dto.token) + return dto.toModel() + } + + override suspend fun signOut() { + preferences.clear() + } + + override fun isSignedIn(): Boolean = preferences.hasToken() + +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/di/AuthModules.kt b/app/src/main/java/com/sampoom/android/feature/auth/di/AuthModules.kt new file mode 100644 index 0000000..87b7f09 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/di/AuthModules.kt @@ -0,0 +1,26 @@ +package com.sampoom.android.feature.auth.di + +import com.sampoom.android.feature.auth.data.remote.api.AuthApi +import com.sampoom.android.feature.auth.data.repository.AuthRepositoryImpl +import com.sampoom.android.feature.auth.domain.repository.AuthRepository +import dagger.Binds +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import retrofit2.Retrofit +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +abstract class AuthBinModule { + @Binds @Singleton + abstract fun bindAuthRepository(impl: AuthRepositoryImpl): AuthRepository +} + +@Module +@InstallIn(SingletonComponent::class) +object AuthProvideModule { + @Provides @Singleton + fun provideAuthApi(retrofit: Retrofit): AuthApi = retrofit.create(AuthApi::class.java) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt new file mode 100644 index 0000000..b9e6e4b --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt @@ -0,0 +1,8 @@ +package com.sampoom.android.feature.auth.domain.model + +data class User( + val id: String, + val name: String, + val email: String, + val token: String +) diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt new file mode 100644 index 0000000..f5fccd8 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt @@ -0,0 +1,9 @@ +package com.sampoom.android.feature.auth.domain.repository + +import com.sampoom.android.feature.auth.domain.model.User + +interface AuthRepository { + suspend fun signIn(email: String, password: String): User + suspend fun signOut() + fun isSignedIn(): Boolean +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignInUseCase.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignInUseCase.kt new file mode 100644 index 0000000..630b4e2 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignInUseCase.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.auth.domain.usecase + +import com.sampoom.android.feature.auth.domain.model.User +import com.sampoom.android.feature.auth.domain.repository.AuthRepository +import javax.inject.Inject + +class SignInUseCase @Inject constructor( + private val repository: AuthRepository +) { + suspend operator fun invoke(email: String, password: String): User = repository.signIn(email, password) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt new file mode 100644 index 0000000..3cd6f1a --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt @@ -0,0 +1,63 @@ +package com.sampoom.android.feature.auth.ui + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.unit.dp +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel + +@Composable +fun LoginScreen( + onSuccess: () -> Unit, + viewModel: LoginViewModel = hiltViewModel() +) { + val state by viewModel.state.collectAsState() + + if (state.success) onSuccess() + + Column( + Modifier + .fillMaxSize() + .padding(24.dp) + ) { + Text("로그인", style = MaterialTheme.typography.headlineMedium) + Spacer(Modifier.height(16.dp)) + OutlinedTextField( + value = state.email, + onValueChange = { viewModel.onEvent(LoginUiEvent.EmailChanged(it)) }, + label = { Text("Email") }, + modifier = Modifier.fillMaxWidth() + ) + Spacer(Modifier.height(8.dp)) + OutlinedTextField( + value = state.password, + onValueChange = { viewModel.onEvent(LoginUiEvent.PasswordChanged(it)) }, + label = { Text("Password") }, + visualTransformation = PasswordVisualTransformation(), + modifier = Modifier.fillMaxWidth() + ) + Spacer(Modifier.height(16.dp)) + Button( + onClick = { viewModel.onEvent(LoginUiEvent.Submit) }, + enabled = !state.loading, + modifier = Modifier.fillMaxWidth() + ) { Text(if (state.loading) "로그인 중..." else "로그인") } + + state.error?.let { + Spacer(Modifier.height(8.dp)) + Text(it, color = MaterialTheme.colorScheme.error) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiEvent.kt new file mode 100644 index 0000000..ea2af9a --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiEvent.kt @@ -0,0 +1,7 @@ +package com.sampoom.android.feature.auth.ui + +sealed interface LoginUiEvent { + data class EmailChanged(val email: String) : LoginUiEvent + data class PasswordChanged(val password: String) : LoginUiEvent + data object Submit: LoginUiEvent +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiState.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiState.kt new file mode 100644 index 0000000..dd36855 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiState.kt @@ -0,0 +1,9 @@ +package com.sampoom.android.feature.auth.ui + +data class LoginUiState( + val email: String = "", + val password: String = "", + val loading: Boolean = false, + val error: String? = null, + val success: Boolean = false +) diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt new file mode 100644 index 0000000..c92c743 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt @@ -0,0 +1,35 @@ +package com.sampoom.android.feature.auth.ui + +import android.util.Log +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.sampoom.android.feature.auth.domain.usecase.SignInUseCase +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class LoginViewModel @Inject constructor( + private val singIn: SignInUseCase +) : ViewModel() { + private val _state = MutableStateFlow(LoginUiState()) + val state: StateFlow = _state + + fun onEvent(e: LoginUiEvent) = when (e) { + is LoginUiEvent.EmailChanged -> _state.value = _state.value.copy(email = e.email) + is LoginUiEvent.PasswordChanged -> _state.value = _state.value.copy(password = e.password) + LoginUiEvent.Submit -> submit() + } + + private fun submit() = viewModelScope.launch { + val s = _state.value + _state.update { it.copy(loading = true, error = null) } + runCatching { singIn(s.email, s.password) } + .onSuccess { _state.update { it.copy(loading = false, success = true) } } + .onFailure { _state.update { it.copy(loading = false, error = it.error) } } + Log.d("LoginViewModel", "submit: ${_state.value}") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/data/remote/api/.gitkeep b/app/src/main/java/com/sampoom/android/feature/sample/data/local/database/.gitkeep similarity index 100% rename from app/src/main/java/com/sampoom/android/data/remote/api/.gitkeep rename to app/src/main/java/com/sampoom/android/feature/sample/data/local/database/.gitkeep diff --git a/app/src/main/java/com/sampoom/android/data/remote/dto/.gitkeep b/app/src/main/java/com/sampoom/android/feature/sample/data/local/preferences/.gitkeep similarity index 100% rename from app/src/main/java/com/sampoom/android/data/remote/dto/.gitkeep rename to app/src/main/java/com/sampoom/android/feature/sample/data/local/preferences/.gitkeep diff --git a/app/src/main/java/com/sampoom/android/data/repository/.gitkeep b/app/src/main/java/com/sampoom/android/feature/sample/data/mapper/.gitkeep similarity index 100% rename from app/src/main/java/com/sampoom/android/data/repository/.gitkeep rename to app/src/main/java/com/sampoom/android/feature/sample/data/mapper/.gitkeep diff --git a/app/src/main/java/com/sampoom/android/domain/model/.gitkeep b/app/src/main/java/com/sampoom/android/feature/sample/data/remote/api/.gitkeep similarity index 100% rename from app/src/main/java/com/sampoom/android/domain/model/.gitkeep rename to app/src/main/java/com/sampoom/android/feature/sample/data/remote/api/.gitkeep diff --git a/app/src/main/java/com/sampoom/android/domain/repository/.gitkeep b/app/src/main/java/com/sampoom/android/feature/sample/data/remote/dto/.gitkeep similarity index 100% rename from app/src/main/java/com/sampoom/android/domain/repository/.gitkeep rename to app/src/main/java/com/sampoom/android/feature/sample/data/remote/dto/.gitkeep diff --git a/app/src/main/java/com/sampoom/android/domain/usecase/.gitkeep b/app/src/main/java/com/sampoom/android/feature/sample/data/repository/.gitkeep similarity index 100% rename from app/src/main/java/com/sampoom/android/domain/usecase/.gitkeep rename to app/src/main/java/com/sampoom/android/feature/sample/data/repository/.gitkeep diff --git a/app/src/main/java/com/sampoom/android/ui/component/.gitkeep b/app/src/main/java/com/sampoom/android/feature/sample/di/.gitkeep similarity index 100% rename from app/src/main/java/com/sampoom/android/ui/component/.gitkeep rename to app/src/main/java/com/sampoom/android/feature/sample/di/.gitkeep diff --git a/app/src/main/java/com/sampoom/android/ui/navigation/.gitkeep b/app/src/main/java/com/sampoom/android/feature/sample/domain/model/.gitkeep similarity index 100% rename from app/src/main/java/com/sampoom/android/ui/navigation/.gitkeep rename to app/src/main/java/com/sampoom/android/feature/sample/domain/model/.gitkeep diff --git a/app/src/main/java/com/sampoom/android/ui/screen/.gitkeep b/app/src/main/java/com/sampoom/android/feature/sample/domain/repository/.gitkeep similarity index 100% rename from app/src/main/java/com/sampoom/android/ui/screen/.gitkeep rename to app/src/main/java/com/sampoom/android/feature/sample/domain/repository/.gitkeep diff --git a/app/src/main/java/com/sampoom/android/feature/sample/domain/usecase/.gitkeep b/app/src/main/java/com/sampoom/android/feature/sample/domain/usecase/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/sample/ui/.gitkeep b/app/src/main/java/com/sampoom/android/feature/sample/ui/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/build.gradle.kts b/build.gradle.kts index 952b930..233e11b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,4 +3,6 @@ plugins { alias(libs.plugins.android.application) apply false alias(libs.plugins.kotlin.android) apply false alias(libs.plugins.kotlin.compose) apply false + id("com.google.devtools.ksp") version "2.2.20-2.0.3" apply false + id("com.google.dagger.hilt.android") version "2.57.2" apply false } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1c3d1c4..081086d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,16 +1,26 @@ [versions] agp = "8.13.0" -kotlin = "2.0.21" +hiltAndroid = "2.57.2" +hiltNavigationCompose = "1.3.0" +kotlin = "2.2.20" coreKtx = "1.17.0" junit = "4.13.2" junitVersion = "1.3.0" espressoCore = "3.7.0" lifecycleRuntimeKtx = "2.9.4" activityCompose = "1.11.0" -composeBom = "2024.09.00" +composeBom = "2025.09.01" +navigationCompose = "2.9.5" +retrofitVersion = "3.0.0" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +androidx-hilt-lifecycle-viewmodel-compose = { module = "androidx.hilt:hilt-lifecycle-viewmodel-compose", version.ref = "hiltNavigationCompose" } +androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hiltNavigationCompose" } +androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" } +converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofitVersion" } +hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" } +hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hiltAndroid" } junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } @@ -24,6 +34,7 @@ androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "u androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" } +retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofitVersion" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } From 2ac423356cf9e01f29404088e9a3ec4d226fbebc Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Tue, 30 Sep 2025 14:36:51 +0900 Subject: [PATCH 03/88] =?UTF-8?q?[FEAT]=20Part=20=EC=83=98=ED=94=8C=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=97=B0?= =?UTF-8?q?=EB=8F=99=20=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 3 + .../android/app/navigation/AppNavHost.kt | 5 +- .../android/core/network/ApiResponse.kt | 8 ++ .../android/core/network/NetworkModule.kt | 2 +- .../feature/part/data/local/database/.gitkeep | 0 .../part/data/local/preferences/.gitkeep | 0 .../feature/part/data/mapper/PartMappers.kt | 6 + .../feature/part/data/remote/api/PartApi.kt | 10 ++ .../feature/part/data/remote/dto/PartDto.kt | 7 ++ .../data/repository/PartRepositoryImpl.kt | 17 +++ .../android/feature/part/di/PartModules.kt | 26 ++++ .../android/feature/part/domain/model/Part.kt | 7 ++ .../feature/part/domain/model/PartList.kt | 11 ++ .../part/domain/repository/PartRepository.kt | 7 ++ .../part/domain/usecase/GetPartUseCase.kt | 11 ++ .../android/feature/part/ui/PartScreen.kt | 118 ++++++++++++++++++ .../android/feature/part/ui/PartUiEvent.kt | 4 + .../android/feature/part/ui/PartUiState.kt | 10 ++ .../android/feature/part/ui/PartViewModel.kt | 47 +++++++ 19 files changed, 297 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/core/network/ApiResponse.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/data/local/database/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/part/data/local/preferences/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/PartDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/di/PartModules.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/domain/model/Part.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/domain/model/PartList.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetPartUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/ui/PartUiEvent.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 647ee15..a025302 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,8 @@ + + ( + val status: Int, + val success: Boolean, + val message: String, + val data: T +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt index 2708b90..4884ee1 100644 --- a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt +++ b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt @@ -17,7 +17,7 @@ object NetworkModule { @Provides @Singleton fun provideRetrofit(client: OkHttpClient): Retrofit = Retrofit.Builder() - .baseUrl("http://10.0.2.2:8080/") + .baseUrl("http://10.0.2.2:8080/api/") .client(client) .addConverterFactory(GsonConverterFactory.create()) .build() diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/local/database/.gitkeep b/app/src/main/java/com/sampoom/android/feature/part/data/local/database/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/local/preferences/.gitkeep b/app/src/main/java/com/sampoom/android/feature/part/data/local/preferences/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt b/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt new file mode 100644 index 0000000..0c06f6a --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt @@ -0,0 +1,6 @@ +package com.sampoom.android.feature.part.data.mapper + +import com.sampoom.android.feature.part.data.remote.dto.PartDto +import com.sampoom.android.feature.part.domain.model.Part + +fun PartDto.toModel(): Part = Part(id, name, count) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt b/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt new file mode 100644 index 0000000..e5a4998 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.part.data.remote.api + +import com.sampoom.android.core.network.ApiResponse +import com.sampoom.android.feature.part.data.remote.dto.PartDto +import retrofit2.http.GET + +interface PartApi { + @GET("part") + suspend fun getPartList(): ApiResponse> +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/PartDto.kt b/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/PartDto.kt new file mode 100644 index 0000000..d7973be --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/PartDto.kt @@ -0,0 +1,7 @@ +package com.sampoom.android.feature.part.data.remote.dto + +data class PartDto( + val id: Int, + val name: String, + val count: Int +) diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt new file mode 100644 index 0000000..663cd0a --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt @@ -0,0 +1,17 @@ +package com.sampoom.android.feature.part.data.repository + +import com.sampoom.android.feature.part.data.mapper.toModel +import com.sampoom.android.feature.part.data.remote.api.PartApi +import com.sampoom.android.feature.part.domain.model.PartList +import com.sampoom.android.feature.part.domain.repository.PartRepository +import javax.inject.Inject + +class PartRepositoryImpl @Inject constructor( + private val api: PartApi +) : PartRepository { + override suspend fun getPartList(): PartList { + val response = api.getPartList() + val partItems = response.data.map { it.toModel() } + return PartList(items = partItems) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/di/PartModules.kt b/app/src/main/java/com/sampoom/android/feature/part/di/PartModules.kt new file mode 100644 index 0000000..4d1a08a --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/di/PartModules.kt @@ -0,0 +1,26 @@ +package com.sampoom.android.feature.part.di + +import com.sampoom.android.feature.part.data.remote.api.PartApi +import com.sampoom.android.feature.part.data.repository.PartRepositoryImpl +import com.sampoom.android.feature.part.domain.repository.PartRepository +import dagger.Binds +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import retrofit2.Retrofit +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +abstract class PartBinModule { + @Binds @Singleton + abstract fun bindPartRepository(impl: PartRepositoryImpl): PartRepository +} + +@Module +@InstallIn(SingletonComponent::class) +object PartModule { + @Provides @Singleton + fun providePartApi(retrofit: Retrofit): PartApi = retrofit.create(PartApi::class.java) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/model/Part.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/model/Part.kt new file mode 100644 index 0000000..9c1bb23 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/model/Part.kt @@ -0,0 +1,7 @@ +package com.sampoom.android.feature.part.domain.model + +data class Part( + val id: Int, + val name: String, + val count: Int +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/model/PartList.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/model/PartList.kt new file mode 100644 index 0000000..74b0891 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/model/PartList.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.part.domain.model + +data class PartList( + val items: List, + val totalCount: Int = items.size, + val isEmpty: Boolean = items.isEmpty() +) { + companion object Companion { + fun empty() = PartList(emptyList()) + } +} diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt new file mode 100644 index 0000000..06c46d5 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt @@ -0,0 +1,7 @@ +package com.sampoom.android.feature.part.domain.repository + +import com.sampoom.android.feature.part.domain.model.PartList + +interface PartRepository { + suspend fun getPartList(): PartList +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetPartUseCase.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetPartUseCase.kt new file mode 100644 index 0000000..9fdd394 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetPartUseCase.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.part.domain.usecase + +import com.sampoom.android.feature.part.domain.model.PartList +import com.sampoom.android.feature.part.domain.repository.PartRepository +import javax.inject.Inject + +class GetPartUseCase @Inject constructor( + private val repository: PartRepository +) { + suspend operator fun invoke(): PartList = repository.getPartList() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt new file mode 100644 index 0000000..f1fdce1 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -0,0 +1,118 @@ +package com.sampoom.android.feature.part.ui + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle + +@Composable +fun PartScreen( + viewModel: PartViewModel = hiltViewModel() +) { + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + + Column( + modifier = Modifier + .fillMaxSize() + .padding(16.dp) + ) { + Text( + text = "인벤토리", + style = MaterialTheme.typography.headlineMedium, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(bottom = 16.dp) + ) + + when { + uiState.loading -> { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + + uiState.error != null -> { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Text( + text = "오류가 발생했습니다: ${uiState.error}", + color = MaterialTheme.colorScheme.error + ) + Spacer(modifier = Modifier.height(16.dp)) + Button(onClick = { viewModel.refreshPart() }) { + Text("다시 시도") + } + } + } + + uiState.partList.isEmpty() -> { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Text("인벤토리가 비어있습니다") + } + } + + else -> { + LazyColumn( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + items(uiState.partList) { inventory -> + PartItemCard(part = inventory) + } + } + } + } + } +} + +@Composable +private fun PartItemCard( + part: com.sampoom.android.feature.part.domain.model.Part +) { + Card( + modifier = Modifier.fillMaxWidth(), + elevation = CardDefaults.cardElevation(defaultElevation = 4.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Column { + Text( + text = part.name, + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.Bold + ) + Text( + text = "ID: ${part.id}", + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + + Text( + text = "${part.count}개", + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold, + color = MaterialTheme.colorScheme.primary + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiEvent.kt new file mode 100644 index 0000000..e6a49d0 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiEvent.kt @@ -0,0 +1,4 @@ +package com.sampoom.android.feature.part.ui + +sealed interface PartUiEvent { +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt new file mode 100644 index 0000000..d343dbe --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.part.ui + +import com.sampoom.android.feature.part.domain.model.Part + +data class PartUiState( + val loading: Boolean = false, + val error: String? = null, + val success: Boolean = false, + val partList: List = emptyList() +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt new file mode 100644 index 0000000..c979584 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt @@ -0,0 +1,47 @@ +package com.sampoom.android.feature.part.ui + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.sampoom.android.feature.part.domain.usecase.GetPartUseCase +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class PartViewModel @Inject constructor( + private val getPartUseCase: GetPartUseCase +) : ViewModel() { + + private val _uiState = MutableStateFlow(PartUiState()) + val uiState: StateFlow = _uiState.asStateFlow() + + init { + loadPart() + } + + private fun loadPart() { + viewModelScope.launch { + _uiState.value = _uiState.value.copy(loading = true, error = null) + try { + val partListResult = getPartUseCase() + _uiState.value = _uiState.value.copy( + loading = false, + partList = partListResult.items, + success = true + ) + } catch (e: Exception) { + _uiState.value = _uiState.value.copy( + loading = false, + error = e.message ?: "Unknown error occurred" + ) + } + } + } + + fun refreshPart() { + loadPart() + } +} \ No newline at end of file From baa6ea5b7b9df26cce7de62fd4a0d5ebb0cd4386 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Tue, 30 Sep 2025 14:41:13 +0900 Subject: [PATCH 04/88] =?UTF-8?q?[FIX]=20NavHost=20=EC=9D=B4=EB=8F=99=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/sampoom/android/app/navigation/AppNavHost.kt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 4a74b4c..6f925ba 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -5,19 +5,23 @@ import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import com.sampoom.android.feature.auth.ui.LoginScreen -import com.sampoom.android.feature.part.ui.InventoryScreen +import com.sampoom.android.feature.part.ui.PartScreen const val ROUTE_LOGIN = "login" -const val ROUTE_INVENTORY = "inventory" +const val ROUTE_PART = "part" @Composable fun AppNavHost(navController: NavHostController) { - NavHost(navController, startDestination = ROUTE_INVENTORY) { + NavHost(navController, startDestination = ROUTE_PART) { + + // 로그인 화면 composable(ROUTE_LOGIN) { LoginScreen(onSuccess = { // navController.navigate("main") { // popUpTo(ROUTE_LOGIN) { inclusive = true } // 로그인 화면 스택 제거 // } }) } - composable(ROUTE_INVENTORY) { InventoryScreen() } + + // 부품 조회 화면 + composable(ROUTE_PART) { PartScreen() } } } \ No newline at end of file From ac3dedab0b3c1e75404486759c03ed376802b32e Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Thu, 2 Oct 2025 21:03:16 +0900 Subject: [PATCH 05/88] =?UTF-8?q?#5=20[FEAT]=20Navigation=20Bar=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20Route=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sampoom/android/MainActivity.kt | 11 +- .../com/sampoom/android/app/di/AppModule.kt | 16 -- .../android/app/navigation/AppNavHost.kt | 166 ++++++++++++++++-- .../sampoom/android/core/common/AppResult.kt | 12 -- .../android/core/common/DispatcherProvider.kt | 17 -- .../android/feature/auth/ui/LoginScreen.kt | 65 +++---- app/src/main/res/drawable/outline_home_24.xml | 5 + 7 files changed, 194 insertions(+), 98 deletions(-) delete mode 100644 app/src/main/java/com/sampoom/android/app/di/AppModule.kt delete mode 100644 app/src/main/java/com/sampoom/android/core/common/AppResult.kt delete mode 100644 app/src/main/java/com/sampoom/android/core/common/DispatcherProvider.kt create mode 100644 app/src/main/res/drawable/outline_home_24.xml diff --git a/app/src/main/java/com/sampoom/android/MainActivity.kt b/app/src/main/java/com/sampoom/android/MainActivity.kt index 8823d78..ca423aa 100644 --- a/app/src/main/java/com/sampoom/android/MainActivity.kt +++ b/app/src/main/java/com/sampoom/android/MainActivity.kt @@ -4,14 +4,6 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.navigation.compose.rememberNavController import com.sampoom.android.app.navigation.AppNavHost import com.sampoom.android.core.ui.theme.SampoomManagementTheme import dagger.hilt.android.AndroidEntryPoint @@ -23,8 +15,7 @@ class MainActivity : ComponentActivity() { enableEdgeToEdge() setContent { SampoomManagementTheme { - val navController = rememberNavController() - AppNavHost(navController) + AppNavHost() } } } diff --git a/app/src/main/java/com/sampoom/android/app/di/AppModule.kt b/app/src/main/java/com/sampoom/android/app/di/AppModule.kt deleted file mode 100644 index f49417e..0000000 --- a/app/src/main/java/com/sampoom/android/app/di/AppModule.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.sampoom.android.app.di - -import com.sampoom.android.core.common.DispatcherProvider -import com.sampoom.android.core.common.DispatcherProviderImpl -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -abstract class AppModule { - @Binds @Singleton - abstract fun bindDispatchers(impl: DispatcherProviderImpl): DispatcherProvider -} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 6f925ba..cc1de7f 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -1,27 +1,169 @@ package com.sampoom.android.app.navigation +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.Icon +import androidx.compose.material3.NavigationBar +import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable +import androidx.navigation.compose.currentBackStackEntryAsState +import androidx.navigation.compose.rememberNavController +import com.sampoom.android.R import com.sampoom.android.feature.auth.ui.LoginScreen import com.sampoom.android.feature.part.ui.PartScreen const val ROUTE_LOGIN = "login" +const val ROUTE_HOME = "home" + +// Main Screen const val ROUTE_PART = "part" +const val ROUTE_INVENTORY = "inventory" +const val ROUTE_PROFILE = "profile" +const val ROUTE_SETTINGS = "settings" + +// Detail Screen +const val ROUTE_DETAIL = "detail" + +sealed class BottomNavItem( + val route: String, + val title: String, + val icon: Int +) { + object Part : BottomNavItem(ROUTE_PART, "Part", R.drawable.outline_home_24) + object Inventory : BottomNavItem(ROUTE_INVENTORY, "인벤토리", R.drawable.outline_home_24) + object Profile : BottomNavItem(ROUTE_PROFILE, "프로필", R.drawable.outline_home_24) + object Settings : BottomNavItem(ROUTE_SETTINGS, "설정", R.drawable.outline_home_24) +} + +@Composable +fun AppNavHost() { + val navController = rememberNavController() + + // TODO: 임시 로그인 상태 확인 -> AuthRepository에서 확인하도록 변경 + val isLoggedIn = true + + NavHost( + navController = navController, + startDestination = if (isLoggedIn) ROUTE_HOME else ROUTE_LOGIN + ) { + composable(ROUTE_LOGIN) { + LoginScreen(onSuccess = { + navController.navigate(ROUTE_HOME) { + popUpTo(ROUTE_LOGIN) { inclusive = true } // 로그인 화면 스택 제거 + } + }) + } + composable(ROUTE_HOME) { MainScreen(navController) } + composable(ROUTE_DETAIL) { DetailScreen() } + } +} + +@Composable +fun MainScreen( + parentNavController: NavHostController +) { + val navController = rememberNavController() + + Scaffold( + bottomBar = { + BottomNavigationBar(navController) + } + ) { innerPadding -> + NavHost( + navController = navController, + startDestination = ROUTE_PART, + modifier = Modifier.background(Color.Green).padding(innerPadding) + ) { + composable(ROUTE_PART) { PartScreen() } + composable(ROUTE_INVENTORY) { InventoryScreen() } + composable(ROUTE_PROFILE) { ProfileScreen() } + composable(ROUTE_SETTINGS) { SettingsScreen(parentNavController) } + } + } +} + +@Composable +fun BottomNavigationBar(navController: NavHostController) { + val bottomNavItems = listOf( + BottomNavItem.Part, + BottomNavItem.Inventory, + BottomNavItem.Profile, + BottomNavItem.Settings, + ) + + NavigationBar { + bottomNavItems.forEach { item -> + val navBackStackEntry by navController.currentBackStackEntryAsState() + val currentDestination = navBackStackEntry?.destination + + NavigationBarItem( + icon = { Icon(painterResource(id = item.icon), contentDescription = item.title) }, + label = { Text(item.title) }, + selected = currentDestination?.route == item.route, + onClick = { + navController.navigate(item.route) { + popUpTo(navController.graph.startDestinationId) { + saveState = true + } + launchSingleTop = true + restoreState = true + } + } + ) + } + } +} + +// 임시 화면들 (실제로는 각각의 feature 모듈에서 구현) +@Composable +private fun InventoryScreen() { + // 홈 화면 구현 + Text("인벤토리 화면") +} + +@Composable +private fun ProfileScreen() { + // 프로필 화면 구현 + Text("프로필 화면") +} + +@Composable +private fun SettingsScreen( + navController: NavHostController +) { + Column( + modifier = Modifier.fillMaxSize() + ) { + // 설정 화면 구현 + Text("설정 화면") + Button( + onClick = { navController.navigate(ROUTE_DETAIL) } + ) { + Text("상세 화면") + } + } +} @Composable -fun AppNavHost(navController: NavHostController) { - NavHost(navController, startDestination = ROUTE_PART) { - - // 로그인 화면 - composable(ROUTE_LOGIN) { LoginScreen(onSuccess = { -// navController.navigate("main") { -// popUpTo(ROUTE_LOGIN) { inclusive = true } // 로그인 화면 스택 제거 -// } - }) } - - // 부품 조회 화면 - composable(ROUTE_PART) { PartScreen() } +private fun DetailScreen() { + // 설정 화면 구현 + Scaffold { innerPadding -> + Box(Modifier.fillMaxSize().background(Color.Red).padding(innerPadding) + ) { + Text("상세 화면") + } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/common/AppResult.kt b/app/src/main/java/com/sampoom/android/core/common/AppResult.kt deleted file mode 100644 index f05e748..0000000 --- a/app/src/main/java/com/sampoom/android/core/common/AppResult.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.sampoom.android.core.common - -sealed class AppResult { - data class Success(val value: T) : AppResult() - data class Error(val throwable: Throwable) : AppResult() -} - -inline fun appRunCatching(block: () -> T): AppResult = try { - AppResult.Success(block()) -} catch (t: Throwable) { - AppResult.Error(t) -} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/common/DispatcherProvider.kt b/app/src/main/java/com/sampoom/android/core/common/DispatcherProvider.kt deleted file mode 100644 index d5ae202..0000000 --- a/app/src/main/java/com/sampoom/android/core/common/DispatcherProvider.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.sampoom.android.core.common - -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.Dispatchers -import javax.inject.Inject - -interface DispatcherProvider { - val io: CoroutineDispatcher - val main: CoroutineDispatcher - val default: CoroutineDispatcher -} - -class DispatcherProviderImpl @Inject constructor() : DispatcherProvider { - override val io = Dispatchers.IO - override val main = Dispatchers.Main - override val default = Dispatchers.Default -} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt index 3cd6f1a..e508ffb 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt @@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.Button import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -26,38 +27,40 @@ fun LoginScreen( val state by viewModel.state.collectAsState() if (state.success) onSuccess() - - Column( - Modifier - .fillMaxSize() - .padding(24.dp) - ) { - Text("로그인", style = MaterialTheme.typography.headlineMedium) - Spacer(Modifier.height(16.dp)) - OutlinedTextField( - value = state.email, - onValueChange = { viewModel.onEvent(LoginUiEvent.EmailChanged(it)) }, - label = { Text("Email") }, - modifier = Modifier.fillMaxWidth() - ) - Spacer(Modifier.height(8.dp)) - OutlinedTextField( - value = state.password, - onValueChange = { viewModel.onEvent(LoginUiEvent.PasswordChanged(it)) }, - label = { Text("Password") }, - visualTransformation = PasswordVisualTransformation(), - modifier = Modifier.fillMaxWidth() - ) - Spacer(Modifier.height(16.dp)) - Button( - onClick = { viewModel.onEvent(LoginUiEvent.Submit) }, - enabled = !state.loading, - modifier = Modifier.fillMaxWidth() - ) { Text(if (state.loading) "로그인 중..." else "로그인") } - - state.error?.let { + Scaffold { innerPadding -> + Column( + Modifier + .fillMaxSize() + .padding(innerPadding) + .padding(24.dp) + ) { + Text("로그인", style = MaterialTheme.typography.headlineMedium) + Spacer(Modifier.height(16.dp)) + OutlinedTextField( + value = state.email, + onValueChange = { viewModel.onEvent(LoginUiEvent.EmailChanged(it)) }, + label = { Text("Email") }, + modifier = Modifier.fillMaxWidth() + ) Spacer(Modifier.height(8.dp)) - Text(it, color = MaterialTheme.colorScheme.error) + OutlinedTextField( + value = state.password, + onValueChange = { viewModel.onEvent(LoginUiEvent.PasswordChanged(it)) }, + label = { Text("Password") }, + visualTransformation = PasswordVisualTransformation(), + modifier = Modifier.fillMaxWidth() + ) + Spacer(Modifier.height(16.dp)) + Button( + onClick = { viewModel.onEvent(LoginUiEvent.Submit) }, + enabled = !state.loading, + modifier = Modifier.fillMaxWidth() + ) { Text(if (state.loading) "로그인 중..." else "로그인") } + + state.error?.let { + Spacer(Modifier.height(8.dp)) + Text(it, color = MaterialTheme.colorScheme.error) + } } } } \ No newline at end of file diff --git a/app/src/main/res/drawable/outline_home_24.xml b/app/src/main/res/drawable/outline_home_24.xml new file mode 100644 index 0000000..ef91752 --- /dev/null +++ b/app/src/main/res/drawable/outline_home_24.xml @@ -0,0 +1,5 @@ + + + + + From 9525a152426eb67b57b514ea8eef390ffb4d8fa9 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Thu, 2 Oct 2025 22:00:51 +0900 Subject: [PATCH 06/88] =?UTF-8?q?#5=20[FEAT]=20=EC=95=B1=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=EC=BD=98=20=EC=B6=94=EA=B0=80,=20=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EB=A7=81=20=EB=A6=AC=EC=86=8C=EC=8A=A4=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 1 + app/src/main/AndroidManifest.xml | 5 + app/src/main/ic_launcher-playstore.png | Bin 0 -> 10324 bytes .../android/app/navigation/AppNavHost.kt | 15 +- .../android/feature/auth/ui/LoginScreen.kt | 10 +- .../android/feature/part/ui/PartScreen.kt | 10 +- .../drawable-night/ic_launcher_background.xml | 74 ++++++ .../drawable-night/ic_launcher_foreground.xml | 20 ++ .../res/drawable/ic_launcher_background.xml | 236 ++++++------------ .../res/drawable/ic_launcher_foreground.xml | 42 ++-- .../res/mipmap-anydpi-v26/ic_launcher.xml | 6 +- .../mipmap-anydpi-v26/ic_launcher_round.xml | 6 +- app/src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 1404 -> 1150 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 2898 -> 2328 bytes app/src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 982 -> 816 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 1772 -> 1582 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 1900 -> 1306 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 3918 -> 3168 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 2884 -> 1790 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 5914 -> 4858 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 3844 -> 2270 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 7778 -> 6698 bytes app/src/main/res/values-night/colors.xml | 10 + .../values-night/ic_launcher_background.xml | 4 + app/src/main/res/values-night/themes.xml | 6 + .../res/values/ic_launcher_background.xml | 4 + app/src/main/res/values/strings.xml | 23 +- app/src/main/res/values/themes.xml | 7 +- gradle/libs.versions.toml | 2 + 29 files changed, 264 insertions(+), 217 deletions(-) create mode 100644 app/src/main/ic_launcher-playstore.png create mode 100644 app/src/main/res/drawable-night/ic_launcher_background.xml create mode 100644 app/src/main/res/drawable-night/ic_launcher_foreground.xml create mode 100644 app/src/main/res/values-night/colors.xml create mode 100644 app/src/main/res/values-night/ic_launcher_background.xml create mode 100644 app/src/main/res/values-night/themes.xml create mode 100644 app/src/main/res/values/ic_launcher_background.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 396151f..6dfe38b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -78,6 +78,7 @@ dependencies { implementation(libs.retrofit) implementation(libs.converter.gson) + implementation(libs.androidx.core.splashscreen) implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.activity.compose) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a025302..780ee42 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,6 +15,11 @@ android:supportsRtl="true" android:usesCleartextTraffic="true" android:theme="@style/Theme.SampoomManagement"> + + + b6?O_znSlx?|gI4%=yikzj#URTeqri)l*N^ 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 B + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable-night/ic_launcher_foreground.xml b/app/src/main/res/drawable-night/ic_launcher_foreground.xml new file mode 100644 index 0000000..a41ec78 --- /dev/null +++ b/app/src/main/res/drawable-night/ic_launcher_foreground.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml index 07d5da9..ca3826a 100644 --- a/app/src/main/res/drawable/ic_launcher_background.xml +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -1,170 +1,74 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + xmlns:android="http://schemas.android.com/apk/res/android"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml index 2b068d1..1c28491 100644 --- a/app/src/main/res/drawable/ic_launcher_foreground.xml +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -1,30 +1,20 @@ - - - - - - - - + android:viewportWidth="512" + android:viewportHeight="512"> + - \ No newline at end of file + android:pathData="M0,0h512v512h-512z" + android:fillColor="#ffffff"/> + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index 6f3b755..ef49c99 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,6 +1,6 @@ - - - + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index 6f3b755..ef49c99 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,6 +1,6 @@ - - - + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp index c209e78ecd372343283f4157dcfd918ec5165bb3..7f4c78afc9407e062ff6118e0cda3ff530f3fcc6 100644 GIT binary patch literal 1150 zcmV-^1cCcfNk&F?1ONb6MM6+kP&iC#1ONapN5Byfl~BX}$&e()*|u%lwr$(~wG)ZYTK4K`64LXtFTD@jyprPOAr{ZhN7 z_E2kfB1B0WNh;MW^&BQ{fIlAgT&PJ&p;7@+*h`p@A1UL7-atsD0+A~6Sq&5N!%~L* zcvx$Vs)RsLY)clyPk;@Mlo$x}9kV1(kPWWlVj#|PB1+Vue&Sx)6y?Z!@qGkI3I z{jZi&WXz(;Q)Ulg=3vzLIem5vTjEP#p38GQiRi0r0@coXH3HT6Ri#d6RI?|Z6z1U^ z0U&x3i$OJgOpQQ|pTo?7m`-O@!*|QOZEa?-l3#e6qX3TK2VD1P_;^0xS9XCZw@~X_ zN)23>Q^Z86&ZoGD6ee>Dz!{{#d@8`X%q4|l5aku--qDB&~u0b4r!&hn9Csnr!44 z0P#~m6NuSeE4NTlmT6&5jAxD*yI|@Bf1EtLv{#)U!Y%K4QVcvSV+mU8i2!^O)6rV% z72sLYr$!*$?1?9ZxhH4gy6zbOd@vE$buVE$sM_3E+RJotzZMTn+5-q5%|uXjxUjvE z>6R9)Z&}^K1kA4lo2bPJ+=2PANGFOZqs*cK!YjH2Vwl&UggdhnJeU!svxgLd*vMfI zi6ZdS=0q%K;pYMLWn{zLotv=S1%Hj!-NEx4faP@j+zy{j76#k^z;X))p8#+t@QmUs znE6YtLZm0R;yBJNoD4qpu$+agB*4d*9nL*`jzI}oxUQSZOGvPli#d#|v0|<^F!k{U z5^UjofXhkLy+^-8MwY_c$r?=Ws*D*|`(Bb773l}M&xo-DwJKy3`nQSlhA=5k&p1XuQB zF9lo!I1J!6%p!}J%4~d?JWVV1?{C2S+{NeM>d&D7C-EZIFEa%b%a_14fWrVp52h;y z+@8ZRJ(||{BU#YwDj zYbV`d7)fFQ7CN&t-#W)a$PfwpDWsnb5HFR8lnOuudON%aabps?iDkaPMAQ+X!6Hz7 z&cbS6dH4x}K0rQ8d_QFwRBMVsO8h}t&1mqL3}YgiZcL;#ktR)~HIXJF z(nMMlY0^Ym6KT>jj1G+V*wQc_y-Ne5f5yr2h%@8TWh?)bSK`O z^Z@d={gn7J{iyxL_y_%J|L>ep{dUxUP8a{byupH&!UNR*OutO~0{*T4q5R6@ApLF! z5{w?Z150gC7#>(VHFJZ-^6O@PYp{t!jH(_Z*nzTK4 zkc{fLE4Q3|mA2`CWQ3{8;gxGizgM!zccbdQoOLZc8hThi-IhN90RFT|zlxh3Ty&VG z?Fe{#9RrRnxzsu|Lg2ddugg7k%>0JeD+{XZ7>Z~{=|M+sh1MF7~ zz>To~`~LVQe1nNoR-gEzkpe{Ak^7{{ZBk2i_<+`Bq<^GB!RYG+z)h;Y3+<{zlMUYd zrd*W4w&jZ0%kBuDZ1EW&KLpyR7r2=}fF2%0VwHM4pUs}ZI2egi#DRMYZPek*^H9YK zay4Iy3WXFG(F14xYsoDA|KXgGc5%2DhmQ1gFCkrgHBm!lXG8I5h*uf{rn48Z!_@ z4Bk6TJAB2CKYqPjiX&mWoW>OPFGd$wqroa($ne7EUK;#3VYkXaew%Kh^3OrMhtjYN?XEoY`tRPQsAkH-DSL^QqyN0>^ zmC>{#F14jz4GeW{pJoRpLFa_*GI{?T93^rX7SPQgT@LbLqpNA}<@2wH;q493)G=1Y z#-sCiRNX~qf3KgiFzB3I>4Z%AfS(3$`-aMIBU+6?gbgDb!)L~A)je+;fR0jWLL-Fu z4)P{c7{B4Hp91&%??2$v9iRSFnuckHUm}or9seH6 z>%NbT+5*@L5(I9j@06@(!{ZI?U0=pKn8uwIg&L{JV14+8s2hnvbRrU|hZCd}IJu7*;;ECgO%8_*W Kmw_-CKmY()leWbG diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp index b2dfe3d1ba5cf3ee31b3ecc1ced89044a1f3b7a9..09b2c83c74d4297559812d103bd65a3946061d37 100644 GIT binary patch literal 2328 zcmV+z3Fr1wNk&Ex2><|BMM6+kP&iBk2><{uN5Byf^@f7BZ6t?3?Cl;15itSYqltEW zQTa-1+jc{iv!c^Eif!ArZQHiZL)*4(+qTB`%=WITbNtDCu2%S+qP}nwr$(CZQFLk?R)V{{)4)W+s*BB{GQsjIk_G4dy}oUrXB%D z3;+U7&Q>vbvNhSZZQE|&-v0@JcvIG*T%MK%wXj8bD)_+Y+rCvxgmws#RHjzcnR?5}+Wb4uR3TC&3Jp}eY3@oFY zWL%O!O|@4X6%FHVBG+EO3duMmfdAb+92js1PL@TJr3fqG4cjg+NW-<5Gpe zB~Nd?!W{naDX+MRj2Z#;;4YF{X#IMLs&zP(X-m+=%5Mo9iw!wjxQVQz8`@2D9`4nn z97ROcaP95Qn^$BIv6=ul6I+OYs`h+|U0^f$km;sPVZgGh{do3&k>_hg1`$;vLWm^= zL`=^VPH$!+1r#->F7*bVO}WoaWK}d+6Qb6R0udFI0$g&+901!)OiauIu*D>hIY?+G z$~_@0iw&76Le-IZdS#A3A-?HRMBdNwHHbK#YXC(dqB8(FAuH80a8)kY(L%`mz$Md~ z#AYEx!PmBv%d?2J zavv}vOL+UCp;S=(CfIp|P}W)2 z!l?oP6`;y)E@OLJ{GMFwff9x(oGy&Tq>^l0c7(7tfbZ0}iLrg`Hn5jLXu3G0ojjnM#in_vIq~sge~DyS7L2Q8*P}vX;-r`*r#iyri876Y7=snU z9yUrZ28Lkg2t`I$KW%(GMg@QH9-A;(ya z0m8VJ%D;bMX^jNMciYx6?nc8YjK6+u1@qQL1&5-Gc57C( z>Y5iUB@?^ipHVUlVI4pbltv5V<;%GcwXc~10Zk-?*wDM0M8ytZ?qci4%_ezqyM|(M2V!xA@)d#b_|ELL9Dso=`NlBRg4R zBhfij%|Go8akv8*58&UOEvb+POzg&p+R<$y+U1rKgOZpODvFOyolcC`6 zECU*eGKMd5&I}N7n&HR~b(LXve#qs+5E2@xhF#BowVVMk6Lt(^;&H`$U)A!`!U;|D zPyb9jJEhp*dt%;4XwgPAjb`#In|h0M7ZxGbg;ioZPhq(+A&n))E#tG4cKH@!pTmSW zZM32y71Bsjl%i{{CC+o0q;yD4Yew8Q-CUlE#tEY&O!3x6+dr7XJOz3>W11JNyQ<_U z7AB05DCD<{t+uvcGz$mxbtbSR?sJx0+mr>3dPeYW&&K6VGnF^L*8#nqNi2wKk?1o& zRE21)=<#aOSTsBNQ<0dzA9g_h)P$zQkp%60y4c9`qH&XWG-)iJFFLZ_ITGCN$rQvh zHG2h({Thf1#u?A$d<%~1TMGytncqP5|paM zYZ6NnPc{_KzyIcPE89NUv?IhnHGtQ^R~yc8W7zs*7!PSnoQZFP{*qT%wcEuL9$)mA`nL`}L^WvhI`RDUAM;BGjPDE~ ybsEiLXq%qwUikDu;`;Z4pT2Pa&^C=aJ?B6zn{vh#Mi3{H$5ozqv1M~71#t%T$ZOO9 literal 2898 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 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp index 4f0f1d64e58ba64d180ce43ee13bf9a17835fbca..719851c50a0f63d863c7a79cc5102841b4b5ae29 100644 GIT binary patch literal 816 zcmV-01JC?YNk&E}0{{S5MM6+kP&iB*0{{RoFTe{BRY;<(&5)$%v2D++Y}+eyXWQJ_ zwr$(CZQE)qDN@7o~<0zj~dZQI5a z={M_@8yHhrPoD#~krXLjrek;mh6^stMZk>zxRAvFu-4yQK;+6?kLv;%ji?S5xfFNk zdSG6`40Fh()WITk?7|2D9p#J&%5hPh^{W3mqV~B=$Gv@M)Ljonp!ZrTTkWBo-0TK;) zTeJMZ_`u{J6aQ>G^u1{Fi3$G}zqmKBn9QUgf{fTyXgd@Sfc~X;m-lS@TDEh~q+f@& zcvoIEIT3Scf?^zr0E&*=x#v+wQVhesZ26aRc5eHD9|ep&WJC1>$jX(e)i)%oZmqrY zwT!Wf(O6rUbaY}gb|HyCI=XIrVE%^{_YjvqnD)v4X(OP(x-#`U%a|Vp>n=%^XC^{h zz{#Xik{%&7u=LxSs}r*8BT)&A+ss9Ao=|$?vs}8 zH~>mw5DhUVBiXo2bJB4fJr#nGg6-Uc&>2WNjygl_;T6`_1fDJr;T52R2g$Ycm7x4QcVoOgns==Rn9w8FX2W z0xXsdEMYSTILJAEBR3p|0E{ve!W*t^>SKJdr38VQ7k=wL>Ivgwgk8@V@7-Sp;gb#a50B<6a%di%TGWr#Sz- zPB+5yBJ%Gbk$C0Yf#YI;v`OZUYa*%sZW7@-*0^$pN~kN5aLe#@pj#PEn6b& u=ZD!4!)A6p?K|58nWheip*lxI+fj^26FD&KDE6QK66Zzkh=N%R69@p;(14Br literal 982 zcmV;{11bDcNk&G_0{{S5MM6+kP&il$0000G0000l001ul06|PpNU8t;00Dqo+t#w^ z^1csucXz7-Qrhzl9HuHB%l>&>1tG2^vb*E&k^T3$FG1eQZ51g$uv4V+kI`0<^1Z@N zk?Jjh$olyC%l>)Xq;7!>{iBj&BjJ`P&$fsCfpve_epJOBkTF?nu-B7D!hO=2ZR}

C%4 zc_9eOXvPbC4kzU8YowIA8cW~Uv|eB&yYwAObSwL2vY~UYI7NXPvf3b+c^?wcs~_t{ ze_m66-0)^{JdOMKPwjpQ@Sna!*?$wTZ~su*tNv7o!gXT!GRgivP}ec?5>l1!7<(rT zds|8x(qGc673zrvYIz;J23FG{9nHMnAuP}NpAED^laz3mAN1sy+NXK)!6v1FxQ;lh zOBLA>$~P3r4b*NcqR;y6pwyhZ3_PiDb|%n1gGjl3ZU}ujInlP{eks-#oA6>rh&g+!f`hv#_%JrgYPu z(U^&XLW^QX7F9Z*SRPpQl{B%x)_AMp^}_v~?j7 zapvHMKxSf*Mtyx8I}-<*UGn3)oHd(nn=)BZ`d$lDBwq_GL($_TPaS{UeevT(AJ`p0 z9%+hQb6z)U9qjbuXjg|dExCLjpS8$VKQ55VsIC%@{N5t{NsW)=hNGI`J=x97_kbz@ E0Of=7!TR z^RsQ+wr#F=CrNkLwKLt5p zA#XD@dUjpeAE$b3+L^DxHTFeSf1cS31%p^T>zA;%h{$GrFN-vf0?Y(=!&mW&$5d>Mf0V@R0U<7&@A z0tBskENz}biu4`Tru=##`SZli9Ear751gWr1KE>bu^0_-9y>^*?MI2?4Hj!5lps_l zqky&hoe8SS>b35}A0PaB|Ie=%=C;%&HS_V8@9yzqT+D9l!m$)j2iT7bd4ndj`>&{0 zI8X&=6i~e>3MtYT`te5c(YJvMnse{}88(fQKC9ML@$H;|>CTALF&PUtOv;OJO{I>5%SQ-uq{051ROj z=ZK<90Zt@}qJOcFXex1vg%*Oqi>cN@79tnEeb9D?ZJS+Ryvnwrhe%^Qj)GN=fv~wJ z4Ia4CcSU22ZB1I6T{;)?H;z}}25<5hq(DHUlxtGNLX>?*XLk<3aSz;3Y*X@?${?WG z>ZZLl$pnp@@YgZZ8GX!8a2ci_kin$JyZq&l z+WQ|h1p&RTa-$-XZM?+;MA6j%$Dz^0MF5URk%cWv9#jJa1hQ2gng~)1q&;)!h{nF0 zh@_S(eE$uy!D~GQWk7&ZAhpR+w?!@n_=27s!nv&FdYBJD5;j5f4%raQa|)yblm_8k zizQMVX;d?hvjARVEdTNmZMYu3oKKK^#*+lW1-K){N^CLIDiGSwVH@qzz8TN?01jh! zfPE<(%6{C46Bb-b_OK8kRla|rD+oqOp^!kit!^9d(J)TN@icCrKMs5;z)f@^j{D$- zkmDupfr^AeJ2BQ0fj*mIAm89KGdE%kUO~dlE(kG-o9JZ~NTHNd2QE^-N}*l{Qak`~ z8xCm(@dp!d24P?N(1nkME(1RgnG8@Ou9gc1W;< z@tDqmIZX=Nn0Yh)0%GQjJhIcj4~+4qOPh5VR2pcT1&Z^0If|7Ade~J)DVI8brzEH| z$>|g*%BvL%7NeX4b;xu3j({|1Jk5CvB+i{UDNJ+`Gy&6MP4?dXr2%v z*Nu9Xx+)?RSFxBB#9IWkzpxGxPiEXEuc-*RmKBB zPEMBwSy1Z;?f$WPj(gjDZ6t$4f!KyzZeqKybKR>HK`rxs=MoG-X;2fiyvLw6){S*; zp{HvVZSiKOk1fGEMTs%Y_%Ai#x4&Rr^@6QFKL4^uv1X>@X!*%-HqHpN6a$NC~ g03|3-Q8-F!flODK1e6A4LHS}!oDfP^vhRcd0JD?l-T(jq literal 1772 zcmVQj4N+cqN`nQhxvX7dAV-`K|Ub$-q+H-5I?Tx0g9jWxd@A|?POE8`3b8fO$T))xP* z(X?&brZw({`)WU&rdAs1iTa0x6F@PIxJ&&L|dpySV!ID|iUhjCcKz(@mE z!x@~W#3H<)4Ae(4eQJRk`Iz3<1)6^m)0b_4_TRZ+cz#eD3f8V;2r-1fE!F}W zEi0MEkTTx}8i1{`l_6vo0(Vuh0HD$I4SjZ=?^?k82R51bC)2D_{y8mi_?X^=U?2|F{Vr7s!k(AZC$O#ZMyavHhlQ7 zUR~QXuH~#o#>(b$u4?s~HLF*3IcF7023AlwAYudn0FV~|odGH^05AYPEfR)8p`i{n zwg3zPVp{+wOsxKc>)(pMupKF!Y2HoUqQ3|Yu|8lwR=?5zZuhG6J?H`bSNk_wPoM{u zSL{c@pY7+c2kck>`^q1^^gR0QB7Y?KUD{vz-uVX~;V-rW)PDcI)$_UjgVV?S?=oLR zf4}zz{#*R_{LkiJ#0RdQLNC^2Vp%JPEUvG9ra2BVZ92(p9h7Ka@!yf9(lj#}>+|u* z;^_?KWdzkM`6gqPo9;;r6&JEa)}R3X{(CWv?NvgLeOTq$cZXqf7|sPImi-7cS8DCN zGf;DVt3Am`>hH3{4-WzH43Ftx)SofNe^-#|0HdCo<+8Qs!}TZP{HH8~z5n`ExcHuT zDL1m&|DVpIy=xsLO>8k92HcmfSKhflQ0H~9=^-{#!I1g(;+44xw~=* zxvNz35vfsQE)@)Zsp*6_GjYD};Squ83<_?^SbALb{a`j<0Gn%6JY!zhp=Fg}Ga2|8 z52e1WU%^L1}15Ex0fF$e@eCT(()_P zvV?CA%#Sy08_U6VPt4EtmVQraWJX` zh=N|WQ>LgrvF~R&qOfB$!%D3cGv?;Xh_z$z7k&s4N)$WYf*k=|*jCEkO19{h_(%W4 zPuOqbCw`SeAX*R}UUsbVsgtuG?xs(#Ikx9`JZoQFz0n*7ZG@Fv@kZk`gzO$HoA9kN z8U5{-yY zvV{`&WKU2$mZeoBmiJrEdzUZAv1sRxpePdg1)F*X^Y)zp^Y*R;;z~vOv-z&)&G)JQ{m!C9cmziu1^nHA z`#`0c>@PnQ9CJKgC5NjJD8HM3|KC(g5nnCq$n0Gsu_DXk36@ql%npEye|?%RmG)

FJ$wK}0tWNB{uH;AM~i diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp index 948a3070fe34c611c42c0d3ad3013a0dce358be0..75b8c6f28b8e2ea6007e59d861563e2b41fbfd5b 100644 GIT binary patch literal 1306 zcmV+#1?BouNk&Ez1pok7MM6+kP&iBm1pojqU%(d-b%uhrZJ2~V@9qMKhzTInq|p!A zC`g&MPxZ3rTi|YyPvDRpDnqtNr_o(9$=#bphQ^TG-Qktp{l(pxv+32}kv;ziIJT`F zdtUywZQCyY^-my9M)R+f=~JglMq{h8ZQcoxg#Dk{IaAv&iCJ65^!$YHuY+opAp+hXWOi7RVi&dr~ebczgQC^Zb9!?ILB6W z&KL=1lH{WZg*_gz55l1#$7G@*Ez>nU(PQ9g7x*y^$;8BsgiIOQBPdANFjRYQIVNF% zIKNobzJmM`Kl0atejL6XY}!GbiJ!9s@h$%)tQg7fZ#bMYK#Z4_a#cb6N?0-uE;rkB zAjEVWAB5$tg!r>XM7X&d%P?^*(4CxovB}-*XdP4!Y$I=#+n1pRm>&2-(JHsEy)E!x zX3|s9HBq%cE0XdS@goLM%Hn-uqvvpFr5FX4UD}B|y|8T~S5k&J}r~MI; zdt){wYg&80`}F!8hpHI+mnrga#0c}MtIr+x#}+*i5j_|+JsAXmKH9VYm?C#4j3Ao! zx923f1_*E1d+gEb%cQ*MzB{t=2Q}`E8!_j@eK4Am1%R~loyow%3>t_a2SIDCiqiXE|8_4lAKDMs4Iz) zcDsQ~bJ-b|V`bw6hxF(3y&?tl!HL&#gozm7l0;oNUZ6aPzL80h%yK2?-~fEJ-3O*_ z4Eu5MD$C6>2S&NI@}L|TAQvJcWOtTnI}V6f4kM}9DvZ3-WmCa@a>evwJ%d_r?Ihmk zx(7bUAlC>dsS?uN;d$?5g3yV6%E9ycaV4_x`RuttzEdg&1N0&B+D=5D2&&k~Jl|-2 zRkn>%KQVxxN1l*=MZdHq6f1^gq70l;ZV>z7kcB@4@%cPe z)cqac_Ql9j$tt(6{cRKD8F6Qmi~F9c9x=bf{cvz0>Lz^xX{5FuM1c=#g2AB5aVCWkM;aN=2Z;L#s6r644ieflYql%Po#FAg7dnOn Q1u^cxAs{`U@Im?4Qe}IQL;wH) literal 1900 zcmV-y2b1_xNk&Fw2LJ$9MM6+kP&il$0000G0001A003VA06|PpNH75a00DqwTbm-~ zullQTcXxO9ki!OCRx^i?oR|n!<8G0=kI^!JSjFi-LL*`V;ET0H2IXfU0*i>o6o6Gy zRq6Ap5(_{XLdXcL-MzlN`ugSdZY_`jXhcENAu)N_0?GhF))9R;E`!bo9p?g?SRgw_ zEXHhFG$0{qYOqhdX<(wE4N@es3VIo$%il%6xP9gjiBri+2pI6aY4 zJbgh-Ud|V%3O!IcHKQx1FQH(_*TK;1>FQWbt^$K1zNn^cczkBs=QHCYZ8b&l!UV{K z{L0$KCf_&KR^}&2Fe|L&?1I7~pBENnCtCuH3sjcx6$c zwqkNkru);ie``q+_QI;IYLD9OV0ZxkuyBz|5<$1BH|vtey$> z5oto4=l-R-Aaq`Dk0}o9N0VrkqW_#;!u{!bJLDq%0092{Ghe=F;(kn} z+sQ@1=UlX30+2nWjkL$B^b!H2^QYO@iFc0{(-~yXj2TWz?VG{v`Jg zg}WyYnwGgn>{HFaG7E~pt=)sOO}*yd(UU-D(E&x{xKEl6OcU?pl)K%#U$dn1mDF19 zSw@l8G!GNFB3c3VVK0?uyqN&utT-D5%NM4g-3@Sii9tSXKtwce~uF zS&Jn746EW^wV~8zdQ1XC28~kXu8+Yo9p!<8h&(Q({J*4DBglPdpe4M_mD8AguZFn~ ztiuO~{6Bx?SfO~_ZV(GIboeR9~hAym{{fV|VM=77MxDrbW6`ujX z<3HF(>Zr;#*uCvC*bpoSr~C$h?_%nXps@A)=l_;({Fo#6Y1+Zv`!T5HB+)#^-Ud_; zBwftPN=d8Vx)*O1Mj+0oO=mZ+NVH*ptNDC-&zZ7Hwho6UQ#l-yNvc0Cm+2$$6YUk2D2t#vdZX-u3>-Be1u9gtTBiMB^xwWQ_rgvGpZ6(C@e23c!^K=>ai-Rqu zhqT`ZQof;9Bu!AD(i^PCbYV%yha9zuoKMp`U^z;3!+&d@Hud&_iy!O-$b9ZLcSRh? z)R|826w}TU!J#X6P%@Zh=La$I6zXa#h!B;{qfug}O%z@K{EZECu6zl)7CiNi%xti0 zB{OKfAj83~iJvmpTU|&q1^?^cIMn2RQ?jeSB95l}{DrEPTW{_gmU_pqTc)h@4T>~& zluq3)GM=xa(#^VU5}@FNqpc$?#SbVsX!~RH*5p0p@w z;~v{QMX0^bFT1!cXGM8K9FP+=9~-d~#TK#ZE{4umGT=;dfvWi?rYj;^l_Zxywze`W z^Cr{55U@*BalS}K%Czii_80e0#0#Zkhlij4-~I@}`-JFJ7$5{>LnoJSs??J8kWVl6|8A}RCGAu9^rAsfCE=2}tHwl93t0C?#+jMpvr7O3`2=tr{Hg$=HlnjVG^ewm|Js0J*kfPa6*GhtB>`fN!m#9J(sU!?(OSfzY*zS(FJ<-Vb zfAIg+`U)YaXv#sY(c--|X zEB+TVyZ%Ie4L$gi#Fc++`h6%vzsS$pjz9aLt+ZL(g;n$Dzy5=m=_TV(3H8^C{r0xd zp#a%}ht55dOq?yhwYPrtp-m1xXp;4X;)NhxxUpgP%XTLmO zcjaFva^}dP3$&sfFTIR_jC=2pHh9kpI@2(6V*GQo7Ws)`j)hd+tr@P~gR*2gO@+1? zG<`_tB+LJuF|SZ9tIec;h%}}6WClT`L>HSW?E{Hp1h^+mlbf_$9zA>!ug>NALJsO{ mU%z=YwVD?}XMya)Bp;vlyE5&E_6!fzx9pwrdz474!~g(M6R?N? diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp index 1b9a6956b3acdc11f40ce2bb3f6efbd845cc243f..d92ac47658ddda6c22c98cd1de43bfef7ee3c899 100644 GIT binary patch literal 3168 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 literal 5914 zcmV+#7v<CP}*Q=lvp4$ZXrTZQHhO+w%wJn3c8j%+5C3UAFD&%8dBl_qi9D5g8fry}6Ev z2_Q~)5^N$!IU`BPh1O|=BxQ#*C5*}`lluC515$lxc-vNC)IgW=K|=z7o%cWFpndn= zX}f{`!VK02_kU+Q5a3m37J;c} zTzbxteE{GNf?yLt5X=Bzc-mio^Up0nunMCgp*ZJ;%MJvPM3QK)BryP(_v@ei4UvHr z6+sbCifQaOkL6-;5fL8$W($zZ_;CZp305C;~$hhRquZr-r)jjd1z z31%ZK{-(`P#|Um_Sivn@p$-vz46uqT>QG0B1w9znfS9A8PB2LaHdzA|_)yjXVR*l{ zkcu3@vEf7bxH0nkh`q?8FmoO_Ucui*>_a~P?qQrlZ9@+D7%MTpSnztpylXrt5!-k8_QPB?YL8Kx_On8WD zgT+111d(Op$^$&KLAN5+@?>f7F4~wFi(8TL8+szgVmcMDTp5l&k6~=rA{Dt}!gb^r zSWY<)M7D|Z2P0cEodj6E42PV>&>DFmQpgt)E-|#sSUU@uKed+F680H@<;-x{p|nuH4!_mn85rx>wz;0mPi2ZkL#k6;sznu?cXh!T0S>{w6 zL^gvR05NY64l*<+_L>On$rjx9!US;l;LX6@z}yi#2XHh)F@Oo+l)h%fq$v}DNmF2> zfs^_t0)3N-W<9-N?uedVv{)-J0W5mh#29QM5R5h&KuiRM=0Zvnf#lF=K#WlCgc#9c zS;qvh(P$!_a8JwyhI^ZJV2k+B6Z^64?w|1?5gyo6y{}923CRZfYVe1#?F% z7h2SUiNO3;T#JUOyovSs@@C1GtwipycA=*x5{BpIZ_#GCMuV8XK=x;qCNy{d7?wA~ zC+=vjls;ci&zW=6$H~4^K%v{p}Ab?U%C6Z4p%eC<3ExqU$XR<}LLF67A$Sr20DR_pJ3yeBa~ z^sw{V0FI5;UpwXsScYuhbqGQ`YQ25;6p6W^+tgL&;Ml;>S3CGpSZ>VrTn0m1$y$HU z&65)I!c?oREz};c=nLCliriqQX->4uivHTgd${GqeAlf*!P^B|jkU|*IdNP(&6C>4 zqOW$)Nw9nvjy^&`?E|gotDV{JmJ9Q~vuhy<`^C4XIUDt|j4o6rK^e8_(=YqC zuaR6TRVf@tUFHB079o4MBIh{M~4>WwnGgesQH*3?w(RA%hCZ*7)b!aNV=yOQ%o_Y=Lt0Sl*(9^jfRnC210Om$=y>*o|3z} zAR&vAdrB#mWoaB0fJSw9xw|Am$fzK>rx-~R#7IFSAwdu_EI|SRfB*yl0w8oX09H^q zAjl2?0I)v*odGJ40FVGaF&2qJq9Gv`>V>2r0|c`GX8h>CX8eHcOy>S0@<;M3<_6UM z7yCEpug5NZL!H_0>Hg_HasQGxR`rY&Z{geOy?N92Z z{lER^um|$*?*G63*njwc(R?NT)Bei*3jVzR>FWUDb^gKhtL4A=kE_1p-%Fo2`!8M} z(0AjuCiS;G{?*^1tB-uY%=)SRx&D)pK4u@>f6@KPe3}2j_har$>HqzH;UCR^ssFD0 z7h+VLO4o@_Yt>>AeaZKUxqyvxWCAjKB>qjQ30UA)#w z&=RmdwlT`7a8J8Yae=7*c8XL|{@%wA8uvCqfsNX^?UZsS>wX}QD{K}ad4y~iO*p%4 z_cS{u7Ek%?WV6em2(U9#d8(&JDirb^u~7wK4+xP$iiI6IlD|a&S)6o=kG;59N|>K1 zn(0mUqbG3YIY7dQd+*4~)`!S9m7H6HP6YcKHhBc#b%1L}VIisp%;TckEkcu0>lo@u995$<*Em;XNodjTiCdC%R+TX|_ZR#|1`RR|`^@Teh zl#w@8fI1FTx2Dy+{blUT{`^kY*V-AZUd?ZZqCS4gW(kY5?retkLbF=>p=59Nl|=sf zo1Pc|{{N4>5nt#627ylGF`3n>X%`w%bw-Y~zWM_{Si$dc82|=YhISal{N7OY?O`C4 zD|qb}6nLWJ`hUyL+E>-;ricg9J@ZNYP(x(Sct&OI$Y!QWr*=^VN;G3#i>^1n4e#Je zOVhbFbLpXVu*16enDM+ic;97@R~u&kh__kgP#!R`*rQEnA+_dLkNP~L`0alC|J;c; zeiK=s8;BsLE)KbG3BD&Br@(Ha@SBT&$?xX`=$;eeel=|R_dIr6-Ro?=HEjnsJ_b`1 zK6Yg^-6;^2aW!xeTK)A~3Rm|L^FCHB_I>jIju7ZGo&N_1*QHkxH2!!%@o4iZ?vntS;&zJdPe1dH#04YD93A44o-MpfD zP{rn_aq>U%RDvC2+bp;xPlsOzauIi3*Lf42`jVKKZCRuKdYhi>FDuL2l=v{$BCN#Q6796s%r-AG$Q^t(3c@ zD?w0UhYr11@feiyl9kY_@H8~|xlmO<8PfQmj1!$@WieW@VxR@Psxfe-v9WCi1+f>F4VL?0O~K7T?m4-u|pSkBpUJZZe*16_wAp zSYZ@;k`3;W3UHKUWc8QeI}0jH5Ly=cGWQPw(Kr2fm=-5L(d`lcXofy8tJY3@Tuadz zYWXR{mW7XT!RF#RVCe%}=tM*O6!AD3^(!8un~opNI%Uko7$5t@<8+?; zTxDys(MyyGsUjtSu9$+|_-t!U3fVb1dkK?l`17<+jfl=hrBHnDSV>^R1=TnQeyqbW z>ov#l%!1|S!1>8UUxIdhQq`_klcHVx0{?#>K3#$4GlXncwldt!g17TcvKq-jo_996 z>oA=tH9CqRl6Yw?Uc`am!V?lHJbizOJaVaScf1UP5e7Dbgabq=b!B~T&_F6?ooU>w%x0A zH~&MHJ=q`fCH{U<7MDXE4SD32cDZA)WJeWkllJ`UspWaS#eDe^kg^oU_A14UE9zG-a^g{xaXf$})Wik>gT zl#dkzGr(;h0JZDuFn(+k8wNq?PZ5grQ<+sM?wBGt@JnH6v0#or-5wBQWKU~(S_> zkE!tc*ZJ1Y&*p(xX84POb3cClRMd!^qJ#CAZfIepEj-<`VURS_yCz0(?*Ixcj4 z-!zV1_QZhpm=0<;*(nm+F>T=)o?ep@CK5I%g^VAA+RB25ab?7)A~z~egru=I1S|@v zH7tXV!0wmGS^qj#e+MY;C5eUjEAp$Y?LDkS^QPZ}8WN85?r$u<-Epi;yZ1|J2J`se z$D6DpH~2F=eI0B&=UFAUnJvZAmClJlK)sutJ?M>xpZiWV&0=G4MZP+x+p>EX=HbCz zxls%Mw?*u^;LbHWIWCyq+yi)`GmFn9J112CZda_u@YIP%i;srFg_paU02Ifij*7}l z&CF-(3|>*a|+vbNR`^RP=9G?ymEJ0Z~)d&c*UE$UMepZ zcITr{0WqhxkjUnM15js_gW=e3Uh|y6ZReaXHIz-=p`x5VvB&rH9y>Amv@^WmXFEw) zQXYrk3feir=a{jMQ+wDIkkFnZ$k{sJakHn*?u za%4b!00ev8NVLM1TY=cl?KB&55BY_MU-sg?c>=Dbz_W{(Z~c?HJi*XpYL)C6Bd8WH zt+v-#0&o~@t4qESi*)+eW%@VD0|o^yF)n0hME$UtXF$*Lvh}7sso{`|pn*JDIy5^Fm3s$5*zEE=?u5<=l8FJc3r%+H} zdfoNl2J0^~!-*mOL5o-x32|e0Im*E!yY7F7E5N)W3>+v_LBydlEx?4$RL5f2oYRD# zaR0wv(-p~wO0eLDl3K=%`{5+0Gd$ktO=W)gWlGZJ0`K z$_RNA=ckrfa;H0KA~dR^p�(p-{x$&=IACIfoAR!za)F-^da-t3#0Dycnp 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 literal 3844 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 AhyVZp literal 7778 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

UmY2RIYtNPVDpE$%vda+HD#3m z&VuXJ{BK&Qe+rBa7eq}Q(bq|tn(RrJAk|ztj2(i{d>nmQnM?;HF2k&9sA6up5tmjl z7lySlzMbifH17-m-Lwa_F&e7nOH?ESi3#ckR3tsM+jsck3`oG!uMS}|eAwVXv>}qxwq?QY%QJ0}r@^;fhuUA9W z*BVl>TGo&N004@xSiwDUXUvp51sVmqO3m)=B55aPwf@0=e}cN+$-BdKxY`YrT_4)0 z_d10#i44Q*rFr8MC>*)v$EJvz``(pb{e&*6k+b zsMz%($|1+8hn8c2?P(l@;Rb&CsZeYoCI3?2!LqjbwPXW3z4G$Qfj=cT5Yb%vY0(AX oeb?AaKtwrnc|$|zzw9vfvn^aJJ!zd)XFXqqy0000001=f@-~a#s diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml new file mode 100644 index 0000000..f8c6127 --- /dev/null +++ b/app/src/main/res/values-night/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/app/src/main/res/values-night/ic_launcher_background.xml b/app/src/main/res/values-night/ic_launcher_background.xml new file mode 100644 index 0000000..8314ac8 --- /dev/null +++ b/app/src/main/res/values-night/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #36393F + \ No newline at end of file diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml new file mode 100644 index 0000000..d1e3047 --- /dev/null +++ b/app/src/main/res/values-night/themes.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..c5d5899 --- /dev/null +++ b/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cb0735c..9ebea0a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,24 @@ - SampoomManagement + 삼품관리 + + + 부품 조회 + 인벤토리 + 프로필 + 설정 + + + 로그인 + 이메일 + 비밀번호 + 로그인 + 로그인 중… + + + 부품 목록 + 부품 목록이 없습니다. + + + 오류가 발생했습니다 + 다시 시도 \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 4048c21..d1e3047 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -1,5 +1,6 @@ - - - \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 081086d..14f873b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,6 @@ [versions] agp = "8.13.0" +coreSplashscreen = "1.0.1" hiltAndroid = "2.57.2" hiltNavigationCompose = "1.3.0" kotlin = "2.2.20" @@ -15,6 +16,7 @@ retrofitVersion = "3.0.0" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +androidx-core-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "coreSplashscreen" } androidx-hilt-lifecycle-viewmodel-compose = { module = "androidx.hilt:hilt-lifecycle-viewmodel-compose", version.ref = "hiltNavigationCompose" } androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hiltNavigationCompose" } androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" } From 8dfb8a72c8e56b11e1824091d021dfcc18b205cd Mon Sep 17 00:00:00 2001 From: Choo ChangWoo Date: Sat, 4 Oct 2025 20:11:19 +0900 Subject: [PATCH 07/88] =?UTF-8?q?=EA=B8=B0=EB=8A=A5:=20=EA=B3=B5=ED=86=B5?= =?UTF-8?q?=20=EC=9B=8C=ED=81=AC=ED=94=8C=EB=A1=9C=EC=9A=B0=20=ED=85=9C?= =?UTF-8?q?=ED=94=8C=EB=A6=BF=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/assign-issue-creator.yml | 14 ++++++++++++++ .../workflows/close-issues-on-dev-merge.yml | 19 +++++++++++++++++++ .github/workflows/request-pr-review.yml | 17 +++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 .github/workflows/assign-issue-creator.yml create mode 100644 .github/workflows/close-issues-on-dev-merge.yml create mode 100644 .github/workflows/request-pr-review.yml diff --git a/.github/workflows/assign-issue-creator.yml b/.github/workflows/assign-issue-creator.yml new file mode 100644 index 0000000..6dde730 --- /dev/null +++ b/.github/workflows/assign-issue-creator.yml @@ -0,0 +1,14 @@ +# 각 레포지토리의 .github/workflows/assign-issue-creator.yml + +name: Assign issue creator + +on: + issues: + types: [opened] + +jobs: + call-reusable-workflow: + # @main 은 .github 레포지토리의 main 브랜치를 사용한다는 의미입니다. 버전을 위해 @v1과 같이 태그를 사용하는 것을 권장합니다. + uses: 33-Auto/.github/.github/workflows/reusable-assign-issue-creator.yml@main + # 이 워크플로우는 secrets를 전달할 필요가 없지만, 필요 시 아래와 같이 전달합니다. + # secrets: inherit \ No newline at end of file diff --git a/.github/workflows/close-issues-on-dev-merge.yml b/.github/workflows/close-issues-on-dev-merge.yml new file mode 100644 index 0000000..325a846 --- /dev/null +++ b/.github/workflows/close-issues-on-dev-merge.yml @@ -0,0 +1,19 @@ +# 각 레포지토리의 .github/workflows/close-issues-on-dev-merge.yml + +name: Auto Close Issues on dev merge + +on: + pull_request: + types: [closed] + +jobs: + call-reusable-workflow: + if: > + github.event.pull_request.merged == true && + github.event.pull_request.base.ref == 'dev' + uses: 33-Auto/.github/.github/workflows/reusable-close-linked-issues.yml@main + # with를 통해 재사용 워크플로우의 inputs에 값을 전달합니다. + with: + pr-body: ${{ github.event.pull_request.body }} + issue-number: ${{ github.event.pull_request.number }} + secrets: inherit # 재사용 워크플로우가 GITHUB_TOKEN을 사용할 수 있도록 전달 \ No newline at end of file diff --git a/.github/workflows/request-pr-review.yml b/.github/workflows/request-pr-review.yml new file mode 100644 index 0000000..66a31b9 --- /dev/null +++ b/.github/workflows/request-pr-review.yml @@ -0,0 +1,17 @@ +# 각 레포지토리의 .github/workflows/request-pr-review.yml + +name: PR Assignee & Team Review Request + +on: + pull_request: + types: [opened, reopened, ready_for_review] + +jobs: + call-reusable-workflow: + uses: 33-Auto/.github/.github/workflows/reusable-pr-assign-and-review.yml@main + with: + team-slug-for-review: "review_avengers" # 여기에 리뷰를 요청할 팀의 slug를 입력합니다. + pr-author: ${{ github.event.pull_request.user.login }} + pr-number: ${{ github.event.pull_request.number }} + secrets: + ORGANIZATION_TOKEN: ${{ secrets.ORGANIZATION_TOKEN }} # 재사용 워크플로우가 ORGANIZATION_TOKEN을 사용할 수 있도록 전달 From bb095b2ea6c05d5836029a90434e21738be93425 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Fri, 10 Oct 2025 18:57:59 +0900 Subject: [PATCH 08/88] =?UTF-8?q?#8=20[REFAC]=20=EC=95=B1=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=EC=BD=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/ic_launcher-playstore.png | Bin 10324 -> 7749 bytes .../drawable-night/ic_launcher_foreground.xml | 4 ++-- .../res/drawable/ic_launcher_foreground.xml | 4 ++-- app/src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 1150 -> 998 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 2328 -> 2148 bytes app/src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 816 -> 722 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 1582 -> 1490 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 1306 -> 1184 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 3168 -> 2916 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 1790 -> 1594 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 4858 -> 4504 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 2270 -> 1890 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 6698 -> 6314 bytes 13 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png index 4007c413f93981478e5cce26fa3ad1f294056b94..abf6dd4dfd31abded88aa446eef4344e76af06e0 100644 GIT binary patch literal 7749 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 dRnqt?{KvYCnwTs0qMwIB`~E}o_zNi4%-H|{ literal 10324 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 B diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml index 1c28491..078cfa1 100644 --- a/app/src/main/res/drawable/ic_launcher_foreground.xml +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -11,10 +11,10 @@ android:pathData="M0,0h512v512h-512z" android:fillColor="#ffffff"/> diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp index 7f4c78afc9407e062ff6118e0cda3ff530f3fcc6..1ed8d225f979e7b69b448e8bd323c632201dc05c 100644 GIT binary patch literal 998 zcmVHPfa+IZQFF#_m9=KH7q;nIb(-fZQJrDKZTj0 zwu(0(*;83v-xXr37!)(8q%+U}xDH(tfd9W|2r|S%nmLdmL_z(A{D>J=GHhnp&#;?e zk84S0E~4LnA2T#FJbSPd__sWsV>Qvwlp#R$c=3?#M@TEy8wfE&z>+ z-2Nx~dTQ^@?g!TW7e5RrkUN$^Fh31HpRH{8TKC7g>Ft{d1#;^FFrR>*xT0U%e(7M% zk1rrfXFc<%4N#bo*mg^ZMqs}MKRK9AFah)cD9$AUpwR%77eFKe#nPKrlmaM#Yz37E zAlZr)aFiB`s0(e;kE~I}P>(_|kB6hkntfM}{;@4p04LZ7^L^sr=-|o55B(EsDhU|e z2|vdFK0f0Eq?GS67=W%L)q#kUOlN9f+ja>6s)B9X_E8jgi7ESL;_E5)Z^x1oltf(s z=3Q{(Z2VaF$G+t$qE1zh8$5&NJb3zH;PAnLGxno9QB|rEbfO!Y4dE#@5?>Hk#BQYr zRLuP3qTiMpv~J(0R7%vf~X4$Bwjfda2>rujA1^G<7_4YzTyZ%H%R!yRi~ zQcxgS6m>DmQj?Z^4PVQs1amu5A$pqIXui%Lq@mCkZ)<|#hv)zCLY#{8nHwWv&O|ZY zFWedlcIZJ6Un=i9GxD}|@}(m}uE$R-S8RazLkUZU07Rhoi}y5apMbXekuNaeHCgbc z2vmn#_}o_%DWt)DD$#u4d$46tT`vYH_Fl4}59aq9KJD>UPcIq0VvL9{8zV}IC{ZFx zi6{{fC8Csw5+$OPh!W*1Mo*shxZlw7_K*W9gCOW654vCyOo3_c9UthlRRDnz#7>f4 Us+~03YIARS^Dsvp0rCG-03PMcWdHyG literal 1150 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 aN~)w06PVmwUQ5|Q+gu-?v?pXh#v}l7XA%zp literal 2328 zcmV+z3Fr1wNk&Ex2><|BMM6+kP&iBk2><{uN5Byf^@f7BZ6t?3?Cl;15itSYqltEW zQTa-1+jc{iv!c^Eif!ArZQHiZL)*4(+qTB`%=WITbNtDCu2%S+qP}nwr$(CZQFLk?R)V{{)4)W+s*BB{GQsjIk_G4dy}oUrXB%D z3;+U7&Q>vbvNhSZZQE|&-v0@JcvIG*T%MK%wXj8bD)_+Y+rCvxgmws#RHjzcnR?5}+Wb4uR3TC&3Jp}eY3@oFY zWL%O!O|@4X6%FHVBG+EO3duMmfdAb+92js1PL@TJr3fqG4cjg+NW-<5Gpe zB~Nd?!W{naDX+MRj2Z#;;4YF{X#IMLs&zP(X-m+=%5Mo9iw!wjxQVQz8`@2D9`4nn z97ROcaP95Qn^$BIv6=ul6I+OYs`h+|U0^f$km;sPVZgGh{do3&k>_hg1`$;vLWm^= zL`=^VPH$!+1r#->F7*bVO}WoaWK}d+6Qb6R0udFI0$g&+901!)OiauIu*D>hIY?+G z$~_@0iw&76Le-IZdS#A3A-?HRMBdNwHHbK#YXC(dqB8(FAuH80a8)kY(L%`mz$Md~ z#AYEx!PmBv%d?2J zavv}vOL+UCp;S=(CfIp|P}W)2 z!l?oP6`;y)E@OLJ{GMFwff9x(oGy&Tq>^l0c7(7tfbZ0}iLrg`Hn5jLXu3G0ojjnM#in_vIq~sge~DyS7L2Q8*P}vX;-r`*r#iyri876Y7=snU z9yUrZ28Lkg2t`I$KW%(GMg@QH9-A;(ya z0m8VJ%D;bMX^jNMciYx6?nc8YjK6+u1@qQL1&5-Gc57C( z>Y5iUB@?^ipHVUlVI4pbltv5V<;%GcwXc~10Zk-?*wDM0M8ytZ?qci4%_ezqyM|(M2V!xA@)d#b_|ELL9Dso=`NlBRg4R zBhfij%|Go8akv8*58&UOEvb+POzg&p+R<$y+U1rKgOZpODvFOyolcC`6 zECU*eGKMd5&I}N7n&HR~b(LXve#qs+5E2@xhF#BowVVMk6Lt(^;&H`$U)A!`!U;|D zPyb9jJEhp*dt%;4XwgPAjb`#In|h0M7ZxGbg;ioZPhq(+A&n))E#tG4cKH@!pTmSW zZM32y71Bsjl%i{{CC+o0q;yD4Yew8Q-CUlE#tEY&O!3x6+dr7XJOz3>W11JNyQ<_U z7AB05DCD<{t+uvcGz$mxbtbSR?sJx0+mr>3dPeYW&&K6VGnF^L*8#nqNi2wKk?1o& zRE21)=<#aOSTsBNQ<0dzA9g_h)P$zQkp%60y4c9`qH&XWG-)iJFFLZ_ITGCN$rQvh zHG2h({Thf1#u?A$d<%~1TMGytncqP5|paM zYZ6NnPc{_KzyIcPE89NUv?IhnHGtQ^R~yc8W7zs*7!PSnoQZFP{*qT%wcEuL9$)mA`nL`}L^WvhI`RDUAM;BGjPDE~ ybsEiLXq%qwUikDu;`;Z4pT2Pa&^C=aJ?B6zn{vh#Mi3{H$5ozqv1M~71#t%T$ZOO9 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp index 719851c50a0f63d863c7a79cc5102841b4b5ae29..371dc79fbadc0ec1f4c3a074706dc62d78bfe219 100644 GIT binary patch literal 722 zcmV;@0xkVgNk&G>0ssJ4MM6+kP&iDz0ssInFTe{BRY;<>?Tn{P|BOe`@B-OznRJ)5x}+>e|7j0#M0jaJc}63XrJ)AO`|Ku!(Kk#uVu{ z>y;ZAQ&~@+1GkYBDPG3o`vZ>_RG5mO$;eS5#ciNeq=&#cRi=7W7fA}vt%KrJiaOLi z5U*&GIHXe6L2=Eo4#5siXCTN%g}GZr^F+{m5r3LLB&GS%aeF?m2?ET;s0e>-8ta{) z`4ebT$L(XU6$nrfwhLyl-fU`zb%gAiY_W;P9#jq>l0bZN5YWpS@T z_(?hdRx?7_v=U2z!T`q!(1sXh5`8nZIBEv3KolGBh9V$5BQ*f4HUSWQO0E7_ zt-Bc&WGb^!Y81F!iJK#LVJm^56hX9s&piBWut=C6E_aT7s`;ChakJdYJfD%U;^z~MJ`fvk}$m~g(^XE&@CV_rgY51 z+*})=0EG}$c@DB?tY#TI*~>nz@C3Gp5Ddt?6bE<#L5Ob*r9UBzPVkx+oM$FoLD!3s zm?q)G$drwapkt-wBZL(U!Z4B@U@zpt0n3R7ft!Tz;lNK6{Z9V7-}%cHc1^a~vQc5a zODF6_$BzFg%5SeTjrbW6_J0s0o;wdi(UC|(hPde(B(49OAY94%hPxl$96o>haQMV9 z9@I~7SKL>y1>p#P%n}Ui*mbpUZ;vEvI{-s-ZXKG7fi%dW@#bO*1R^>ka#Ivd@hHIo E0P7z|)&Kwi literal 816 zcmV-01JC?YNk&E}0{{S5MM6+kP&iB*0{{RoFTe{BRY;<(&5)$%v2D++Y}+eyXWQJ_ zwr$(CZQE)qDN@7o~<0zj~dZQI5a z={M_@8yHhrPoD#~krXLjrek;mh6^stMZk>zxRAvFu-4yQK;+6?kLv;%ji?S5xfFNk zdSG6`40Fh()WITk?7|2D9p#J&%5hPh^{W3mqV~B=$Gv@M)Ljonp!ZrTTkWBo-0TK;) zTeJMZ_`u{J6aQ>G^u1{Fi3$G}zqmKBn9QUgf{fTyXgd@Sfc~X;m-lS@TDEh~q+f@& zcvoIEIT3Scf?^zr0E&*=x#v+wQVhesZ26aRc5eHD9|ep&WJC1>$jX(e)i)%oZmqrY zwT!Wf(O6rUbaY}gb|HyCI=XIrVE%^{_YjvqnD)v4X(OP(x-#`U%a|Vp>n=%^XC^{h zz{#Xik{%&7u=LxSs}r*8BT)&A+ss9Ao=|$?vs}8 zH~>mw5DhUVBiXo2bJB4fJr#nGg6-Uc&>2WNjygl_;T6`_1fDJr;T52R2g$Ycm7x4QcVoOgns==Rn9w8FX2W z0xXsdEMYSTILJAEBR3p|0E{ve!W*t^>SKJdr38VQ7k=wL>Ivgwgk8@V@7-Sp;gb#a50B<6a%di%TGWr#Sz- zPB+5yBJ%Gbk$C0Yf#YI;v`OZUYa*%sZW7@-*0^$pN~kN5aLe#@pj#PEn6b& u=ZD!4!)A6p?K|58nWheip*lxI+fj^26FD&KDE6QK66Zzkh=N%R69@p;(14Br diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp index 46f6e2c840b497c68588234d4b98dbeb528e21ec..4898eebbe8b4e33404b74178ad6ca5bb19d174ac 100644 GIT binary patch literal 1490 zcmV;@1ugngNk&G>1pok7MM6+kP&iD!1pojqFTe{B)rNw$ZJ2~V>~;r2L`;B*0KQa7 z+qRw2lc{anw(Tz4RhPDnm2KO$ZQHhO+jxdt(5|1zuwuYLpI#wi2%RJbIz(cy08RwP47Ivo_um0V zpukSa4ghGWl@NtE!9{z87x_?sj3f9(lt9~#1!pwpC?^2mzX+b!!UYh6)jFhNaAL)p z#KI*C{&^N1A%c;LRREB`y;|80EyMsbXw35zFUcnl3|^rxY5`E5;II?1970}XAC$m_ z1GH|6wrF=y`Hwzg3Rp}U1UoTRplJDYhbTBq<1=Jqvx;$74NJB4u6rv-oi{>=xEe0)X>a8RQ~ZndiE z2k*Kn*eN*21ONa3|L+za?{no$UEq>=`>mDQ!Q5eIWgD!zyM;EuIs1-hyR4b>>R;Bm z0EZn@xYq^hJhsz`=4=J~S;$<-^`JZN$HTM89oTBsdS^8WH&Dwln?NW`2UCbn5Xj;n zJR&C?wfFPvfoZzUa;v4J#WYPnh|*BT;tN4$LB*%aDMmzqgf%BtSB}sD#}y=j;+;ku zV-F7>?jSd6fR{qC+wmXHCYA#yku+zB+I~zTVP|$|1Jhad`u-AG%dHU$pUNW1h^!eo!I#2oe=uO8q1`c!^XRC-Y+mr5}^okAzZ%n%~2 sO5yunUc{PD{)(A>PQYX#ayJG1TqpE|n0hKh-X8-^I literal 1582 zcmV+}2GRLaNk&E{1^@t8MM6+kP&iB(1^@srFTe{BmC)X{$#C@5&$iEO+d8&w9oe>R z^RsQ+wr#F=CrNkLwKLt5p zA#XD@dUjpeAE$b3+L^DxHTFeSf1cS31%p^T>zA;%h{$GrFN-vf0?Y(=!&mW&$5d>Mf0V@R0U<7&@A z0tBskENz}biu4`Tru=##`SZli9Ear751gWr1KE>bu^0_-9y>^*?MI2?4Hj!5lps_l zqky&hoe8SS>b35}A0PaB|Ie=%=C;%&HS_V8@9yzqT+D9l!m$)j2iT7bd4ndj`>&{0 zI8X&=6i~e>3MtYT`te5c(YJvMnse{}88(fQKC9ML@$H;|>CTALF&PUtOv;OJO{I>5%SQ-uq{051ROj z=ZK<90Zt@}qJOcFXex1vg%*Oqi>cN@79tnEeb9D?ZJS+Ryvnwrhe%^Qj)GN=fv~wJ z4Ia4CcSU22ZB1I6T{;)?H;z}}25<5hq(DHUlxtGNLX>?*XLk<3aSz;3Y*X@?${?WG z>ZZLl$pnp@@YgZZ8GX!8a2ci_kin$JyZq&l z+WQ|h1p&RTa-$-XZM?+;MA6j%$Dz^0MF5URk%cWv9#jJa1hQ2gng~)1q&;)!h{nF0 zh@_S(eE$uy!D~GQWk7&ZAhpR+w?!@n_=27s!nv&FdYBJD5;j5f4%raQa|)yblm_8k zizQMVX;d?hvjARVEdTNmZMYu3oKKK^#*+lW1-K){N^CLIDiGSwVH@qzz8TN?01jh! zfPE<(%6{C46Bb-b_OK8kRla|rD+oqOp^!kit!^9d(J)TN@icCrKMs5;z)f@^j{D$- zkmDupfr^AeJ2BQ0fj*mIAm89KGdE%kUO~dlE(kG-o9JZ~NTHNd2QE^-N}*l{Qak`~ z8xCm(@dp!d24P?N(1nkME(1RgnG8@Ou9gc1W;< z@tDqmIZX=Nn0Yh)0%GQjJhIcj4~+4qOPh5VR2pcT1&Z^0If|7Ade~J)DVI8brzEH| z$>|g*%BvL%7NeX4b;xu3j({|1Jk5CvB+i{UDNJ+`Gy&6MP4?dXr2%v z*Nu9Xx+)?RSFxBB#9IWkzpxGxPiEXEuc-*RmKBB zPEMBwSy1Z;?f$WPj(gjDZ6t$4f!KyzZeqKybKR>HK`rxs=MoG-X;2fiyvLw6){S*; zp{HvVZSiKOk1fGEMTs%Y_%Ai#x4&Rr^@6QFKL4^uv1X>@X!*%-HqHpN6a$NC~ g03|3-Q8-F!flODK1e6A4LHS}!oDfP^vhRcd0JD?l-T(jq diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp index 75b8c6f28b8e2ea6007e59d861563e2b41fbfd5b..5b3a93fc6700477559877dbf4142eec4c0bf4720 100644 GIT binary patch literal 1184 zcmV;R1Yi47Nk&GP1ONb6MM6+kP&iDB1ONapU%(d-b zZQHhO`<%5gwrx+Pa!{3IPjal}U!AIOYTMeBY~~p%4*+VjnV_1CV@4y%W&WRCj%{tn zp1q81+qTQBOu!gTR?76LQzfIZRpqyB>I?p7V|J zKtM%2RwrmC-Vz-DR1u>TdiR_jO~qUw{9YgNMJ2_)K4Kh%d?5N%zfy{PdC&xi_(1%w zL8TP=dXFg(|0Sk5mN?gxsnk&~Z& z#cZZB5&&@^#+b1nVqd0WZbg=(`8)vP6%Y_V1VG#jfnT~pwh~?qfOsBT3Bx-<#1q&` zn23W~UZg9g0{~(>x?)U60K~Q!a~_STr!#68>xBD26k82a-#FOdNul@IZJm!7Dgj&lftyI?|W%_|Um>luIwssIqz@hh;Mc3682 zEKStmSxJA?frxc%*@hNKSIc_ZVFARJwBzTk8BHof05B|v zfOsDOqim}Hn3dO#W5|MSA}8Q^8tF*Y#1}k=@AJIRHuh6W32b*k@QRuS`kHW!Z4H;1Y_WiP9as77uS3|S^VHF?P(+^8Qzz6bK?-sQDIKnAnCc;FB##2CK?*_;2)7^x2}q@n3<&jKO9248CnTW& literal 1306 zcmV+#1?BouNk&Ez1pok7MM6+kP&iBm1pojqU%(d-b%uhrZJ2~V@9qMKhzTInq|p!A zC`g&MPxZ3rTi|YyPvDRpDnqtNr_o(9$=#bphQ^TG-Qktp{l(pxv+32}kv;ziIJT`F zdtUywZQCyY^-my9M)R+f=~JglMq{h8ZQcoxg#Dk{IaAv&iCJ65^!$YHuY+opAp+hXWOi7RVi&dr~ebczgQC^Zb9!?ILB6W z&KL=1lH{WZg*_gz55l1#$7G@*Ez>nU(PQ9g7x*y^$;8BsgiIOQBPdANFjRYQIVNF% zIKNobzJmM`Kl0atejL6XY}!GbiJ!9s@h$%)tQg7fZ#bMYK#Z4_a#cb6N?0-uE;rkB zAjEVWAB5$tg!r>XM7X&d%P?^*(4CxovB}-*XdP4!Y$I=#+n1pRm>&2-(JHsEy)E!x zX3|s9HBq%cE0XdS@goLM%Hn-uqvvpFr5FX4UD}B|y|8T~S5k&J}r~MI; zdt){wYg&80`}F!8hpHI+mnrga#0c}MtIr+x#}+*i5j_|+JsAXmKH9VYm?C#4j3Ao! zx923f1_*E1d+gEb%cQ*MzB{t=2Q}`E8!_j@eK4Am1%R~loyow%3>t_a2SIDCiqiXE|8_4lAKDMs4Iz) zcDsQ~bJ-b|V`bw6hxF(3y&?tl!HL&#gozm7l0;oNUZ6aPzL80h%yK2?-~fEJ-3O*_ z4Eu5MD$C6>2S&NI@}L|TAQvJcWOtTnI}V6f4kM}9DvZ3-WmCa@a>evwJ%d_r?Ihmk zx(7bUAlC>dsS?uN;d$?5g3yV6%E9ycaV4_x`RuttzEdg&1N0&B+D=5D2&&k~Jl|-2 zRkn>%KQVxxN1l*=MZdHq6f1^gq70l;ZV>z7kcB@4@%cPe z)cqac_Ql9j$tt(6{cRKD8F6Qmi~F9c9x=bf{cvz0>Lz^xX{5FuM1c=#g2AB5aVCWkM;aN=2Z;L#s6r644ieflYql%Po#FAg7dnOn Q1u^cxAs{`U@Im?4Qe}IQL;wH) diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp index d92ac47658ddda6c22c98cd1de43bfef7ee3c899..e963f60ca0147dd0c9233121d17eeb1fdb01d854 100644 GIT binary patch literal 2916 zcmV-q3!C&(Nk&Fo3jhFDMM6+kP&iCb3jhEwU%(d-^@f7BZ6t?3?Cl;15itSoJ5@B1 zLzy>SzBqZZQGQ#3|6h&d=6^BUVPOfm~ORN z>dN`=Whu}-Car78@SK`bn^iSN?F)<*8W~?^J1?7OoRU$??WAYDj*v!e+u2A#?RL

AwNk0 zX&~KXkPMIc=jo)r?!mu5H1j``5Yh3txjc@D#F$JbS4a*SAfN(c3TS1F-AA(j)pipi za?d=RBN8zgPact0!5F0qQYhE8EQOAu$g*75wJ4>G{TC;U1PnPh2j_@HOZJd5!5Foy zNMUHkL1bB!GIsO-i58J_<2fE8(UJ3{M=*s^{zriVx(88fK-rWTM2F}(2J;Y!oE#v% zf>~~$K$Zj7qU^@04Fl?uNZ zdD$Qwk;IP>)TM@YDf@$s$PM8kDmw*h4XD9`R>rD!0gj#lJmktf!IBg;VS%#5{cTw2 zNp=!Ps$WGEQBy_{OME*@iYF!VkjT_j;Re*Cfy;)bouEK3D;{$+;h26E(jWmh1c;P$#g1haSV-T(-X_U=uBhQ_RC)du>=Gm=C1iC6&x zmqi@noX5L3g37LeKn;;mY(_Kk2yt&V0jDrz+xc}04fJnXDiJ6UKP8xT^v0$s>@bZuaZ zd$P4~Ie4c~XqxesWOd7YR7RB0gW#Y;l4~gAHX@~n#hGdJnOC$8RwZ7{LgOLyQgl?I5^(r) zARQ-F84pq^jV#pR)shkOQCWqeOYD(6xU;1*jkmtvrd#tE2!(0A`~00<5kqT>Lo-%S=%rg9g3;KnDhhj%HbivWhI zXejLe5ZI1`SVrIs{ALDr2nE@P{s94&5zByg5)H|vnH`-xo3I3)HI-9Lk1c$oLf(hS z^*m4?PDuLQ`t07B8Z{b!CTfY`z=*<&=hhN5fl zg6@8bO`MhfT-9x0L7x;rZs3x;=Jy3M#hMQ1>d{{T^qjwp;_B6_Z4etgqn_X|=apT( zdUf|yAj5v;nQC$Cs#ZNJLVC^@Fh)c@Vko4xq!-SUK}4&D0Xez-8!oB7ZaSof#->3fw_8A@k|&^oMvh}fA5MWQz>vvAt#oN9!1`FtK#T{O%+ zp*XSUOF@@kS+93)OG`8WsptWDU{d-aQ4Qzkg8aCvETfnD`Ui&VToa{_vtbN&perBLbNTRjYJ$CMj$LA2#;MinN5F_1ML`4vS^SZqbS3@_Dv z!2h`Ypn4kSnou0x^nUl7e#lCNALN4Jv5#qz%E}W5t}uO$LHPJ3s3fS=@U7o~@@h=` zLk`H+on@X8C3@m~MZv zAzGRgX2; zDjK`N`+HBX>|mB36@cm$UdLA33YE^pwrlTQ`%=FN?+{5g^xq-}^Iy#APO;E@p*WiQ z#^TcowFp^ynITxNeXKW#$ZVnL0!yFy$IA>$sH=Pme=Zf+ZvCVm)F&Bp73+J#nlD?1 zKS?0RDRklu6rbVv}m59iu%D;X|s5o z_ELE*V7kl7D-A$Br^l`-{h&TFOIUyVR_Swi-*87o>W8v488qOw?e_~sXq&+fMNio1 z7kFMYxg;^0^75A`K?^P$KkEv@wT)-HqBE@V5?p_G*5wkjD=&YJ!9{h;o;db@0#p>) z#3g^i17Fqb`@2ZCQG<-orKE@a+YASKlsN+eo%6Zr`ou%ZqRMw- zjZh4Si3z)v{cuA^(=GX0i3at7_e|yEbYTA|-{mhH*m@x&jDkWtJ9cQz5Pjf))}=4~ z{*)`HO!LvWvIOF1nKyycTVqzeePGLkiQ?M0XzOJc<7Vk}vsaQonTR_$Qk_T-y$gv$)LS^}eKUuU_)xdQZ3cy+_W0m4`MR)plIxWyQmq z?!S23-|IhF>g0D;y)Ws^TgHJ+qdWf6k`I`PWi4<))NZ@RqVOU$WK`aY1g Ol}e>jTkHE$qG18o!l$?Z literal 3168 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 literal 1790 zcmVy5HXa2@r3nrDRH>RPKj$H_|CBEKm%ax|^6n2+E>*YNjU6 z2a7U<5T;xBg-Pe=DSf6LI-*0)dw%@Q z?t=W9f+|Hif#=b|SBlIS} zl=!zLutB@^|H<_oMppGoa_kaxLo5dTOA=V`6JTGZ_2GO*$2;I!qV-{WLxVuHcsGkN z4Bk0Z>gxInqJ0~cy{zO}a&oc?Pdfm`|Gmghm)0j+Cr3JKQBJ%;NFqup@)Mbk8|03S5c8^AkF)BHJtOQ&*&ZMsR?RqIn*&7XJ$bi2Ho#Bj_k3eItjsNA|=94bZf|9*#VQnq|MT!M71HKgo3 zVzOU6aw8t$2mig33&)TlAOmIV5Kzmv$up~a+>rKE?(zZisJdNFxs-Y(`2lh~opX=; zq)O;Ee`4As|9e1azR`LG`0#?Z5%Ik3cqjS)3v9I!ZCXG#_h^q(Av|x2F^s1G)b`Z) zTF9Gon*?RRza)V*2o3+}-PEt~&-Znm^y3%Quj$v(BBWo{YaNOL8J7^9+i(33=sVr= z_%IM-U83X6;E5Nk>c`n;hAKFP79^ym)aRahV<{8}W+>O0{%d_wH|`-!3F|=p_bn zGAk5}@R~6o2eU#SY;JWVMlN7|!2iy0c6L7Pgw^b!@Tz-I%N2-&Bt;p=MA28q173`)-u*n-Xsq$R3M40r~kSWwQ0Z!~Mg-_{K$)k)<#9-gGv z1Z4+TiL8$bSSxB|va{YGmq*AbF5aqUztlwJ8P91cPYL}lGEKR$vY^f?zb6&^d&pJz=7qTaR?f^d^!5n8(S%j(-3zYY%oX4q>&wpr? z2I;l7&xzqeu)DDS9ArN%27S07-M0M@Gz^tkg8g>vdAjfz0J#+t#EtBi-ikGZNGw6Q z8@}tizcphi20(8u1O1%E3lN(gi$&~L3OVCeL7x|30W{z>)PcjXa~whhO9?s&1cNCl z$$MbN(T4_l;6)e+%l6c>deeK+``LQ#>Hl}^oG z6I~`a-+iKEt7#=F>H}YXIOMeiQw3Bz1e&t8y1t452ti{z5SPtAR;E9Rnavm zPUN-g5l=eW!eN&#ja==&;6Mf4Q+UdCdQz%UjXYPOh5w&f&Dq`Bwr#stwr$(Evu#_q zwz0Nt+xF(1d74aS{{P9OxXZicNzL@VSx)V)ZQHx4nc8MJwQXBf=EL1-?rw=eB@!V+ zcSt10`*yh1wk=QMo-!w$l#0s)8H2+NRMc$YvIspb1Gu|Y`hDN!P?DsonK>hO0+n~r z{DD1Y{};EBzI%5*W@ct)W@ct)W@ct)W+*H(@0OXFnK3D+v1fj|v1e*~#{GNZ6y#B( zsF(HmDmx8mT#7ckK3C1AtI4F<^Jt?h`l6isYcxp%o%FJDE~l)kI`Juj0wl?%Z7bff zZQFdlzR$L8+qP}<+xCC9ZR^_BUi&lzw{0XzG7717T)3tP-2VG4bRZhT(}R zU5u`x{g?eqRo3W7-F<(C6$=z*1DcsbAW z{s`Cee$*Q6MX!y$u<&vu=o|uQ=OFTOM8+7`??bKpT#g&R9b`p|(Ibp8nII{LqR=W1 zg4!=*>?uN4o_CdSb%#>W=co!}IiQJFlSWXojQ_cU=iiYf3F{y>&!g2CS7@RHY5|P5@ce4FA9;CX zM;9npe`&pVlN0G}Ild4zZ^QOi!W}tzUzc!p*(!s-*SR+JU zFypDaeAdkeS0CX_xEE!jG<$;dTDTEN#H6dhv^>*5)vq!qRJ`igul++f&%de`VBY(a%M44}^}^vG1(uq^aik=JoRM-MBtXV+Lu8YpVCf;H4&G2A_qRHdRe(6$=WCDH?r1^6!`)DcU z)(2oOK4B7{bHG{)hyjS4-({uLlg8Y3m zkzkqQ8I#e$yC@3Uc`8onC~-UI19Rb4OcDYtb0ou27w=07C?bFBanRk2oBv2eJXunj zzckI)0JeCQ6llVT7jIC!@A2{}tuP6ZB}svZOHb&|OaC98zaBeS=Qze-RG5xTOekXU z8ry{dLy}nMy??QBslZ9R%mMNd2ezj&IutYU9NQGYNyNZgF;v+pVn}`5WI1)3eN~|l zEUzY-;t}RuDFx~raBStNW?Oy39zAuSFU1AHgiHj>>%;Uy2bbm6)Pkcy#NwPb-hCv8 zu@joR-PZ&ehz+*)I_SXDXFDAUF*RH-VgfhejNOS;r_YsOvWuznO_kwen~(^nYFw!j z5k^@~&}MkfD@;;^;o9A=F>1i{tar+d2>V%%CixSoUuU>~#%4%H$MwZwNx{i9v42Q} zMeEq?j^dh#d+=xwY5g%{qAM8y&dh~a6J=sEvcmO3#zp{P@zS$4qEpL+u zzp|cQ2K2oT;#}2~&oZKSlq5c*u=smV0_1_OZ>o;2Gv%`AXLb5dav%lq84ILuq6qM? zoLAYSRWw3Bb{L8{!tXbOG#wf^Mwh%h6rz*Y!ben6uPSWrD|l?xrXL@bmWPySM!y_7vurLp&eg(4qDvkH?K{{+P7PrnxMFT#|5SxU&k^!A!WFjLhUE$Q6 zh1OdfOn{`rARLk`!t7!IE+VuP4Us0}hm&#`co!GMKTjrV+hAipD0e_4bp@kI{;0Z- zblCn{9-UkeKHQq{t_?P=OTQ)Lz3J7aZ`QrNsSjY&;N3S7f;R3{o9}D@a%9^pTW>CK z^E80*A`z&@?C|Z48y3oN?D5JMi6jP|CGeg*-0v)kA~Zb`!%L{eV0b?H}Y8 zmSt;V1LiOkM@BIDu!i>!$e=omNX~01cTc-!c1b}(0D74zjfRp4djih656){Tof0!D zupg#4bnYTO?4ngA5dxwo;>Q~gJy<#PeTS|49-@rL#^Q6$ekg8sEmvX~{jRKNVvmA{ zw#c}PSkHOs{nTLXdrS|9nUrHf+8chK2#auCECNYppv8A!y|>2nnmzcxVEAaqdG*-L za98>=Xzv7ALKSY|WQq|R6Y$>s8s69&47ZmWPxI2??X=(+^4p(_b?F)x*Dw>`bJ&*0 zXyf7D#O0jJ|G$pOT;#$Gd`WTKsg(Z(O|E&J@1X$G7kbX6NGM3aau}K3v|}&|^tr@s zAQJ@-AnzJddRJvg1>pAGMh~t&Kj%9zjLzA3P^$p{Uy=)SKMP0x3$CcoZ3esqoLefu z^3F~(tL4rJVloaB0kr^@qTt>&uk4d{3uPXahU`FiXCt^e9A5~BnILT>4B&n$e)k=? z?r2J-rTG*8JMBTu#%BvVxW*LhNeNJBdUVXYZ%W$DRrJaHiBs=r0%yy`aY$#6GnkgC z;W$0BG8>DsD>v|SGldyuK>A30b6p+1f)3YS%?!SN7Z-w{Sfgtrp6y)x?}9*5aX9fN z_`S9CK4_BL>Qdg+bwZ6m&`YEu8?ib_i=(inV?$~g9t`Lgs(bCr`lOgnF}DC4B)7GJ z_vj7V?BWtt1FQ;-3%-AXeK>xwvu0CHh^pq7Mo?VG4uQ_6=Yb$1*M#`NJmykTAt)MY z6+GmI`nr214arJ?!$#I3w8^ot^}HEyC8Jx_tQWS8}P>Bx4#!`%b*6CXLv+K{jN45->`rom?7G$(h;_PiK1m6jUY$yC{6lC`v$obL znO1ZkP~5};zB?v$eR*j>;PNWXb|`j3d0A%yM&0#M~=KcZFFw{Zw?dEMY@0h8=o zx+{IgkeCRif;vCx5v@AD;Oqf6EEMNDrwf=w^oB-a`L7* zBw2CHgWIJgxoUqmw3XusjP0Pkg$IJV#;2SekNtLmbFS7r8Z9sCnwIa2^&HyjeSxS_ z-geO4(37N#9r?or^&}Cv7Ly0#H^1oONf~9^n;4tmh+W&2t&9G2+W_JhIkpb=Am7?u z4*qR1(g;%v-KM0Zcj_vSq6{5M5614P&Gqc`0sl4c_j>2%BR*SdYo{17!H!eF0j2LN&dzouRf!j7?Ukih@!UAlq>H~|aLd1YR@db> zQ=_dsJ6(@S=u!R0e_l4!({$s=RXnAY+nsdR@*+rMX_+^U?)5yQ_bM=hs;}v9C{t1yW=c_v0ypg4x;wMDsX*7{1%rNg=(GoY zYsX_Q2pEU-t}b^vR}gY`7<;mR68hKvtNHnZ_ZBo2XM%03H|&g>xE$M*H5A<>e2u6s z>bdCU!@jrgxGSCWv(e(;?|q+$N~xe%FFm9B1tCF+=@<+CsThHx<1hdH6(e-bJh~{q z{3;%>mU+XCv>nGbjbQ~erQo<`p!mv>0*|ioJ=?#3`cDoYeXh;x-sR`jZHpz>6Tmdd z^$Cd0Le?nsE#JB_=Y2Eo(P6Krz+HUJ060oB6o!O^4dD1dQVIGra26F`BU(pFDU1Wi@=!%dQgGX2OQc?&IT|;jUaMVZru#_t9Y*$D!yI>BF1Rb-oIXci&ppO z_~0&&?6xK33|_8leo>P#3z18TS7haGrkrpiu-&FRX&c5kWq=a2YtnMB;=ZPTMe!|S z>#q?lr&K_xoD#o&Rq=}ItGIL1*2I!2$Cx+Wao_N5uk{v!4vd={a=}qoopnurbx~1u zb=Fnfbt$pX%+|dwlfe*rPPOUe&vM?i7Mk$t2Sefjt%?YOlouR0k q$+4Xl6^(}SoQ=Vt&qTpsqcblQrLxAJZAzsi8Re!V8KtUhXL$f8BF0(( literal 4858 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 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp index 7b5e294ca8a43b2881ccbb3ab3cff4135c2d9fac..71adf050d0eae99adfadc2f8f35bdb175feecdf4 100644 GIT binary patch literal 1890 zcmV-o2c7s*Nk&Fm2LJ$9MM6+kP&iCZ2LJ#szrZgLwT9xhZ5(O;wUb;g&xn`+7Stw< zXm=n$pPa932MwHQqy*ZwO}lxuZR7u++O}=mwr$(CZQHhOH@2NT-sGOxdUw3q4FirS z00gR+ZQC6}la0B#12oph+1W;tr+eaADgZQ~%e z?W9hZHmPjq52&}Rr1NLnsO&lz-4o#Hu}#THDp^Yv`%$f5YW%2{G_f}FOM@Q~5y?QA zV(G$u;1dx=l0ilivBj0|4>xiC3c$EmQN2lsNOxY83>;GL^&W#E*)%G2IT{ZYE zA{gN~gm^n&Xhu`s(pS|cizOu>T`AO;W%V^m#E>r*>C2LaXqK!1NDSp%vA!&7^a2nE zP@ppln!Is}0vvd!OEd;*%qSF|j^W|Nt}_%>N?1H(69{fa3(TBc8u1UsXMHSYLV;j( z9^lOC%*@yi6rcBiMlV6R3`L^|7MB>0?Km)uMWQbXT{!9^Ns=@LRWM^WQ^8;iq3;R9 zS_qm>dS6bm6Wa-4*p4rKbr^cH6Wh;$j3xyTQCy7kE6uFKD+jiOd@u!}w+&;yM*I`< z&>A}fzK;OKD?rAc#Mu^>fa*iQk_8G>mxGYEe7z3wm;h76Un8TwPz2Qd&hK#uc{WEx@oe4T}Fr-WZ=(}Q1$iUDCMEaIE3z_ zABL1jl2o2z<_lYmIr2{?g-rzLs-E*gbt#SAnthA_zi%_7FZbrK8N$T?o}1}#h>gaAocCKlEK42 zBXXe*mJ|T##(VJl^{JMWK$y|hcL?#i3I+kNz1*{(tqM4%mVAms2iZcZM1PO$@y@Yg{O)XTPZc=rqQDoC??3qij^+&wS7=}1_*=x}JE>q90Z>Ri{SmgV>r-T4 zW&y($=3lstIX!XrfErLGAhz*pABMP7EAPX^{^<<~SD23V2pe}Rd<#(pGT`CfF&NQE zJ#qLZeuvOG7u(_WB$Z`T^*6Y z7r23S`>-P+$$Q{HU_+1ti10vQ$9N<+vd`*0@%|Cs#}D`u<(6Py;4l1ykMIBoK1}Xs zBzKHQpqm6>R3H#=9()kmDzQacBYUH)X+t}XPJF)n|IzhL^M-->8|EYJ+W+I9w;fLz zX_U>`GK7)`4g@wO!GJ=58~hN~B)+p9_D0S|u7-JoI!1MM^y0pQFYuEzwB^|te$@~_ zSq);a5aFJU5!*PWlcSTfkt1y60$^yWstB=hwju$`u&Dx)CKY)EBNA~)Y@F8C(b1L6 zoy>#zV6Uy+Y5nTFe%L@jUhrQz}=-Bfq~yK9vB$tRusG>P7Ral%qB>|#lBw% c=KcKGrh#FmQpjwK2>@t}VW!f{0Hmi~1aO6K_y7O^ literal 2270 zcmV<42qE`UNk&H22mkbh{+D;}D*GaJU6r(otoS6exk1}Y@;RY1kxHg=>$7&I zyLV2QPMrl=*`4^b0Wk~!f=$}lwr$(CZQC|(mvh^;u|4@-8?kNMwpph$E8F=4>g_7& zY}=~r`s4Gya{}0JwkfHQge4J4l=_kUV3G+&@);2GBf+E)j4;NSq^YEbq!;x^2N+{4 z5+qI%N-!oFFF7E&EBPX+l+;RUDDRO}W&gY64~!)egyl0P87;XkfptQA({<(;#`1~E zXUt)zX_}J2DR2k?=uq-{xoMh1?P4sSpaf$jra9iJ>;Q}oWv3dG_jL%VURcQ9KM-eh&Tnqsqg34bq^mVO2X-4h4l?|s)mWzNek7-8CUpSaS|>TM`BeClhm3c zlpu1a*+Si6CQmy?LTD#akwhiKoob^%X{PQ6rpCW1Nd%HCZ6sX2WBPqWWFo06je^U! z%=qi4r3f%Gk@RIo!{r-h`csUbfKnjyHM9KhmnJ}@_%AjFFi2*aAff2jYZw@*Ntrfz zx}@n7XF!x8VTK1O%C27x->QIuE}RC51E5uhET8@HrFUO{^6fj{z43!fKRS2e6eSOT z>L3329STZ;Ah9j9YL~;p+hF^z%!ymTcGe=93#UMBXsDwP$keF=wGLSfnTOT*f5S?5 z-+gzt6fUj#BCbyZw>mE-9sf*ZUO>8QA1GC(kA*+-NVXc-vb|jJ9|E@q$H4KQLgp|y zp(Cf>@n*}MwkjEDR}A~~ADPd6J9A0TL?CNa;fo(Eg_EkaSf)XF&c*db;0oT!4ft0e z^Hy$ftp$xbW%$l5OR?vKZ9(;B=_I}Z3N1U#)V1^m?&pif9sx1 z&gSyKIe!M{ymPvv4=6b5P_`P!@F_?<4_ZxJn9Mon!$Oqn@#QzTuRY7+YK$aDQgd%h z=Gaj1xLq#GtF{WMa4JVY>V;6~8;?r&>lcG792~Ar2x&5 zK<4vbCaRbMt6Q#Cv2HC`H7mhY?2zRr7~?e5oI$(k{iCV)M-7gJtNC$g=eb5jj|u^q z_i_XBF#y0+XG?T-H>L?c z*Hz%|YJjUdr{eAt0hjwPLz_-~hio?w0ZMDLJv&fb{9U-3F9!;}sYX?>?NJSz4w*7+ z#};7I!FDA#>)3HW7xET%1YaMOhA|X3Uj{^!j)14G0dB&gH*)X27sENvc{eY?&7Ht) zf~D;FfS@m@^I4w43*o5+xF-|g_%7^^t}fL+Kt@JJ#$zeK?MX&P#&cNyNcLbeLL0Fr zy8Z%`jMgf2tFr6q@-%b}f39UUe(&byK%`*l{+xss`*1Snq5LBHL9tQW;C}3Zop}-; z;RqI1V;EeE$I}b0CZ#m~DOoLSd?~<|z6SVL0=Cbi<6lnFno)8V5o&z_Et>Iso(uLp z3_^<$^rkuG2)&O-@Vi+#a?gi0pGON7 zvLT>J$Y^^mKLc5dyO&byx{<&Jj9c_WdNG5`Wk6>1)a%^+DpOCTq%9qoHyqBng6Bb- z1W_7Ot2Lz{u^VLcqXItcgDWUQM)Bsvf@r)_&md?#AmI^JW!MS!bHS3QQTZBq|-%?v}Ty{ zojyqTJXtk4(%H$u!Z-=cKw?O4OU;q?NY4vgY|3C3XZd_E@cFV9&qzJirP;|_XpuI} zAOeZ{=WU}s(go>#vQxF_#0rnc<50Sj`imEPJkc(c=P>7yJ_{4`{DlT1P=w=19%;Iz z&PeyQ^!c>47kHoAnm)|nCiSEF{b)yZ&hX(Q)?2^bQs;ko<6%JpLqdgqqyf@$BV9Mp z%Ua8zkK1&DOBeWD%Kw^b>IiD9qkL^aO|@nHKi}u$T>hvnYZ+|aGVbrA{74iDF(O46 zi6hxq<~llWt#@4b4l7+enBQCJZ}(WRN1#cqP&XX_q${=}i5}d4Kx%%CT8R0oxFa zTw#Qf7?QjrYu;F-S!gBoLo>(D%ev#fX<L^1JE!GAz0EC0A#=JB3kxGEC2ui diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp index 61466d15563562c55a36aea6fc3308d3190eeaca..c436d4dc4a070a06dd2f0ce9f953e0acb68b2eb1 100644 GIT binary patch literal 6314 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 z zG`Njsch%;e+C4yr5BvS!-=3TFy^|){aW$HtgmLE_V~GvPNuC%P5KPDitfXhG3>fir zz)li~G0y;e@TDvu)KR!26kRSL^~#R-$cza9$K_gK=Tq7>A9wXOy0NJzW>i_@% literal 6698 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 AhyVZp From cc493452f5688fe9418c3ebcc9e9e7b508409d51 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Fri, 10 Oct 2025 23:24:29 +0900 Subject: [PATCH 09/88] =?UTF-8?q?#8=20[REFAC]=20=EB=82=B4=EB=B9=84?= =?UTF-8?q?=EA=B2=8C=EC=9D=B4=EC=85=98=20=EB=9D=BC=EC=9A=B0=ED=8A=B8=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC=20=EB=B0=8F=20FAB=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 3 + .../android/app/navigation/AppNavHost.kt | 107 +++++++++--------- .../android/feature/part/ui/PartScreen.kt | 101 +++++++++-------- app/src/main/res/drawable/cart.xml | 13 +++ app/src/main/res/drawable/dashboard.xml | 9 ++ app/src/main/res/drawable/delivery.xml | 13 +++ app/src/main/res/drawable/employee.xml | 9 ++ app/src/main/res/drawable/orders.xml | 9 ++ app/src/main/res/drawable/parts.xml | 9 ++ app/src/main/res/drawable/search.xml | 13 +++ app/src/main/res/drawable/settings.xml | 13 +++ app/src/main/res/values/strings.xml | 8 +- gradle/libs.versions.toml | 7 +- 13 files changed, 205 insertions(+), 109 deletions(-) create mode 100644 app/src/main/res/drawable/cart.xml create mode 100644 app/src/main/res/drawable/dashboard.xml create mode 100644 app/src/main/res/drawable/delivery.xml create mode 100644 app/src/main/res/drawable/employee.xml create mode 100644 app/src/main/res/drawable/orders.xml create mode 100644 app/src/main/res/drawable/parts.xml create mode 100644 app/src/main/res/drawable/search.xml create mode 100644 app/src/main/res/drawable/settings.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 6dfe38b..9ccbfc2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -79,6 +79,9 @@ dependencies { implementation(libs.converter.gson) implementation(libs.androidx.core.splashscreen) + implementation(libs.androidx.material) + implementation(libs.androidx.material.icons.core) + implementation(libs.androidx.material.icons.extended) implementation(libs.androidx.core.ktx) implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.activity.compose) diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index da7e9d9..b5c7e63 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -1,11 +1,7 @@ package com.sampoom.android.app.navigation -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Button +import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem @@ -14,7 +10,6 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.navigation.NavHostController @@ -30,23 +25,25 @@ const val ROUTE_LOGIN = "login" const val ROUTE_HOME = "home" // Main Screen -const val ROUTE_PART = "part" -const val ROUTE_INVENTORY = "inventory" -const val ROUTE_PROFILE = "profile" -const val ROUTE_SETTINGS = "settings" +const val ROUTE_DASHBOARD = "dashboard" +const val ROUTE_DELIVERY = "delivery" +const val ROUTE_CART = "cart" +const val ROUTE_ORDERS = "orders" // Detail Screen -const val ROUTE_DETAIL = "detail" +const val ROUTE_PARTS = "parts" +const val ROUTE_EMPLOYEE = "employee" +const val ROUTE_SETTINGS = "settings" sealed class BottomNavItem( val route: String, val title: Int, val icon: Int ) { - object Part : BottomNavItem(ROUTE_PART, R.string.nav_part, R.drawable.outline_home_24) - object Inventory : BottomNavItem(ROUTE_INVENTORY, R.string.nav_inventory, R.drawable.outline_home_24) - object Profile : BottomNavItem(ROUTE_PROFILE, R.string.nav_profile, R.drawable.outline_home_24) - object Settings : BottomNavItem(ROUTE_SETTINGS, R.string.nav_setting, R.drawable.outline_home_24) + object Dashboard : BottomNavItem(ROUTE_DASHBOARD, R.string.nav_dashboard, R.drawable.dashboard) + object Delivery : BottomNavItem(ROUTE_DELIVERY, R.string.nav_delivery, R.drawable.delivery) + object Cart : BottomNavItem(ROUTE_CART, R.string.nav_cart, R.drawable.cart) + object Orders : BottomNavItem(ROUTE_ORDERS, R.string.nav_order, R.drawable.orders) } @Composable @@ -68,7 +65,7 @@ fun AppNavHost() { }) } composable(ROUTE_HOME) { MainScreen(navController) } - composable(ROUTE_DETAIL) { DetailScreen() } + composable(ROUTE_PARTS) { PartScreen() } } } @@ -79,30 +76,46 @@ fun MainScreen( val navController = rememberNavController() Scaffold( - bottomBar = { - BottomNavigationBar(navController) - } + floatingActionButton = { FloatingActionButton(parentNavController) }, + bottomBar = { BottomNavigationBar(navController) } ) { innerPadding -> NavHost( navController = navController, - startDestination = ROUTE_PART, - modifier = Modifier.background(Color.Green).padding(innerPadding) + startDestination = ROUTE_DASHBOARD, + modifier = Modifier.padding(innerPadding) ) { - composable(ROUTE_PART) { PartScreen() } - composable(ROUTE_INVENTORY) { InventoryScreen() } - composable(ROUTE_PROFILE) { ProfileScreen() } - composable(ROUTE_SETTINGS) { SettingsScreen(parentNavController) } + composable(ROUTE_DASHBOARD) { DashboardScreen() } + composable(ROUTE_DELIVERY) { DeliveryScreen() } + composable(ROUTE_CART) { CartScreen() } + composable(ROUTE_ORDERS) { OrderScreen() } + } + } +} + +@Composable +fun FloatingActionButton(navController: NavHostController) { + FloatingActionButton( + onClick = { + navController.navigate(ROUTE_PARTS) { + popUpTo(navController.graph.startDestinationId) { + saveState = true + } + launchSingleTop = true + restoreState = true + } } + ) { + Icon(painterResource(R.drawable.parts), contentDescription = stringResource(R.string.part_title)) } } @Composable fun BottomNavigationBar(navController: NavHostController) { val bottomNavItems = listOf( - BottomNavItem.Part, - BottomNavItem.Inventory, - BottomNavItem.Profile, - BottomNavItem.Settings, + BottomNavItem.Dashboard, + BottomNavItem.Delivery, + BottomNavItem.Cart, + BottomNavItem.Orders, ) NavigationBar { @@ -130,41 +143,25 @@ fun BottomNavigationBar(navController: NavHostController) { // 임시 화면들 (실제로는 각각의 feature 모듈에서 구현) @Composable -private fun InventoryScreen() { +private fun DashboardScreen() { // 홈 화면 구현 - Text("인벤토리 화면") + Text("대시보드 화면") } @Composable -private fun ProfileScreen() { +private fun DeliveryScreen() { // 프로필 화면 구현 - Text("프로필 화면") + Text("Delivery 화면") } @Composable -private fun SettingsScreen( - navController: NavHostController -) { - Column( - modifier = Modifier.fillMaxSize() - ) { - // 설정 화면 구현 - Text("설정 화면") - Button( - onClick = { navController.navigate(ROUTE_DETAIL) } - ) { - Text("상세 화면") - } - } +private fun CartScreen() { + // 프로필 화면 구현 + Text("Cart 화면") } @Composable -private fun DetailScreen() { - // 설정 화면 구현 - Scaffold { innerPadding -> - Box(Modifier.fillMaxSize().background(Color.Red).padding(innerPadding) - ) { - Text("상세 화면") - } - } +private fun OrderScreen() { + // 프로필 화면 구현 + Text("Order 화면") } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index 2f48b78..1164887 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -20,60 +20,63 @@ fun PartScreen( ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() - Column( - modifier = Modifier - .fillMaxSize() - .padding(16.dp) - ) { - Text( - text = stringResource(R.string.part_title), - style = MaterialTheme.typography.headlineMedium, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(bottom = 16.dp) - ) + Scaffold { innerPadding -> + Column( + modifier = Modifier + .fillMaxSize() + .padding(innerPadding) + .padding(16.dp) + ) { + Text( + text = stringResource(R.string.part_title), + style = MaterialTheme.typography.headlineMedium, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(bottom = 16.dp) + ) - when { - uiState.loading -> { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { - CircularProgressIndicator() + when { + uiState.loading -> { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } } - } - - uiState.error != null -> { - Column( - modifier = Modifier.fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - Text( - text = "${stringResource(R.string.common_error)}: ${uiState.error}", - color = MaterialTheme.colorScheme.error - ) - Spacer(modifier = Modifier.height(16.dp)) - Button(onClick = { viewModel.refreshPart() }) { - Text(stringResource((R.string.common_retry))) + + uiState.error != null -> { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Text( + text = "${stringResource(R.string.common_error)}: ${uiState.error}", + color = MaterialTheme.colorScheme.error + ) + Spacer(modifier = Modifier.height(16.dp)) + Button(onClick = { viewModel.refreshPart() }) { + Text(stringResource((R.string.common_retry))) + } } } - } - - uiState.partList.isEmpty() -> { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { - Text(stringResource(R.string.part_empty)) + + uiState.partList.isEmpty() -> { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Text(stringResource(R.string.part_empty)) + } } - } - - else -> { - LazyColumn( - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - items(uiState.partList) { inventory -> - PartItemCard(part = inventory) + + else -> { + LazyColumn( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + items(uiState.partList) { inventory -> + PartItemCard(part = inventory) + } } } } diff --git a/app/src/main/res/drawable/cart.xml b/app/src/main/res/drawable/cart.xml new file mode 100644 index 0000000..afc4912 --- /dev/null +++ b/app/src/main/res/drawable/cart.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/drawable/dashboard.xml b/app/src/main/res/drawable/dashboard.xml new file mode 100644 index 0000000..c2c0e05 --- /dev/null +++ b/app/src/main/res/drawable/dashboard.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/delivery.xml b/app/src/main/res/drawable/delivery.xml new file mode 100644 index 0000000..ca411d4 --- /dev/null +++ b/app/src/main/res/drawable/delivery.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/drawable/employee.xml b/app/src/main/res/drawable/employee.xml new file mode 100644 index 0000000..8ac942e --- /dev/null +++ b/app/src/main/res/drawable/employee.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/orders.xml b/app/src/main/res/drawable/orders.xml new file mode 100644 index 0000000..7521789 --- /dev/null +++ b/app/src/main/res/drawable/orders.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/parts.xml b/app/src/main/res/drawable/parts.xml new file mode 100644 index 0000000..ff89964 --- /dev/null +++ b/app/src/main/res/drawable/parts.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/search.xml b/app/src/main/res/drawable/search.xml new file mode 100644 index 0000000..519d2d6 --- /dev/null +++ b/app/src/main/res/drawable/search.xml @@ -0,0 +1,13 @@ + + + diff --git a/app/src/main/res/drawable/settings.xml b/app/src/main/res/drawable/settings.xml new file mode 100644 index 0000000..20ed042 --- /dev/null +++ b/app/src/main/res/drawable/settings.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9ebea0a..8a5d69e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2,10 +2,10 @@ 삼품관리 - 부품 조회 - 인벤토리 - 프로필 - 설정 + 대시보드 + 출고목록 + 장바구니 + 주문관리 로그인 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 14f873b..3c44195 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,9 @@ junitVersion = "1.3.0" espressoCore = "3.7.0" lifecycleRuntimeKtx = "2.9.4" activityCompose = "1.11.0" -composeBom = "2025.09.01" +composeBom = "2025.10.00" +material = "1.9.3" +materialIconsCore = "1.7.8" navigationCompose = "2.9.5" retrofitVersion = "3.0.0" @@ -20,6 +22,9 @@ androidx-core-splashscreen = { module = "androidx.core:core-splashscreen", versi androidx-hilt-lifecycle-viewmodel-compose = { module = "androidx.hilt:hilt-lifecycle-viewmodel-compose", version.ref = "hiltNavigationCompose" } androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hiltNavigationCompose" } androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" } +androidx-material = { module = "androidx.compose.material:material", version.ref = "material" } +androidx-material-icons-core = { module = "androidx.compose.material:material-icons-core", version.ref = "materialIconsCore" } +androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended" } converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofitVersion" } hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" } hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hiltAndroid" } From 3ba895e3fbe234390727836f4b85f376201dd29d Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Sat, 11 Oct 2025 00:14:52 +0900 Subject: [PATCH 10/88] =?UTF-8?q?#8=20[FEAT]=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/core/ui/component/.gitkeep | 0 .../android/core/ui/component/CommonButton.kt | 256 ++++++++++++++++++ .../core/ui/component/CommonTextField.kt | 164 +++++++++++ 3 files changed, 420 insertions(+) delete mode 100644 app/src/main/java/com/sampoom/android/core/ui/component/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt create mode 100644 app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/.gitkeep b/app/src/main/java/com/sampoom/android/core/ui/component/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt b/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt new file mode 100644 index 0000000..a9ba4d0 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt @@ -0,0 +1,256 @@ +package com.sampoom.android.core.ui.component + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.FilledTonalButton +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp + +/** + * Sampoom common button with multiple visual variants. + * + * Usage + * ----- + * CommonButton( + * text = "Button", + * variant = ButtonVariant.Primary, + * onClick = { ... } + * ) + * + * Optionally pass a leading icon: + * CommonButton( + * text = "Button", + * variant = ButtonVariant.Primary, + * leadingIcon = { Icon(painterResource(R.drawable.parts), contentDescription = null) }, + * onClick = { ... } + * ) + */ +@Composable +fun CommonButton( + text: String, + modifier: Modifier = Modifier, + enabled: Boolean = true, + variant: ButtonVariant = ButtonVariant.Primary, + size: ButtonSize = ButtonSize.Large, + leadingIcon: (@Composable (() -> Unit))? = null, + onClick: () -> Unit +) { + val cs = MaterialTheme.colorScheme + val shape = MaterialTheme.shapes.large + val height = when (size) { + ButtonSize.Large -> 56.dp + ButtonSize.Medium -> 48.dp + ButtonSize.Small -> 40.dp + } + + when (variant) { + ButtonVariant.Primary -> { + Button( + onClick = onClick, + enabled = enabled, + shape = shape, + modifier = modifier.height(height), + colors = ButtonDefaults.buttonColors( + containerColor = cs.primary, + contentColor = cs.onPrimary, + disabledContainerColor = cs.onSurface.copy(alpha = 0.12f), + disabledContentColor = cs.onSurface.copy(alpha = 0.38f), + ) + ) { + if (leadingIcon != null) { + leadingIcon() + } + Text( + text = text, + style = MaterialTheme.typography.labelLarge, + fontWeight = FontWeight.SemiBold, + modifier = Modifier.padding(start = if (leadingIcon != null) 8.dp else 0.dp) + ) + } + } + + // Light/secondary (tonal) filled button + ButtonVariant.Secondary -> { + FilledTonalButton( + onClick = onClick, + enabled = enabled, + shape = shape, + modifier = modifier.height(height), + colors = ButtonDefaults.filledTonalButtonColors( + containerColor = cs.secondaryContainer, + contentColor = cs.onSecondaryContainer, + disabledContainerColor = cs.onSurface.copy(alpha = 0.08f), + disabledContentColor = cs.onSurface.copy(alpha = 0.38f) + ) + ) { + if (leadingIcon != null) { + leadingIcon() + } + Text( + text = text, + style = MaterialTheme.typography.labelLarge, + fontWeight = FontWeight.SemiBold, + modifier = Modifier.padding(start = if (leadingIcon != null) 8.dp else 0.dp) + ) + } + } + + // Outlined with primary border + ButtonVariant.Outlined -> { + OutlinedButton( + onClick = onClick, + enabled = enabled, + shape = shape, + modifier = modifier.height(height), + border = BorderStroke(1.dp, cs.primary), + colors = ButtonDefaults.outlinedButtonColors( + contentColor = cs.primary, + disabledContentColor = cs.onSurface.copy(alpha = 0.38f) + ) + ) { + Text( + text = text, + style = MaterialTheme.typography.labelLarge, + fontWeight = FontWeight.SemiBold + ) + } + } + + // Ghost: no container, subtle onSurface content + ButtonVariant.Ghost -> { + TextButton( + onClick = onClick, + enabled = enabled, + shape = shape, + modifier = modifier.height(height), + colors = ButtonDefaults.textButtonColors( + contentColor = cs.onSurface, + disabledContentColor = cs.onSurface.copy(alpha = 0.38f) + ) + ) { + Text( + text = text, + style = MaterialTheme.typography.labelLarge, + fontWeight = FontWeight.SemiBold + ) + } + } + + // Destructive/Neutral (dark) filled – matches the black fill example + ButtonVariant.Neutral -> { + Button( + onClick = onClick, + enabled = enabled, + shape = shape, + modifier = modifier.height(height), + colors = ButtonDefaults.buttonColors( + containerColor = Color(0xFF000000), + contentColor = Color.White, + disabledContainerColor = cs.onSurface.copy(alpha = 0.12f), + disabledContentColor = cs.onSurface.copy(alpha = 0.38f), + ) + ) { + Text( + text = text, + style = MaterialTheme.typography.labelLarge, + fontWeight = FontWeight.SemiBold + ) + } + } + } +} + +enum class ButtonVariant { + /** Primary filled (purple in design). Accepts optional [leadingIcon]. */ + Primary, + + /** Filled tonal (light purple in design). */ + Secondary, + + /** Outlined with primary border. */ + Outlined, + + /** No container; text only. */ + Ghost, + + /** Solid dark/neutral fill. */ + Neutral, +} + +enum class ButtonSize { Large, Medium, Small } + +@Preview(showBackground = true, backgroundColor = 0xFF0F0F10) +@Composable +private fun CommonButtonPreview_All() { + // Primary + CommonButton( + text = "Button", + variant = ButtonVariant.Primary, + onClick = {} + ) +} + +@Preview(showBackground = true, backgroundColor = 0xFF0F0F10) +@Composable +private fun CommonButtonPreview_Primary_WithIcon() { + CommonButton( + text = "Button", + variant = ButtonVariant.Primary, + leadingIcon = { Icon(painterResource(android.R.drawable.ic_menu_call), contentDescription = null) }, + onClick = {} + ) +} + +@Preview(showBackground = true, backgroundColor = 0xFF0F0F10) +@Composable +private fun CommonButtonPreview_Tonal() { + CommonButton( + text = "Button", + variant = ButtonVariant.Secondary, + onClick = {} + ) +} + +@Preview(showBackground = true, backgroundColor = 0xFF0F0F10) +@Composable +private fun CommonButtonPreview_Outlined() { + CommonButton( + text = "Button", + variant = ButtonVariant.Outlined, + onClick = {} + ) +} + +@Preview(showBackground = true, backgroundColor = 0xFF0F0F10) +@Composable +private fun CommonButtonPreview_Ghost() { + CommonButton( + text = "Button", + variant = ButtonVariant.Ghost, + onClick = {} + ) +} + +@Preview(showBackground = true, backgroundColor = 0xFF0F0F10) +@Composable +private fun CommonButtonPreview_Neutral_Disabled() { + CommonButton( + text = "Button", + variant = ButtonVariant.Neutral, + enabled = false, + onClick = {} + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt b/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt new file mode 100644 index 0000000..52ba4bf --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt @@ -0,0 +1,164 @@ +package com.sampoom.android.core.ui.component + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Visibility +import androidx.compose.material.icons.filled.VisibilityOff +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.input.VisualTransformation +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp + +enum class TextFieldVariant { Outlined, Filled } + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun CommonTextField( + value: String, + onValueChange: (String) -> Unit, + label: String, + placeholder: String, + modifier: Modifier = Modifier, + enabled: Boolean = true, + isPassword: Boolean = false, + variant: TextFieldVariant = TextFieldVariant.Outlined +) { + var passwordVisible by remember { mutableStateOf(false) } + val darkTheme = isSystemInDarkTheme() + val cs = MaterialTheme.colorScheme + + val textColor = if (darkTheme) Color.White else Color.Black + val containerColor = if (variant == TextFieldVariant.Filled) { + if (darkTheme) Color(0xFF1C1C1E) else Color(0xFFF3F3F3) + } else Color.Transparent + + val focusedBorderColor = cs.primary + val unfocusedBorderColor = if (darkTheme) Color(0xFF666666) else Color(0xFFCCCCCC) + + val trailingIconView = if (isPassword) { + @Composable { + IconButton(onClick = { passwordVisible = !passwordVisible }) { + Icon( + imageVector = if (passwordVisible) Icons.Default.Visibility else Icons.Default.VisibilityOff, + contentDescription = null, + tint = if (darkTheme) Color.White else Color.Black + ) + } + } + } else null + + when (variant) { + TextFieldVariant.Outlined -> { + OutlinedTextField( + value = value, + onValueChange = onValueChange, + label = { Text(text = label, color = textColor) }, + placeholder = { Text(text = placeholder, color = textColor.copy(alpha = 0.4f)) }, + modifier = modifier + .fillMaxWidth() + .padding(vertical = 4.dp), + singleLine = true, + enabled = enabled, + trailingIcon = trailingIconView, + visualTransformation = if (isPassword && !passwordVisible) PasswordVisualTransformation() else VisualTransformation.None, + keyboardOptions = KeyboardOptions(keyboardType = if (isPassword) KeyboardType.Password else KeyboardType.Text), + colors = OutlinedTextFieldDefaults.colors( + focusedBorderColor = focusedBorderColor, + unfocusedBorderColor = unfocusedBorderColor, + disabledBorderColor = Color.Gray, + focusedLabelColor = focusedBorderColor, + unfocusedLabelColor = textColor.copy(alpha = 0.7f), + cursorColor = focusedBorderColor, + focusedTextColor = textColor, + unfocusedTextColor = textColor + ), + shape = MaterialTheme.shapes.medium + ) + } + + TextFieldVariant.Filled -> { + TextField( + value = value, + onValueChange = onValueChange, + label = { Text(text = label, color = textColor) }, + placeholder = { Text(text = placeholder, color = textColor.copy(alpha = 0.4f)) }, + modifier = modifier + .fillMaxWidth() + .padding(vertical = 4.dp), + singleLine = true, + enabled = enabled, + trailingIcon = trailingIconView, + visualTransformation = if (isPassword && !passwordVisible) PasswordVisualTransformation() else VisualTransformation.None, + keyboardOptions = KeyboardOptions(keyboardType = if (isPassword) KeyboardType.Password else KeyboardType.Text), + colors = TextFieldDefaults.colors( + focusedContainerColor = containerColor, + unfocusedContainerColor = containerColor, + disabledContainerColor = containerColor.copy(alpha = 0.5f), + focusedIndicatorColor = focusedBorderColor, + unfocusedIndicatorColor = unfocusedBorderColor, + cursorColor = focusedBorderColor, + focusedTextColor = textColor, + unfocusedTextColor = textColor + ), + shape = MaterialTheme.shapes.medium + ) + } + } +} + +@Preview(showBackground = true) +@Composable +fun Preview_Light_CommonTextFields() { + MaterialTheme { + Column { + CommonTextField( + value = "Example@naver.com", + onValueChange = {}, + label = "이메일 입력", + placeholder = "Example@naver.com", + variant = TextFieldVariant.Outlined + ) + CommonTextField( + value = "", + onValueChange = {}, + label = "비밀번호 입력", + placeholder = "비밀번호 입력", + isPassword = true, + variant = TextFieldVariant.Outlined + ) + } + } +} + +@Preview(showBackground = true) +@Composable +fun Preview_Dark_CommonTextFields() { + MaterialTheme(colorScheme = darkColorScheme()) { + Column { + CommonTextField( + value = "Example@naver.com", + onValueChange = {}, + label = "이메일 입력", + placeholder = "Example@naver.com", + variant = TextFieldVariant.Filled + ) + CommonTextField( + value = "", + onValueChange = {}, + label = "비밀번호 입력", + placeholder = "비밀번호 입력", + isPassword = true, + variant = TextFieldVariant.Filled + ) + } + } +} \ No newline at end of file From bf4ea77e9cf254d71d1ec9621cb4d4e03975e89a Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Sat, 11 Oct 2025 00:36:32 +0900 Subject: [PATCH 11/88] =?UTF-8?q?#8=20[FIX]=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sampoom/android/app/navigation/AppNavHost.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index b5c7e63..3368d4b 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -76,7 +76,7 @@ fun MainScreen( val navController = rememberNavController() Scaffold( - floatingActionButton = { FloatingActionButton(parentNavController) }, + floatingActionButton = { PartsFab(parentNavController) }, bottomBar = { BottomNavigationBar(navController) } ) { innerPadding -> NavHost( @@ -93,7 +93,7 @@ fun MainScreen( } @Composable -fun FloatingActionButton(navController: NavHostController) { +fun PartsFab(navController: NavHostController) { FloatingActionButton( onClick = { navController.navigate(ROUTE_PARTS) { From 1aee327bbdfc4e5e59e02c141d530ae4609d5f61 Mon Sep 17 00:00:00 2001 From: Choosla Date: Tue, 14 Oct 2025 10:48:11 +0900 Subject: [PATCH 12/88] chore: Apply batch updates from central configuration --- .github/workflows/pr-reminder.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-reminder.yml b/.github/workflows/pr-reminder.yml index 9190e01..928e790 100644 --- a/.github/workflows/pr-reminder.yml +++ b/.github/workflows/pr-reminder.yml @@ -2,7 +2,7 @@ name: PR Reminder on: schedule: - - cron: "0 0,5,8 * * *" # 아침 9시, 오후 2시, 오후 5시에 실행 (UTC 기준으로 설정해서 한국 시간에 맞춤) + - cron: "47 23,4,7,8, 10 * * *" # 아침 8시 47분, 오후 2시 47분, 오후 4시 47분, 오후 5시 47분, 오후 7시 47분 에 실행 (UTC 기준으로 설정해서 한국 시간에 맞춤) workflow_dispatch: jobs: From ac9c71e8314d1bd3046872375c64fa48a460641a Mon Sep 17 00:00:00 2001 From: Choosla Date: Wed, 15 Oct 2025 15:48:39 +0900 Subject: [PATCH 13/88] chore: Apply batch updates from central configuration --- .github/workflows/pr-reminder.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-reminder.yml b/.github/workflows/pr-reminder.yml index 928e790..d2410b3 100644 --- a/.github/workflows/pr-reminder.yml +++ b/.github/workflows/pr-reminder.yml @@ -2,7 +2,7 @@ name: PR Reminder on: schedule: - - cron: "47 23,4,7,8, 10 * * *" # 아침 8시 47분, 오후 2시 47분, 오후 4시 47분, 오후 5시 47분, 오후 7시 47분 에 실행 (UTC 기준으로 설정해서 한국 시간에 맞춤) + - cron: "47 23,4,7,8,10 * * *" # 아침 8시 47분, 오후 2시 47분, 오후 4시 47분, 오후 5시 47분, 오후 7시 47분 에 실행 (UTC 기준으로 설정해서 한국 시간에 맞춤) workflow_dispatch: jobs: From 989065dc891bb8a588be7fbec5c9be3fb88d357a Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Wed, 15 Oct 2025 19:49:40 +0900 Subject: [PATCH 14/88] =?UTF-8?q?[FEAT]=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/AppNavHost.kt | 21 +- .../android/core/network/ErrorHandling.kt | 26 +++ .../android/core/network/NetworkModule.kt | 2 +- .../android/core/ui/component/CommonButton.kt | 94 ++++---- .../core/ui/component/CommonSnackBar.kt | 113 ++++++++++ .../core/ui/component/CommonTextField.kt | 83 ++++--- .../sampoom/android/core/ui/theme/Color.kt | 48 +++- .../sampoom/android/core/ui/theme/Theme.kt | 12 +- .../com/sampoom/android/core/ui/theme/Type.kt | 47 ++-- .../data/local/preferences/AuthPreferences.kt | 20 +- .../feature/auth/data/mapper/AuthMappers.kt | 4 +- .../feature/auth/data/remote/api/AuthApi.kt | 12 +- .../auth/data/remote/dto/LoginResponseDto.kt | 10 + .../auth/data/remote/dto/SignUpRequestDto.kt | 10 + .../auth/data/remote/dto/SignUpResponseDto.kt | 7 + .../feature/auth/data/remote/dto/UserDto.kt | 8 - .../data/repository/AuthRepositoryImpl.kt | 25 ++- .../feature/auth/domain/AuthValidator.kt | 72 ++++++ .../android/feature/auth/domain/model/User.kt | 8 +- .../auth/domain/repository/AuthRepository.kt | 9 + .../{SignInUseCase.kt => LoginUseCase.kt} | 5 +- .../auth/domain/usecase/SignUpUseCase.kt | 25 +++ .../android/feature/auth/ui/LoginScreen.kt | 165 +++++++++++--- .../android/feature/auth/ui/LoginUiState.kt | 13 +- .../android/feature/auth/ui/LoginViewModel.kt | 67 +++++- .../android/feature/auth/ui/SignUpScreen.kt | 209 ++++++++++++++++++ .../android/feature/auth/ui/SignUpUiEvent.kt | 11 + .../android/feature/auth/ui/SignUpUiState.kt | 37 ++++ .../feature/auth/ui/SignUpViewModel.kt | 156 +++++++++++++ app/src/main/res/drawable/ic_arrow_back.xml | 5 + app/src/main/res/drawable/oneline_logo.xml | 12 + app/src/main/res/drawable/outline_close.xml | 5 + app/src/main/res/drawable/square_logo.xml | 12 + app/src/main/res/font/gmarket_sans_bold.otf | Bin 0 -> 889708 bytes app/src/main/res/font/gmarket_sans_light.otf | Bin 0 -> 842968 bytes app/src/main/res/font/gmarket_sans_medium.otf | Bin 0 -> 868048 bytes app/src/main/res/values-night/colors.xml | 28 ++- app/src/main/res/values/colors.xml | 28 ++- app/src/main/res/values/strings.xml | 38 +++- 39 files changed, 1250 insertions(+), 197 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/core/network/ErrorHandling.kt create mode 100644 app/src/main/java/com/sampoom/android/core/ui/component/CommonSnackBar.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginResponseDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpRequestDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpResponseDto.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UserDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/domain/AuthValidator.kt rename app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/{SignInUseCase.kt => LoginUseCase.kt} (78%) create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignUpUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt create mode 100644 app/src/main/res/drawable/ic_arrow_back.xml create mode 100644 app/src/main/res/drawable/oneline_logo.xml create mode 100644 app/src/main/res/drawable/outline_close.xml create mode 100644 app/src/main/res/drawable/square_logo.xml create mode 100644 app/src/main/res/font/gmarket_sans_bold.otf create mode 100644 app/src/main/res/font/gmarket_sans_light.otf create mode 100644 app/src/main/res/font/gmarket_sans_medium.otf diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 3368d4b..2008a79 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -19,9 +19,11 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import com.sampoom.android.R import com.sampoom.android.feature.auth.ui.LoginScreen +import com.sampoom.android.feature.auth.ui.SignUpScreen import com.sampoom.android.feature.part.ui.PartScreen const val ROUTE_LOGIN = "login" +const val ROUTE_SIGNUP = "signup" const val ROUTE_HOME = "home" // Main Screen @@ -51,7 +53,7 @@ fun AppNavHost() { val navController = rememberNavController() // TODO: 임시 로그인 상태 확인 -> AuthRepository에서 확인하도록 변경 - val isLoggedIn = true + val isLoggedIn = false NavHost( navController = navController, @@ -62,7 +64,22 @@ fun AppNavHost() { navController.navigate(ROUTE_HOME) { popUpTo(ROUTE_LOGIN) { inclusive = true } // 로그인 화면 스택 제거 } - }) + }, + onNavigateSignUp = { + navController.navigate(ROUTE_SIGNUP) + }) + } + composable(ROUTE_SIGNUP) { + SignUpScreen( + onSuccess = { + navController.navigate(ROUTE_HOME) { + popUpTo(ROUTE_SIGNUP) { inclusive = true } + } + }, + onNavigateBack = { + navController.navigateUp() + } + ) } composable(ROUTE_HOME) { MainScreen(navController) } composable(ROUTE_PARTS) { PartScreen() } diff --git a/app/src/main/java/com/sampoom/android/core/network/ErrorHandling.kt b/app/src/main/java/com/sampoom/android/core/network/ErrorHandling.kt new file mode 100644 index 0000000..23d3ae5 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/network/ErrorHandling.kt @@ -0,0 +1,26 @@ +package com.sampoom.android.core.network + +import com.google.gson.Gson +import com.google.gson.JsonSyntaxException +import retrofit2.HttpException + +data class ApiErrorResponse( + val code: Int? = null, + val message: String? = null +) + +fun Throwable.serverMessageOrNull(): String? { + if (this is HttpException) { + val errorBody = response()?.errorBody()?.string() ?: return null + return try { + Gson().fromJson(errorBody, ApiErrorResponse::class.java).message + } catch (_: JsonSyntaxException) { + null + } catch (_: Exception) { + null + } + } + return null +} + + diff --git a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt index 4884ee1..93cef46 100644 --- a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt +++ b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt @@ -17,7 +17,7 @@ object NetworkModule { @Provides @Singleton fun provideRetrofit(client: OkHttpClient): Retrofit = Retrofit.Builder() - .baseUrl("http://10.0.2.2:8080/api/") + .baseUrl("https://sampoom.store/api/") .client(client) .addConverterFactory(GsonConverterFactory.create()) .build() diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt b/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt index a9ba4d0..077e436 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt @@ -1,6 +1,9 @@ package com.sampoom.android.core.ui.component +import android.R.attr.onClick +import android.R.attr.text import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.Button @@ -18,6 +21,10 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.sampoom.android.core.ui.theme.Main500 +import com.sampoom.android.core.ui.theme.White +import com.sampoom.android.core.ui.theme.disableColor +import com.sampoom.android.core.ui.theme.textSecondaryColor /** * Sampoom common button with multiple visual variants. @@ -40,15 +47,14 @@ import androidx.compose.ui.unit.dp */ @Composable fun CommonButton( - text: String, modifier: Modifier = Modifier, enabled: Boolean = true, variant: ButtonVariant = ButtonVariant.Primary, size: ButtonSize = ButtonSize.Large, leadingIcon: (@Composable (() -> Unit))? = null, - onClick: () -> Unit + onClick: () -> Unit, + content: @Composable RowScope.() -> Unit ) { - val cs = MaterialTheme.colorScheme val shape = MaterialTheme.shapes.large val height = when (size) { ButtonSize.Large -> 56.dp @@ -64,21 +70,14 @@ fun CommonButton( shape = shape, modifier = modifier.height(height), colors = ButtonDefaults.buttonColors( - containerColor = cs.primary, - contentColor = cs.onPrimary, - disabledContainerColor = cs.onSurface.copy(alpha = 0.12f), - disabledContentColor = cs.onSurface.copy(alpha = 0.38f), + containerColor = Main500, + contentColor = White, + disabledContainerColor = disableColor(), + disabledContentColor = textSecondaryColor() ) ) { - if (leadingIcon != null) { - leadingIcon() - } - Text( - text = text, - style = MaterialTheme.typography.labelLarge, - fontWeight = FontWeight.SemiBold, - modifier = Modifier.padding(start = if (leadingIcon != null) 8.dp else 0.dp) - ) + if (leadingIcon != null) leadingIcon() + content() } } @@ -90,21 +89,14 @@ fun CommonButton( shape = shape, modifier = modifier.height(height), colors = ButtonDefaults.filledTonalButtonColors( - containerColor = cs.secondaryContainer, - contentColor = cs.onSecondaryContainer, - disabledContainerColor = cs.onSurface.copy(alpha = 0.08f), - disabledContentColor = cs.onSurface.copy(alpha = 0.38f) + containerColor = Main500, + contentColor = White, + disabledContainerColor = disableColor(), + disabledContentColor = textSecondaryColor() ) ) { - if (leadingIcon != null) { - leadingIcon() - } - Text( - text = text, - style = MaterialTheme.typography.labelLarge, - fontWeight = FontWeight.SemiBold, - modifier = Modifier.padding(start = if (leadingIcon != null) 8.dp else 0.dp) - ) + if (leadingIcon != null) leadingIcon() + content() } } @@ -115,17 +107,13 @@ fun CommonButton( enabled = enabled, shape = shape, modifier = modifier.height(height), - border = BorderStroke(1.dp, cs.primary), + border = BorderStroke(1.dp, Main500), colors = ButtonDefaults.outlinedButtonColors( - contentColor = cs.primary, - disabledContentColor = cs.onSurface.copy(alpha = 0.38f) + contentColor = Main500, + disabledContentColor = textSecondaryColor() ) ) { - Text( - text = text, - style = MaterialTheme.typography.labelLarge, - fontWeight = FontWeight.SemiBold - ) + content() } } @@ -137,15 +125,11 @@ fun CommonButton( shape = shape, modifier = modifier.height(height), colors = ButtonDefaults.textButtonColors( - contentColor = cs.onSurface, - disabledContentColor = cs.onSurface.copy(alpha = 0.38f) + contentColor = disableColor(), + disabledContentColor = textSecondaryColor() ) ) { - Text( - text = text, - style = MaterialTheme.typography.labelLarge, - fontWeight = FontWeight.SemiBold - ) + content() } } @@ -159,15 +143,11 @@ fun CommonButton( colors = ButtonDefaults.buttonColors( containerColor = Color(0xFF000000), contentColor = Color.White, - disabledContainerColor = cs.onSurface.copy(alpha = 0.12f), - disabledContentColor = cs.onSurface.copy(alpha = 0.38f), + disabledContainerColor = disableColor(), + disabledContentColor = textSecondaryColor() ) ) { - Text( - text = text, - style = MaterialTheme.typography.labelLarge, - fontWeight = FontWeight.SemiBold - ) + content() } } } @@ -197,7 +177,7 @@ enum class ButtonSize { Large, Medium, Small } private fun CommonButtonPreview_All() { // Primary CommonButton( - text = "Button", + content = { Text("Button", fontWeight = FontWeight.Bold) }, variant = ButtonVariant.Primary, onClick = {} ) @@ -207,7 +187,7 @@ private fun CommonButtonPreview_All() { @Composable private fun CommonButtonPreview_Primary_WithIcon() { CommonButton( - text = "Button", + content = { Text("Button", fontWeight = FontWeight.Bold) }, variant = ButtonVariant.Primary, leadingIcon = { Icon(painterResource(android.R.drawable.ic_menu_call), contentDescription = null) }, onClick = {} @@ -218,7 +198,7 @@ private fun CommonButtonPreview_Primary_WithIcon() { @Composable private fun CommonButtonPreview_Tonal() { CommonButton( - text = "Button", + content = { Text("Button", fontWeight = FontWeight.Bold) }, variant = ButtonVariant.Secondary, onClick = {} ) @@ -228,7 +208,7 @@ private fun CommonButtonPreview_Tonal() { @Composable private fun CommonButtonPreview_Outlined() { CommonButton( - text = "Button", + content = { Text("Button", fontWeight = FontWeight.Bold) }, variant = ButtonVariant.Outlined, onClick = {} ) @@ -238,7 +218,7 @@ private fun CommonButtonPreview_Outlined() { @Composable private fun CommonButtonPreview_Ghost() { CommonButton( - text = "Button", + content = { Text("Button", fontWeight = FontWeight.Bold) }, variant = ButtonVariant.Ghost, onClick = {} ) @@ -248,7 +228,7 @@ private fun CommonButtonPreview_Ghost() { @Composable private fun CommonButtonPreview_Neutral_Disabled() { CommonButton( - text = "Button", + content = { Text("Button", fontWeight = FontWeight.Bold) }, variant = ButtonVariant.Neutral, enabled = false, onClick = {} diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/CommonSnackBar.kt b/app/src/main/java/com/sampoom/android/core/ui/component/CommonSnackBar.kt new file mode 100644 index 0000000..eb1e478 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/ui/component/CommonSnackBar.kt @@ -0,0 +1,113 @@ +package com.sampoom.android.core.ui.component + +import androidx.compose.material3.SnackbarDuration +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.SnackbarResult +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.remember +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.Dp +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.statusBars +import com.sampoom.android.core.ui.theme.backgroundCardColor +import com.sampoom.android.core.ui.theme.textColor +import androidx.compose.material3.Surface +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.IconButton +import androidx.compose.material3.Icon +import androidx.compose.ui.res.painterResource +import com.sampoom.android.R +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton + +@Composable +fun rememberCommonSnackBarHostState(): SnackbarHostState = remember { SnackbarHostState() } + +@Composable +fun ShowErrorSnackBar( + errorMessage: String?, + snackBarHostState: SnackbarHostState, + onConsumed: () -> Unit, + actionLabel: String? = null, + onAction: (() -> Unit)? = null, + duration: SnackbarDuration = SnackbarDuration.Short +) { + LaunchedEffect(errorMessage) { + val message = errorMessage ?: return@LaunchedEffect + val result = snackBarHostState.showSnackbar( + message = message, + actionLabel = actionLabel, + withDismissAction = true, + duration = duration + ) + if (result == SnackbarResult.ActionPerformed) { + onAction?.invoke() + } + onConsumed() + } +} + +@Composable +fun TopSnackBarHost( + hostState: SnackbarHostState, + extraTopPadding: Dp = 0.dp, + showDismissButton: Boolean = true +) { + Box(modifier = Modifier.fillMaxSize()) { + val statusBarTop = WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + SnackbarHost( + hostState = hostState, + modifier = Modifier + .align(Alignment.TopCenter) + .padding(top = statusBarTop + extraTopPadding, start = 16.dp, end = 16.dp), + snackbar = { data -> + Surface( + color = backgroundCardColor(), + contentColor = textColor(), + shape = RoundedCornerShape(12.dp), + tonalElevation = 6.dp, + ) { + Row( + modifier = Modifier + .padding(horizontal = 16.dp, vertical = 8.dp) + .wrapContentWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Text(data.visuals.message) + Spacer(Modifier.width(12.dp)) + val label = data.visuals.actionLabel + if (label != null) { + TextButton(onClick = { data.performAction() }) { + Text(text = label, color = textColor()) + } + Spacer(Modifier.width(8.dp)) + } + if (showDismissButton) { + IconButton(onClick = { data.dismiss() }) { + Icon( + painter = painterResource(id = R.drawable.outline_close), + contentDescription = null, + tint = textColor() + ) + } + } + } + } + } + ) + } +} + + diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt b/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt index 52ba4bf..51d8feb 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt @@ -1,10 +1,13 @@ package com.sampoom.android.core.ui.component +import android.R.attr.singleLine +import android.R.attr.text import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.text.input.InputTransformation.Companion.keyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Visibility import androidx.compose.material.icons.filled.VisibilityOff @@ -17,32 +20,36 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.sampoom.android.core.ui.theme.FailRed +import com.sampoom.android.core.ui.theme.Main500 +import com.sampoom.android.core.ui.theme.backgroundColor enum class TextFieldVariant { Outlined, Filled } @OptIn(ExperimentalMaterial3Api::class) @Composable fun CommonTextField( + modifier: Modifier = Modifier, value: String, onValueChange: (String) -> Unit, - label: String, placeholder: String, - modifier: Modifier = Modifier, enabled: Boolean = true, isPassword: Boolean = false, - variant: TextFieldVariant = TextFieldVariant.Outlined + variant: TextFieldVariant = TextFieldVariant.Outlined, + isError: Boolean = false, + errorMessage: String? = null ) { var passwordVisible by remember { mutableStateOf(false) } - val darkTheme = isSystemInDarkTheme() - val cs = MaterialTheme.colorScheme - val textColor = if (darkTheme) Color.White else Color.Black - val containerColor = if (variant == TextFieldVariant.Filled) { - if (darkTheme) Color(0xFF1C1C1E) else Color(0xFFF3F3F3) - } else Color.Transparent + val textColor = if (isSystemInDarkTheme()) Color.White else Color.Black + val containerColor = if (variant == TextFieldVariant.Filled) backgroundColor() else Color.Transparent - val focusedBorderColor = cs.primary - val unfocusedBorderColor = if (darkTheme) Color(0xFF666666) else Color(0xFFCCCCCC) + val focusedBorderColor = if (isError) FailRed else Main500 + val unfocusedBorderColor = when { + isError -> FailRed + isSystemInDarkTheme() -> Color(0xFF666666) + else -> Color(0xFFCCCCCC) + } val trailingIconView = if (isPassword) { @Composable { @@ -50,30 +57,43 @@ fun CommonTextField( Icon( imageVector = if (passwordVisible) Icons.Default.Visibility else Icons.Default.VisibilityOff, contentDescription = null, - tint = if (darkTheme) Color.White else Color.Black + tint = textColor ) } } } else null + // 에러 메시지 표시용 + val supportingTextView = if (isError && errorMessage != null) { + @Composable { + Text( + text = errorMessage, + color = FailRed, + style = MaterialTheme.typography.bodySmall + ) + } + } else null + when (variant) { TextFieldVariant.Outlined -> { OutlinedTextField( value = value, onValueChange = onValueChange, - label = { Text(text = label, color = textColor) }, placeholder = { Text(text = placeholder, color = textColor.copy(alpha = 0.4f)) }, modifier = modifier .fillMaxWidth() .padding(vertical = 4.dp), singleLine = true, enabled = enabled, + isError = isError, trailingIcon = trailingIconView, + supportingText = supportingTextView, visualTransformation = if (isPassword && !passwordVisible) PasswordVisualTransformation() else VisualTransformation.None, keyboardOptions = KeyboardOptions(keyboardType = if (isPassword) KeyboardType.Password else KeyboardType.Text), colors = OutlinedTextFieldDefaults.colors( focusedBorderColor = focusedBorderColor, unfocusedBorderColor = unfocusedBorderColor, + errorBorderColor = FailRed, disabledBorderColor = Color.Gray, focusedLabelColor = focusedBorderColor, unfocusedLabelColor = textColor.copy(alpha = 0.7f), @@ -81,7 +101,7 @@ fun CommonTextField( focusedTextColor = textColor, unfocusedTextColor = textColor ), - shape = MaterialTheme.shapes.medium + shape = MaterialTheme.shapes.large ) } @@ -89,19 +109,21 @@ fun CommonTextField( TextField( value = value, onValueChange = onValueChange, - label = { Text(text = label, color = textColor) }, placeholder = { Text(text = placeholder, color = textColor.copy(alpha = 0.4f)) }, modifier = modifier .fillMaxWidth() .padding(vertical = 4.dp), singleLine = true, enabled = enabled, + isError = isError, trailingIcon = trailingIconView, + supportingText = supportingTextView, visualTransformation = if (isPassword && !passwordVisible) PasswordVisualTransformation() else VisualTransformation.None, keyboardOptions = KeyboardOptions(keyboardType = if (isPassword) KeyboardType.Password else KeyboardType.Text), colors = TextFieldDefaults.colors( focusedContainerColor = containerColor, unfocusedContainerColor = containerColor, + errorContainerColor = FailRed, disabledContainerColor = containerColor.copy(alpha = 0.5f), focusedIndicatorColor = focusedBorderColor, unfocusedIndicatorColor = unfocusedBorderColor, @@ -109,7 +131,7 @@ fun CommonTextField( focusedTextColor = textColor, unfocusedTextColor = textColor ), - shape = MaterialTheme.shapes.medium + shape = MaterialTheme.shapes.large ) } } @@ -123,14 +145,12 @@ fun Preview_Light_CommonTextFields() { CommonTextField( value = "Example@naver.com", onValueChange = {}, - label = "이메일 입력", placeholder = "Example@naver.com", variant = TextFieldVariant.Outlined ) CommonTextField( value = "", onValueChange = {}, - label = "비밀번호 입력", placeholder = "비밀번호 입력", isPassword = true, variant = TextFieldVariant.Outlined @@ -144,20 +164,33 @@ fun Preview_Light_CommonTextFields() { fun Preview_Dark_CommonTextFields() { MaterialTheme(colorScheme = darkColorScheme()) { Column { + // 정상 CommonTextField( value = "Example@naver.com", onValueChange = {}, - label = "이메일 입력", - placeholder = "Example@naver.com", - variant = TextFieldVariant.Filled + placeholder = "이메일", + variant = TextFieldVariant.Outlined ) + + // 에러 CommonTextField( - value = "", + value = "invalid", onValueChange = {}, - label = "비밀번호 입력", - placeholder = "비밀번호 입력", + placeholder = "이메일", + variant = TextFieldVariant.Outlined, + isError = true, + errorMessage = "올바른 이메일 형식이 아닙니다" + ) + + // 비밀번호 에러 + CommonTextField( + value = "123", + onValueChange = {}, + placeholder = "비밀번호", isPassword = true, - variant = TextFieldVariant.Filled + variant = TextFieldVariant.Outlined, + isError = true, + errorMessage = "비밀번호는 최소 8자 이상이어야 합니다" ) } } diff --git a/app/src/main/java/com/sampoom/android/core/ui/theme/Color.kt b/app/src/main/java/com/sampoom/android/core/ui/theme/Color.kt index 14c8259..72cdc9c 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/theme/Color.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/theme/Color.kt @@ -1,11 +1,47 @@ package com.sampoom.android.core.ui.theme +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color -val Purple80 = Color(0xFFD0BCFF) -val PurpleGrey80 = Color(0xFFCCC2DC) -val Pink80 = Color(0xFFEFB8C8) +val White = Color(0xFFFFFFFF) +val Black = Color(0xFF000000) -val Purple40 = Color(0xFF6650a4) -val PurpleGrey40 = Color(0xFF625b71) -val Pink40 = Color(0xFF7D5260) \ No newline at end of file +val SuccessGreen = Color(0xFF10B981) +val FailRed = Color(0xFFFF6C6C) +val WaitYellow = Color(0xFFF59E0B) + +val Grey400 = Color(0xFF444444) +val Grey300 = Color(0xFF7C7C7C) +val Grey200 = Color(0xFFCCCCCC) +val Grey100 = Color(0xFFE9EAEC) + +val BgWhite = Color(0xFFF5F5F5) +val BgCardWhite = Color(0xFFFFFFFF) +val BgBlack = Color(0xFF17181B) +val BgCardBlack = Color(0xFF36393F) + +val Main900 = Color(0xFF1F1F5C) +val Main800 = Color(0xFF333399) +val Main700 = Color(0xFF4C4CBB) +val Main600 = Color(0xFF6666DD) +val Main500 = Color(0xFF8080FF) +val Main400 = Color(0xFF9999FF) +val Main300 = Color(0xFFB3B3FF) +val Main200 = Color(0xFFCCCCFF) +val Main100 = Color(0xFFE6E6FF) + +@Composable +fun backgroundColor() = if (isSystemInDarkTheme()) BgBlack else BgWhite + +@Composable +fun backgroundCardColor() = if (isSystemInDarkTheme()) BgCardBlack else BgCardWhite + +@Composable +fun textColor() = if (isSystemInDarkTheme()) BgWhite else BgCardBlack + +@Composable +fun textSecondaryColor() = if (isSystemInDarkTheme()) Grey200 else Grey300 + +@Composable +fun disableColor() = if (isSystemInDarkTheme()) Grey400 else Grey100 \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/ui/theme/Theme.kt b/app/src/main/java/com/sampoom/android/core/ui/theme/Theme.kt index 26b2837..9c55a3d 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/theme/Theme.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/theme/Theme.kt @@ -11,15 +11,15 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext private val DarkColorScheme = darkColorScheme( - primary = Purple80, - secondary = PurpleGrey80, - tertiary = Pink80 + primary = Main500, + secondary = Main300, + tertiary = Main100 ) private val LightColorScheme = lightColorScheme( - primary = Purple40, - secondary = PurpleGrey40, - tertiary = Pink40 + primary = Main500, + secondary = Main300, + tertiary = Main100 /* Other default colors to override background = Color(0xFFFFFBFE), diff --git a/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt b/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt index 6a3a086..0d4c3a4 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt @@ -1,34 +1,35 @@ package com.sampoom.android.core.ui.theme +import android.R.attr.fontFamily import androidx.compose.material3.Typography import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.sp +import com.sampoom.android.R + +val GmarketSansFamily = FontFamily( + Font(R.font.gmarket_sans_light, FontWeight.Light), + Font(R.font.gmarket_sans_medium, FontWeight.Normal), + Font(R.font.gmarket_sans_bold, FontWeight.Bold) +) // Set of Material typography styles to start with val Typography = Typography( - bodyLarge = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 16.sp, - lineHeight = 24.sp, - letterSpacing = 0.5.sp - ) - /* Other default text styles to override - titleLarge = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 22.sp, - lineHeight = 28.sp, - letterSpacing = 0.sp - ), - labelSmall = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Medium, - fontSize = 11.sp, - lineHeight = 16.sp, - letterSpacing = 0.5.sp - ) - */ + displayLarge = TextStyle(fontFamily = GmarketSansFamily), + displayMedium = TextStyle(fontFamily = GmarketSansFamily), + displaySmall = TextStyle(fontFamily = GmarketSansFamily), + headlineLarge = TextStyle(fontFamily = GmarketSansFamily), + headlineMedium = TextStyle(fontFamily = GmarketSansFamily), + headlineSmall = TextStyle(fontFamily = GmarketSansFamily), + titleLarge = TextStyle(fontFamily = GmarketSansFamily), + titleMedium = TextStyle(fontFamily = GmarketSansFamily), + titleSmall = TextStyle(fontFamily = GmarketSansFamily), + bodyLarge = TextStyle(fontFamily = GmarketSansFamily), + bodyMedium = TextStyle(fontFamily = GmarketSansFamily), + bodySmall = TextStyle(fontFamily = GmarketSansFamily), + labelLarge = TextStyle(fontFamily = GmarketSansFamily), + labelMedium = TextStyle(fontFamily = GmarketSansFamily), + labelSmall = TextStyle(fontFamily = GmarketSansFamily) ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/local/preferences/AuthPreferences.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/local/preferences/AuthPreferences.kt index 8345a3f..9dc479f 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/local/preferences/AuthPreferences.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/local/preferences/AuthPreferences.kt @@ -1,21 +1,31 @@ package com.sampoom.android.feature.auth.data.local.preferences import android.content.Context +import androidx.core.content.edit import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton @Singleton class AuthPreferences @Inject constructor( - @ApplicationContext private val context: Context + @param:ApplicationContext private val context: Context ){ private val sharedPreferences = context.getSharedPreferences("auth", Context.MODE_PRIVATE) - fun saveToken(token: String) { - sharedPreferences.edit().putString("token", token) + fun saveToken(accessToken: String, refreshToken: String) { + sharedPreferences.edit { + putString("access_token", accessToken) + putString("refresh_token", refreshToken) + } } + + fun getAccessToken(): String? = sharedPreferences.getString("access_token", null) + fun getRefreshToken(): String? = sharedPreferences.getString("refresh_token", null) + fun clear() { - sharedPreferences.edit().clear().apply() + sharedPreferences.edit { + clear().apply() + } } - fun hasToken(): Boolean = !sharedPreferences.getString("token", null).isNullOrEmpty() + fun hasToken(): Boolean = !sharedPreferences.getString("access_token", null).isNullOrEmpty() } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt index c6bf3b0..b79dea4 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt @@ -1,6 +1,6 @@ package com.sampoom.android.feature.auth.data.mapper -import com.sampoom.android.feature.auth.data.remote.dto.UserDto +import com.sampoom.android.feature.auth.data.remote.dto.LoginResponseDto import com.sampoom.android.feature.auth.domain.model.User -fun UserDto.toModel(): User = User(id, name, email, token) \ No newline at end of file +fun LoginResponseDto.toModel(): User = User(userId, userName, role, accessToken, refreshToken, expiresIn) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt index ce4be9b..74ff84f 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt @@ -1,11 +1,17 @@ package com.sampoom.android.feature.auth.data.remote.api +import com.sampoom.android.core.network.ApiResponse import com.sampoom.android.feature.auth.data.remote.dto.LoginRequestDto -import com.sampoom.android.feature.auth.data.remote.dto.UserDto +import com.sampoom.android.feature.auth.data.remote.dto.SignUpRequestDto +import com.sampoom.android.feature.auth.data.remote.dto.SignUpResponseDto +import com.sampoom.android.feature.auth.data.remote.dto.LoginResponseDto import retrofit2.http.Body import retrofit2.http.POST interface AuthApi { - @POST("auth/login") - suspend fun login(@Body body: LoginRequestDto): UserDto + @POST("login") + suspend fun login(@Body body: LoginRequestDto): ApiResponse + + @POST("signup") + suspend fun signUp(@Body body: SignUpRequestDto): ApiResponse } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginResponseDto.kt new file mode 100644 index 0000000..3d44982 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginResponseDto.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.auth.data.remote.dto + +data class LoginResponseDto( + val userId: Long, + val userName: String, + val role: String, + val accessToken: String, + val refreshToken: String, + val expiresIn: Int +) diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpRequestDto.kt new file mode 100644 index 0000000..ff24ca2 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpRequestDto.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.auth.data.remote.dto + +data class SignUpRequestDto( + val name: String, + val workspace: String, + val branch: String, + val position: String, + val email: String, + val password: String +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpResponseDto.kt new file mode 100644 index 0000000..d683a69 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpResponseDto.kt @@ -0,0 +1,7 @@ +package com.sampoom.android.feature.auth.data.remote.dto + +data class SignUpResponseDto( + val userId: Long, + val userName: String, + val email: String +) diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UserDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UserDto.kt deleted file mode 100644 index 38f07e2..0000000 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UserDto.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.sampoom.android.feature.auth.data.remote.dto - -data class UserDto( - val id: String, - val name: String, - val email: String, - val token: String -) diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt index 1d72da4..fedff45 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt @@ -4,6 +4,7 @@ import com.sampoom.android.feature.auth.data.local.preferences.AuthPreferences import com.sampoom.android.feature.auth.data.mapper.toModel import com.sampoom.android.feature.auth.data.remote.api.AuthApi import com.sampoom.android.feature.auth.data.remote.dto.LoginRequestDto +import com.sampoom.android.feature.auth.data.remote.dto.SignUpRequestDto import com.sampoom.android.feature.auth.domain.model.User import com.sampoom.android.feature.auth.domain.repository.AuthRepository import javax.inject.Inject @@ -12,13 +13,32 @@ class AuthRepositoryImpl @Inject constructor( private val api: AuthApi, private val preferences: AuthPreferences ) : AuthRepository { + override suspend fun signUp( + name: String, + workspace: String, + branch: String, + position: String, + email: String, + password: String + ): User { + api.signUp(SignUpRequestDto( + name = name, + workspace = workspace, + branch = branch, + position = position, + email = email, + password = password + )) + return signIn(email, password) + } + override suspend fun signIn( email: String, password: String ): User { val dto = api.login(LoginRequestDto(email, password)) - preferences.saveToken(dto.token) - return dto.toModel() + preferences.saveToken(dto.data.accessToken, dto.data.refreshToken) + return dto.data.toModel() } override suspend fun signOut() { @@ -26,5 +46,4 @@ class AuthRepositoryImpl @Inject constructor( } override fun isSignedIn(): Boolean = preferences.hasToken() - } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/AuthValidator.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/AuthValidator.kt new file mode 100644 index 0000000..b7c4516 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/AuthValidator.kt @@ -0,0 +1,72 @@ +package com.sampoom.android.feature.auth.domain + +import com.sampoom.android.R + +object AuthValidator { + // 이메일 형식 검증 + fun validateEmail(email: String): ValidationResult { + if (email.isBlank()) { + return ValidationResult.Error(R.string.validation_email_required) + } + + val emailPattern = "[a-zA-Z0-9._-]+@[a-z]+\\.+[a-z]+".toRegex() + if (!email.matches(emailPattern)) { + return ValidationResult.Error(R.string.validation_email_invalid) + } + + return ValidationResult.Success + } + + // 비밀번호 검증 (8-30자, 영문+숫자+특수문자 각 1개 이상) + fun validatePassword(password: String): ValidationResult { + if (password.isBlank()) { + return ValidationResult.Error(R.string.validation_password_required) + } + + if (password.length < 8) { + return ValidationResult.Error(R.string.validation_password_min_length) + } + + if (password.length > 30) { + return ValidationResult.Error(R.string.validation_password_max_length) + } + + val hasLetter = password.any { it.isLetter() } + val hasDigit = password.any { it.isDigit() } + val hasSpecial = password.any { !it.isLetterOrDigit() } + + if (!hasLetter || !hasDigit || !hasSpecial) { + return ValidationResult.Error(R.string.validation_password_complexity) + } + + return ValidationResult.Success + } + + // 비밀번호 확인 검증 + fun validatePasswordCheck(password: String, passwordConfirm: String): ValidationResult { + if (passwordConfirm.isBlank()) { + return ValidationResult.Error(R.string.validation_password_confirm_required) + } + + if (password != passwordConfirm) { + return ValidationResult.Error(R.string.validation_password_mismatch) + } + + return ValidationResult.Success + } + + // 일반 필드 검증 (이름, 지점, 직책 등) + fun validateNotEmpty(value: String, fieldName: String): ValidationResult { + if (value.isBlank()) { + return ValidationResult.ErrorWithArgs(R.string.validation_field_required, fieldName) + } + return ValidationResult.Success + } +} + +// 검증 결과 +sealed class ValidationResult { + object Success : ValidationResult() + data class Error(val messageResId: Int) : ValidationResult() + data class ErrorWithArgs(val messageResId: Int, val args: Any) : ValidationResult() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt index b9e6e4b..d8479ae 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt @@ -1,8 +1,10 @@ package com.sampoom.android.feature.auth.domain.model data class User( - val id: String, + val id: Long, val name: String, - val email: String, - val token: String + val role: String, + val accessToken: String, + val refreshToken: String, + val expiresIn: Int ) diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt index f5fccd8..747e985 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt @@ -3,6 +3,15 @@ package com.sampoom.android.feature.auth.domain.repository import com.sampoom.android.feature.auth.domain.model.User interface AuthRepository { + suspend fun signUp( + name: String, + workspace: String, + branch: String, + position: String, + email: String, + password: String + ): User + suspend fun signIn(email: String, password: String): User suspend fun signOut() fun isSignedIn(): Boolean diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignInUseCase.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/LoginUseCase.kt similarity index 78% rename from app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignInUseCase.kt rename to app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/LoginUseCase.kt index 630b4e2..d31282c 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignInUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/LoginUseCase.kt @@ -4,8 +4,9 @@ import com.sampoom.android.feature.auth.domain.model.User import com.sampoom.android.feature.auth.domain.repository.AuthRepository import javax.inject.Inject -class SignInUseCase @Inject constructor( +class LoginUseCase @Inject constructor( private val repository: AuthRepository ) { - suspend operator fun invoke(email: String, password: String): User = repository.signIn(email, password) + suspend operator fun invoke(email: String, password: String): User = + repository.signIn(email, password) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignUpUseCase.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignUpUseCase.kt new file mode 100644 index 0000000..9fa4ddd --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignUpUseCase.kt @@ -0,0 +1,25 @@ +package com.sampoom.android.feature.auth.domain.usecase + +import com.sampoom.android.feature.auth.domain.model.User +import com.sampoom.android.feature.auth.domain.repository.AuthRepository +import javax.inject.Inject + +class SignUpUseCase @Inject constructor( + private val repository: AuthRepository +) { + suspend operator fun invoke( + name: String, + workspace: String, + branch: String, + position: String, + email: String, + password: String + ): User = repository.signUp( + name = name, + workspace = workspace, + branch = branch, + position = position, + email = email, + password = password + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt index 8efc1f6..96fa07a 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt @@ -1,68 +1,167 @@ package com.sampoom.android.feature.auth.ui +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.ime +import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Button +import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import com.sampoom.android.R +import com.sampoom.android.core.ui.component.CommonButton +import com.sampoom.android.core.ui.component.CommonTextField +import com.sampoom.android.core.ui.theme.Main500 +import com.sampoom.android.core.ui.component.ShowErrorSnackBar +import com.sampoom.android.core.ui.component.rememberCommonSnackBarHostState +import com.sampoom.android.core.ui.component.TopSnackBarHost @Composable fun LoginScreen( onSuccess: () -> Unit, + onNavigateSignUp: () -> Unit, viewModel: LoginViewModel = hiltViewModel() ) { + val emailLabel = stringResource(R.string.login_title_email) + val passwordLabel = stringResource(R.string.login_title_password) + val errorLabel = stringResource(R.string.common_error) + + LaunchedEffect(emailLabel, passwordLabel, errorLabel) { + viewModel.bindLabel(emailLabel, passwordLabel, errorLabel) + } + val state by viewModel.state.collectAsState() if (state.success) onSuccess() - Scaffold { innerPadding -> - Column( - Modifier + val snackBarHostState = rememberCommonSnackBarHostState() + ShowErrorSnackBar( + errorMessage = state.error, + snackBarHostState = snackBarHostState, + onConsumed = { viewModel.consumeError() } + ) + Scaffold( +// contentWindowInsets = WindowInsets.ime, +// snackbarHost = { CommonSnackBarHost(snackBarHostState) } + ) { innerPadding -> + val focusManager = LocalFocusManager.current + Box( // 터치 감지용 컨테이너 + modifier = Modifier .fillMaxSize() - .padding(innerPadding) - .padding(24.dp) + .clickable( // 빈 공간 터치 시 포커스 해제 + indication = null, // 터치 ripple 제거 + interactionSource = remember { MutableInteractionSource() } + ) { + focusManager.clearFocus() + } ) { - Text(stringResource(R.string.login_title), style = MaterialTheme.typography.headlineMedium) - Spacer(Modifier.height(16.dp)) - OutlinedTextField( - value = state.email, - onValueChange = { viewModel.onEvent(LoginUiEvent.EmailChanged(it)) }, - label = { Text(stringResource(R.string.login_placeholder_email)) }, - modifier = Modifier.fillMaxWidth() - ) - Spacer(Modifier.height(8.dp)) - OutlinedTextField( - value = state.password, - onValueChange = { viewModel.onEvent(LoginUiEvent.PasswordChanged(it)) }, - label = { Text(stringResource(R.string.login_placeholder_password)) }, - visualTransformation = PasswordVisualTransformation(), - modifier = Modifier.fillMaxWidth() - ) - Spacer(Modifier.height(16.dp)) - Button( - onClick = { viewModel.onEvent(LoginUiEvent.Submit) }, - enabled = !state.loading, - modifier = Modifier.fillMaxWidth() - ) { Text(if (state.loading) stringResource(R.string.login_button_login_loading) else stringResource(R.string.login_button_login)) } - - state.error?.let { + Column( + Modifier + .fillMaxSize() + .imePadding() + .padding(innerPadding) + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Spacer(Modifier.weight(1f)) + Image( + painter = painterResource(id = R.drawable.square_logo), + contentDescription = stringResource(R.string.app_name) + ) + Spacer(Modifier.height(48.dp)) + CommonTextField( + modifier = Modifier.fillMaxWidth(), + value = state.email, + onValueChange = { viewModel.onEvent(LoginUiEvent.EmailChanged(it)) }, + placeholder = stringResource(R.string.login_placeholder_email), + isError = state.emailError != null, + errorMessage = state.emailError + ) Spacer(Modifier.height(8.dp)) - Text(it, color = MaterialTheme.colorScheme.error) + CommonTextField( + modifier = Modifier.fillMaxWidth(), + value = state.password, + onValueChange = { viewModel.onEvent(LoginUiEvent.PasswordChanged(it)) }, + placeholder = stringResource(R.string.login_placeholder_password), + isPassword = true, + isError = state.passwordError != null, + errorMessage = state.passwordError + ) + Spacer(Modifier.height(48.dp)) + CommonButton( + onClick = { viewModel.onEvent(LoginUiEvent.Submit) }, + enabled = state.isValid && !state.loading, + modifier = Modifier.fillMaxWidth() + ) { + Text( + if (state.loading) stringResource(R.string.login_button_login_loading) + else stringResource(R.string.login_button_login) + ) + } + + + Spacer(Modifier.weight(1f)) + + val annotatedText = buildAnnotatedString { + append(stringResource(R.string.login_need_account)) + + // 클릭 가능한 회원가입 텍스트 + pushStringAnnotation(tag = "SIGNUP", annotation = "signup") + withStyle( + style = SpanStyle( + color = Main500, // 원하는 색상 + textDecoration = TextDecoration.Underline + ) + ) { + append(stringResource(R.string.login_signup)) + } + append(stringResource(R.string.login_do)) + pop() + } + + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = annotatedText, + modifier = Modifier + .padding(vertical = 24.dp) + .clickable { onNavigateSignUp() }, + style = MaterialTheme.typography.bodyMedium.copy(textAlign = TextAlign.Center), + ) + } + + // per-screen inline error removed in favor of snackbar } } + TopSnackBarHost(snackBarHostState, extraTopPadding = 16.dp) } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiState.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiState.kt index dd36855..2546cab 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiState.kt @@ -3,7 +3,18 @@ package com.sampoom.android.feature.auth.ui data class LoginUiState( val email: String = "", val password: String = "", + + // Error message + val emailError: String? = null, + val passwordError: String? = null, + val loading: Boolean = false, val error: String? = null, val success: Boolean = false -) +) { + val isValid: Boolean + get() = email.isNotBlank() && + password.isNotBlank() && + emailError == null && + passwordError == null +} diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt index c92c743..997312c 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt @@ -1,9 +1,13 @@ package com.sampoom.android.feature.auth.ui +import android.app.Application import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sampoom.android.feature.auth.domain.usecase.SignInUseCase +import com.sampoom.android.feature.auth.domain.AuthValidator +import com.sampoom.android.feature.auth.domain.ValidationResult +import com.sampoom.android.feature.auth.domain.usecase.LoginUseCase +import com.sampoom.android.core.network.serverMessageOrNull import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -13,23 +17,76 @@ import javax.inject.Inject @HiltViewModel class LoginViewModel @Inject constructor( - private val singIn: SignInUseCase + private val singIn: LoginUseCase, + private val application: Application ) : ViewModel() { private val _state = MutableStateFlow(LoginUiState()) val state: StateFlow = _state + private var emailLabel: String = "" + private var passwordLabel: String = "" + private var errorLabel: String = "" + + fun bindLabel(email: String, password: String, error: String) { + emailLabel = email + passwordLabel = password + errorLabel = error + } + fun onEvent(e: LoginUiEvent) = when (e) { - is LoginUiEvent.EmailChanged -> _state.value = _state.value.copy(email = e.email) - is LoginUiEvent.PasswordChanged -> _state.value = _state.value.copy(password = e.password) + is LoginUiEvent.EmailChanged -> { + _state.value = _state.value.copy(email = e.email) + validateEmail() + } + is LoginUiEvent.PasswordChanged -> { + _state.value = _state.value.copy(password = e.password) + validatePassword() + } LoginUiEvent.Submit -> submit() } + private fun validateEmail() { + val result = AuthValidator.validateNotEmpty(_state.value.email, emailLabel) + _state.value = _state.value.copy( + emailError = result.toErrorMessage() + ) + } + + private fun validatePassword() { + val result = AuthValidator.validateNotEmpty(_state.value.password, passwordLabel) + _state.value = _state.value.copy( + passwordError = result.toErrorMessage() + ) + } + + private fun ValidationResult.toErrorMessage(): String? { + return when (this) { + is ValidationResult.Error -> application.getString(messageResId) + is ValidationResult.ErrorWithArgs -> application.getString(messageResId, args) + ValidationResult.Success -> null + } + } + private fun submit() = viewModelScope.launch { + validateEmail() + validatePassword() + + if (!_state.value.isValid) return@launch + val s = _state.value _state.update { it.copy(loading = true, error = null) } runCatching { singIn(s.email, s.password) } .onSuccess { _state.update { it.copy(loading = false, success = true) } } - .onFailure { _state.update { it.copy(loading = false, error = it.error) } } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _state.update { + it.copy(loading = false, error = backendMessage ?: (throwable.message ?: errorLabel)) + } + } Log.d("LoginViewModel", "submit: ${_state.value}") } + + fun consumeError() { + _state.update { it.copy(error = null) } + } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt new file mode 100644 index 0000000..713ac4b --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt @@ -0,0 +1,209 @@ +package com.sampoom.android.feature.auth.ui + +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.ime +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import com.sampoom.android.R +import com.sampoom.android.core.ui.component.CommonButton +import com.sampoom.android.core.ui.component.CommonTextField +import com.sampoom.android.core.ui.component.ShowErrorSnackBar +import com.sampoom.android.core.ui.component.rememberCommonSnackBarHostState +import com.sampoom.android.core.ui.component.TopSnackBarHost + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SignUpScreen( + onSuccess: () -> Unit, + onNavigateBack: () -> Unit = {}, + viewModel: SignUpViewModel = hiltViewModel() +) { + val nameLabel = stringResource(R.string.signup_title_name) + val branchLabel = stringResource(R.string.signup_title_branch) + val positionLabel = stringResource(R.string.signup_title_position) + val errorLabel = stringResource(R.string.common_error) + + LaunchedEffect(nameLabel, branchLabel, positionLabel, errorLabel) { + viewModel.bindLabels(nameLabel, branchLabel, positionLabel, errorLabel) + } + + val state by viewModel.state.collectAsState() + val labelTextSize = 16.sp + + if (state.success) onSuccess() + val snackBarHostState = rememberCommonSnackBarHostState() + ShowErrorSnackBar( + errorMessage = state.error, + snackBarHostState = snackBarHostState, + onConsumed = { viewModel.consumeError() } + ) + Scaffold( + topBar = { + TopAppBar( + title = { Text("") }, + navigationIcon = { + IconButton(onClick = onNavigateBack) { + Icon( + painter = painterResource(id = R.drawable.ic_arrow_back), + contentDescription = stringResource(R.string.nav_back) + ) + } + } + ) + }, + contentWindowInsets = WindowInsets.ime, +// snackbarHost = { CommonSnackBarHost(snackBarHostState) } + ) { innerPadding -> + val focusManager = LocalFocusManager.current + Box( // 터치 감지용 컨테이너 + modifier = Modifier + .fillMaxSize() + .clickable( // 빈 공간 터치 시 포커스 해제 + indication = null, // 터치 ripple 제거 + interactionSource = remember { MutableInteractionSource() } + ) { + focusManager.clearFocus() + } + ) { + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .padding(innerPadding) + .padding(16.dp), + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.Center + ) { + Image( + painter = painterResource(id = R.drawable.oneline_logo), + contentDescription = stringResource(R.string.app_name) + ) + Spacer(Modifier.height(48.dp)) + Text( + text = stringResource(R.string.signup_title_name), + fontSize = labelTextSize + ) + CommonTextField( + modifier = Modifier.fillMaxWidth(), + value = state.name, + onValueChange = { viewModel.onEvent(SignUpUiEvent.NameChanged(it)) }, + placeholder = stringResource(R.string.signup_placeholder_name), + isError = state.nameError != null, + errorMessage = state.nameError + ) + Spacer(Modifier.height(8.dp)) + Text( + text = stringResource(R.string.signup_title_branch), + fontSize = labelTextSize + ) + CommonTextField( + modifier = Modifier.fillMaxWidth(), + value = state.branch, + onValueChange = { viewModel.onEvent(SignUpUiEvent.BranchChanged(it)) }, + placeholder = stringResource(R.string.signup_placeholder_branch), + isError = state.branchError != null, + errorMessage = state.branchError + ) + Spacer(Modifier.height(8.dp)) + Text( + text = stringResource(R.string.signup_title_position), + fontSize = labelTextSize + ) + CommonTextField( + modifier = Modifier.fillMaxWidth(), + value = state.position, + onValueChange = { viewModel.onEvent(SignUpUiEvent.PositionChanged(it)) }, + placeholder = stringResource(R.string.signup_placeholder_position), + isError = state.positionError != null, + errorMessage = state.positionError + ) + Spacer(Modifier.height(8.dp)) + Text( + text = stringResource(R.string.signup_title_email), + fontSize = labelTextSize + ) + CommonTextField( + modifier = Modifier.fillMaxWidth(), + value = state.email, + onValueChange = { viewModel.onEvent(SignUpUiEvent.EmailChanged(it)) }, + placeholder = stringResource(R.string.signup_placeholder_email), + isError = state.emailError != null, + errorMessage = state.emailError + ) + Spacer(Modifier.height(8.dp)) + Text( + text = stringResource(R.string.signup_title_password), + fontSize = labelTextSize + ) + CommonTextField( + modifier = Modifier.fillMaxWidth(), + value = state.password, + onValueChange = { viewModel.onEvent(SignUpUiEvent.PasswordChanged(it)) }, + placeholder = stringResource(R.string.signup_placeholder_password), + isPassword = true, + isError = state.passwordError != null, + errorMessage = state.passwordError + ) + Spacer(Modifier.height(8.dp)) + Text( + text = stringResource(R.string.signup_title_password_check), + fontSize = labelTextSize + ) + CommonTextField( + modifier = Modifier.fillMaxWidth(), + value = state.passwordCheck, + onValueChange = { viewModel.onEvent(SignUpUiEvent.PasswordCheckChanged(it)) }, + placeholder = stringResource(R.string.signup_placeholder_password_check), + isPassword = true, + isError = state.passwordCheckError != null, + errorMessage = state.passwordCheckError + ) + Spacer(Modifier.height(48.dp)) + CommonButton( + onClick = { viewModel.onEvent(SignUpUiEvent.Submit) }, + enabled = state.isValid && !state.loading, + modifier = Modifier.fillMaxWidth(), + ) { + Text( + if (state.loading) stringResource(R.string.signup_button_signup_loading) + else stringResource(R.string.signup_button_signup) + ) + } + + // per-screen inline error removed in favor of snackbar + } + } + TopSnackBarHost(snackBarHostState, extraTopPadding = 16.dp) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt new file mode 100644 index 0000000..eb8e77b --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.auth.ui + +sealed interface SignUpUiEvent { + data class NameChanged(val name: String) : SignUpUiEvent + data class BranchChanged(val branch: String) : SignUpUiEvent + data class PositionChanged(val position: String) : SignUpUiEvent + data class EmailChanged(val email: String) : SignUpUiEvent + data class PasswordChanged(val password: String) : SignUpUiEvent + data class PasswordCheckChanged(val passwordCheck: String) : SignUpUiEvent + data object Submit: SignUpUiEvent +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt new file mode 100644 index 0000000..524c1fe --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt @@ -0,0 +1,37 @@ +package com.sampoom.android.feature.auth.ui + +data class SignUpUiState( + val name: String = "", + val workspace: String = "대리점", + val branch: String = "", + val position: String = "", + val email: String = "", + val password: String = "", + val passwordCheck: String = "", + + // Error message + val nameError: String? = null, + val branchError: String? = null, + val positionError: String? = null, + val emailError: String? = null, + val passwordError: String? = null, + val passwordCheckError: String? = null, + + val loading: Boolean = false, + val error: String? = null, + val success: Boolean = false +) { + val isValid: Boolean + get() = name.isNotBlank() && + branch.isNotBlank() && + position.isNotBlank() && + email.isNotBlank() && + password.isNotBlank() && + passwordCheck.isNotBlank() && + nameError == null && + branchError == null && + positionError == null && + emailError == null && + passwordError == null && + passwordCheckError == null +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt new file mode 100644 index 0000000..70e0f79 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt @@ -0,0 +1,156 @@ +package com.sampoom.android.feature.auth.ui + +import android.app.Application +import android.util.Log +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.sampoom.android.feature.auth.domain.AuthValidator +import com.sampoom.android.feature.auth.domain.ValidationResult +import com.sampoom.android.feature.auth.domain.usecase.SignUpUseCase +import com.sampoom.android.core.network.serverMessageOrNull +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class SignUpViewModel @Inject constructor( + private val singUp: SignUpUseCase, + private val application: Application +) : ViewModel() { + private val _state = MutableStateFlow(SignUpUiState()) + val state: StateFlow = _state + + private var nameLabel: String = "" + private var branchLabel: String = "" + private var positionLabel: String = "" + private var errorLabel: String = "" + + fun bindLabels(name: String, branch: String, position: String, error: String) { + nameLabel = name + branchLabel = branch + positionLabel = position + errorLabel = error + } + + fun onEvent(e: SignUpUiEvent) = when (e) { + is SignUpUiEvent.NameChanged -> { + _state.value = _state.value.copy(name = e.name) + validateName() + } + is SignUpUiEvent.BranchChanged -> { + _state.value = _state.value.copy(branch = e.branch) + validateBranch() + } + is SignUpUiEvent.PositionChanged -> { + _state.value = _state.value.copy(position = e.position) + validatePosition() + } + is SignUpUiEvent.EmailChanged -> { + _state.value = _state.value.copy(email = e.email) + validateEmail() + } + is SignUpUiEvent.PasswordChanged -> { + _state.value = _state.value.copy(password = e.password) + validatePassword() + if (_state.value.passwordCheck.isNotBlank()) { + validatePasswordCheck() + } else { + + } + } + is SignUpUiEvent.PasswordCheckChanged -> { + _state.value = _state.value.copy(passwordCheck = e.passwordCheck) + validatePasswordCheck() + } + SignUpUiEvent.Submit -> submit() + } + + private fun validateName() { + val result = AuthValidator.validateNotEmpty(_state.value.name, nameLabel) + _state.value = _state.value.copy( + nameError = result.toErrorMessage() + ) + } + + private fun validateBranch() { + val result = AuthValidator.validateNotEmpty(_state.value.branch, branchLabel) + _state.value = _state.value.copy( + branchError = result.toErrorMessage() + ) + } + + private fun validatePosition() { + val result = AuthValidator.validateNotEmpty(_state.value.position, positionLabel) + _state.value = _state.value.copy( + positionError = result.toErrorMessage() + ) + } + + private fun validateEmail() { + val result = AuthValidator.validateEmail(_state.value.email) + _state.value = _state.value.copy( + emailError = result.toErrorMessage() + ) + } + + private fun validatePassword() { + val result = AuthValidator.validatePassword(_state.value.password) + _state.value = _state.value.copy( + passwordError = result.toErrorMessage() + ) + } + + private fun validatePasswordCheck() { + val result = AuthValidator.validatePasswordCheck(_state.value.password, _state.value.passwordCheck) + _state.value = _state.value.copy( + passwordCheckError = result.toErrorMessage() + ) + } + + private fun ValidationResult.toErrorMessage(): String? { + return when (this) { + is ValidationResult.Error -> application.getString(messageResId) + is ValidationResult.ErrorWithArgs -> application.getString(messageResId, args) + ValidationResult.Success -> null + } + } + + private fun submit() = viewModelScope.launch { + validateName() + validateBranch() + validatePosition() + validateEmail() + validatePassword() + validatePasswordCheck() + + if (!_state.value.isValid) return@launch + + val s = _state.value + _state.update { it.copy(loading = true, error = null) } + runCatching { + singUp( + name = s.name, + workspace = s.workspace, + branch = s.branch, + position = s.position, + email = s.email, + password = s.password + ) + } + .onSuccess { _state.update { it.copy(loading = false, success = true) } } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _state.update { + it.copy(loading = false, error = backendMessage ?: (throwable.message ?: errorLabel)) + } + } + Log.d("SignUpViewModel", "submit: ${_state.value}") + } + + fun consumeError() { + _state.update { it.copy(error = null) } + } +} diff --git a/app/src/main/res/drawable/ic_arrow_back.xml b/app/src/main/res/drawable/ic_arrow_back.xml new file mode 100644 index 0000000..27ea91f --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_back.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/oneline_logo.xml b/app/src/main/res/drawable/oneline_logo.xml new file mode 100644 index 0000000..fc8400c --- /dev/null +++ b/app/src/main/res/drawable/oneline_logo.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/outline_close.xml b/app/src/main/res/drawable/outline_close.xml new file mode 100644 index 0000000..4f9d73e --- /dev/null +++ b/app/src/main/res/drawable/outline_close.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/square_logo.xml b/app/src/main/res/drawable/square_logo.xml new file mode 100644 index 0000000..ebe4e94 --- /dev/null +++ b/app/src/main/res/drawable/square_logo.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/font/gmarket_sans_bold.otf b/app/src/main/res/font/gmarket_sans_bold.otf new file mode 100644 index 0000000000000000000000000000000000000000..3a7ab60b591dba70f7ab3b9ef7cafd8b0641f32d GIT binary patch literal 889708 zcmeFa2YeJ&`#(C_Orh=U%hE_y_y76a`?=vgnRd=ozfU={>zkm^ z&>%{1qbQo9#!s9muk+mNLs8k?sIJ?FPY4N^L{XF*rF}mFj-4h=@SoUqO4sRBx49GG zde)>FK_Ram`m_PAKcgr^>7#l7K_LSMy?yrOLLdU_iqMlq&Q2}!ztzi-OZ|=Mu=68eV!y@4Z7cux^KMQDq;+gsq4laCQbfa*KptY;0JJb;tOUb#M*zBW>|k>Sd zmjS&l7BP&{4vt59%YdGCapyPSdILo*tOreDDMelT!faot8~r=w?tUKbP=}^0yN1W_ zsi5jxwKuoWE8N53(w)-aUHE}D?((hSp!2J@YHwYlS16RoGv)VyvlKOh!rwqMUsFsm z6s>tfGYhV#lB3%KYLJ^Z)kacT=HBCgH>xM#Rfu2U1Zpfr-8!rA`p{j5H4g$M_;LFU zXi}66GEvk+nl5epN8&>m_`4f5(s8Z)8{;_dN}1iZI?lVnd5Pm(EB@)$>Nw{qFGC%iyHgTKH`4H< zNxKP z=edq^?E^nPc-C>wQxgJP9OnXM4l+B=MXFPfuX3&j?My+#9p_G&^`N`+zLT$>(n|A! zh`xHjNVg^5IMymO$H&F5Oo&<?iCRiinq=c{tD~c+|EpbuK2ZW1=1GNHT!+pkswnVehEpgkETW~kBf_4Dvythiy9@*NQiq97Rl4YV#AhN zm8EeBQS$7t*rnd`6qpB-pOR<8ic#{!xLBZMO^jL^tIPxn2}o&bR1C~bPPF313=q~E zhyww*5ibYCL?$K0j~p;y`SRsHONrHe!sC3NN^rTKNYo+s=S~Y4?;jZAKVREL+r`zx zqZJ?fjPaI7-^tHo zB>-4t=q-4AShL+>QAQa&~oGy=yi?)JcSEA@dnKpqPcRH#MURf!JV_+e+MLUhFPC~!!G zb(u9fE*=#{Du|M>#c>J5WlJ!JfjXG<5+OBcyC9Y1cr>8m2W3LIl2Snz>k_atT6u{a z7LKVnDqM+%XmCL?fC?@FX)(#MQAttOL~rF85CjIxP?RuvNrDyK93jVHnpgrxw1T8h z5eP(uM}i*_qZo;cAqXQuF9;Ku9~FZ{;KG3$NV$oTQSq{p%M^PjDn>+$fkou7=;*lR zkUrqDEm0BLAP+0_DYU`K=hVlRFoqx;OP<|C^BRW2%Bh3=x_w0a19oZjZ1<= z5gmbcBe^Ih(HgzXnurMnk_YPI4H9EYL6CNc7t|b{hljq z2#7WSqX-xhwUJz+nvoqgh8h_emZWe}i@PK3r~;$r7$Yu$s|eC&K4K;`gmVgr85y@6 zkOYVac~Nl?xh)Zs5}<@H7za|>%6Kb+#9{h2(h1h5lc6drSOg?FybT_Kdtu;NwUoGI z?T9!?naD3JJ|5fva}_H((yy#Q6BJ5LL<6I{iTFSqE}{}#b#RR`|KRBXAt6wGhHjBy0mTxx~*CjvQwJ#KLl=%M%;A|bvl zolV3zQ>&-42;4yMw-PK0GXaBEg`nbo2O{CFD+WkF0mP!)12#Ff4ZlDNB2P^h9oRww zR=OLInOF*g1cinC6agU{7n?W|v8?Sfu%8@gg*L%amfFz)ZzL#A04qd6utvdJ2=8P_ zfzC4H4c=_a*f76i83914L5_F^3j--@^b*BKgZlmVwRcocrPmfmu9j1h$laqyN$HrP z9N}XPgH)vW4>LD-lw=afo6uL{ebQwEETP8%Ti`M$W|inqgoz}u9W6zK>@X-+{Ulh^ zKMWEIq;2bpB(=|oOpXbQ?GM>DB5X0#L);x>69o1HbE3;22omDr6QVH1$AFMfket(F ztVysi39@XIH98_uNfNjY832jJ&^#opbo5Z|(pek`>saHE8TzXzh_+=>*5xEyAaj6h zg5saSfR4D^TzYq}z(Pg(+dCxEszFniC|g&=L%N7cQtD`uH5OqAQRNbfju=F+pg7@i z36SETtx`Bf2hhRwT6&Dc<`(QHI*tKrzm+ezG694)C_rnW4ee5y=FexDz4hi;7K(OUBlr z&FM9v7$DJYqT-Pqj!I=Oih%*K95JCx7EKQEh3z0$DTd5(~5v~N5j=fYk zB)Nnb5}~Ax4#ff==!g4DWqYY?@Ejn3)&&X`wiU?`dx-gEaZ%7&LR0J9fT+1%EsSjq zA7oj@opUDygp8l&7ckvFm~fcvFHZ~#43$HICWb!Y7wj(wgvc|3gB}l<;6Fk3@(Y1$ zFK_vYfY8Z7Gec#V5$qQjIvcuG*)MRmJT)M2g178H3;O?%5IHDV4wyb;T7W;?3kV!P zZRUi4z)A8rSQi)+Do+cT9uNvdLxYs14pIUBux_FZ@{FGhl>Np9ObZB|?JZ9X2n|G< z6M?9oJi{+IG+_M9X@0@-jG4jkI@cd)OaQWh0f7^Pfs6lie^3GljSreJJ2+s{3*19f*S~z(%O!OfVr#1+)=)(JgonpS1@B%)-?U!%gt_n+5~{7lF6W z^||fU%>bx(@dF&MjNlDXqBA01`JcY+%g?QBkc)mODV)@HCgTgdxn-wIPbg^4*pyv6 zQZD+n^iSJ0Isa$dHJe>7I#+g4?u)+*uG_Yalx_9JrwTH>Gq+@1hJ#$TEB9AhJsfk2 zewC~Lv@5&n;y=o_$OQ-Fg7ejX_QR51*i1+lrxyMI^XrN;OA5W^>?1k3)%N@VB}Tv8$DU#|Q{E=>&JH*+p1)C#`MJDFE6mw%mcHD`~LEXoV)QF(hq);CTC zHl?)}cvE`rufP@cg867|doyS&mtMWQlpv2SU15txv^SvCdtr6v(egiX?D^-s<-#J_ z_P6ajuxx2fRuQVxW>4Gof;3wZQK+G8hn#&Vf2&;FY%i})E4x|xW7%H0;A+kVdqYN5 z);F^49C}jDwF3*}g`7~OR;Q+SCY*UnF8wjDyzD1A<80X_xxLQdq>57&Su(i(6zBqu zI^#mIZ&^V}1;DLNu0Cz6EB^y{w)bIis$y<%M;lpmea0r)cCGAUj=l6pr;im7c5pJV zRP5XYWNhCRWb}0)TfQr_``v~lP{CfFSD$~S*bc_DZL=SgYcha&E&8qvVIVj#E4ylM zC6anlw-!iOCo) zAYN&8-lp4}yz6?#Wji{#e1FOAl8Q2$&z9ib^%!snhk~Zat)?k+x3cKm{D;&V-u8^^W|U5*%vE{ z!3+8MkiV-di*6_y7i3`Ub`%M0aai$V2LXT}n12VvUCtEy~Q4BH8|Z#wG{wlwJa(4B_8a+3^acCxMWE8OjfmZO1V4 zR8_tUu))6emYqB0f>c|bQZ0+F*jk*tl``%u1=&Xwj<5(Z@8Ay{6{1QJR&AhQ8zL7A z8RiPbxG=M=C4i7@GZ>%*=G*oY+Y+WYusbcTjGCP_Ry9z8m3Wik%F6IH-5*9f*c@2sKYVl@}C0Af^u1iE5Mf(cZzpy(WA z0_b;0Q|5{beCCY+ZiS4X_zBml-XcAhZGW4nE=fv>R(M0IWEo6M4huSh$=Ny)kutIh zGul!f#1R5ZfiPH%K)CeB;#72JjZ1EZcc5w-a1sPnk*QNvP!4*;U(wgj?hX(Ib6miq z_&%!$3bxwj0XJ;Jl-hB7ztR?GBsD@=I<8PRg zlUrN}z*I_${ZjVtj#Qj(`x{7rFp$F_E0m??{z(Wz0N26RfsjEejsM$km*tAKa@v8w!>t+u)GuvU;a{z(N{EA}Oz{8drY5*h_ zB|E8zSGL^PC}ZJ5PdkH!G*ubrOHY7+<)wKi)!s@)3eZ+kC(@P6k1Oq>Qg{mM?X8YF zZ_9^xDfqUg48hcXFNYg1!Xy7e#n$p%`vH}KlHr|M8)2+u6X>1N?cZnGq2Q3W9Lie- zXdyD~`S_xu@aIa{Hx?IylGW*eatxZXO=#Y0_SRx(@S%MNERaz4mJ3oaFM(kk-~b)} zLMr*?ze8&PFx-@(GQ|T%Sju+if`Y+|33Hk*#E6oKr>?ds7NN6jS$kqVh zzy+B{<+dfZhJvHEYiPe>c$woZXKXJ23Xg^LyYK~-Qk(3%%TnOHxK-JYDz?HGA;rzb z-$54$cO3~t>8~ob+V-hfgNFZGfM>=g*x%r;+|k@nO@+A$a2*EcxXy?2hO=p~CIZf7%8!bMf3gd$MCHm#CBmu% zY8m{-nUkm(ppig51=q+g1g>IXjtrdQfIqiAr6R1%g zsHikl3ZoS1eL;hP)Wg(5SUm{VJg&%*2)f1rN4Xv4NVu0og)2{%wLSBJIY?!cA~Q;i zvzEYd1q`&44>c6VF!((b<_-G?x!UXAQEC|^Lpz{_(b7wm>m)eCs|dK81ZQDzW^J>f z3=%DYCwKCbkHfYRFo*ai0Q3$AdB-ah!+>6t;ujfg8l~I|hkNK}8NOGGzDb4^h>SS6 zng(2~U<>qh0?fPHs;NM0Ijle{FNIm-mGx1|${DaSj(QU4ASaocu6RET=Ao7q3*rfV_!JC}WI+ZnA<<^~nt2iReUh z<0?ewQpb#VxEBEHFjA5raz;`E;NNoPpAXD(MYfNECLf@baF_Xs3T@RpuJh-Dtpk9& zKcGDXe$S`0R2OC3En-K5WNOsb}(If1$}3svposX_kWplRz_B ziC5PcclAaf=okZX$Uwb4`duSm_1+l3rmATu&?fPqKE)M?_9WnqK0>NwMl>A5;TrP@ zi4?>w#tC8yrNp@*VAE-E3r_yhg|z*hlOD2yP* zYfhhexuCP72427kHNl*c0Meth7;CD`s1Kr=MEMesG8*ovnHA5&+H_v5z zuYZNnyZHijN6BM>HgX|4B8I|29+a41uD$kX4a91D3}S`pSaA~_Qe##pIuPHu${(cY zjuio=hz4oewcbS_vy7KEZpW9wMq2 zEBa#ILv7Wyc$C3Ln3G7XV%8ydmjnLM^2k?}k67K+Gq+o~{hWXDK8Y2?D8?P~AxOdM zyF`&6wI^{yv>`r1zoN{lCaO&T4G|X zI*HE_vrgNDDPBgIV_;@D$cae8OoV*_;s&b-(H)WA{HHE}UezzT=4tM>Y;Ea)#)5|UpD zO*P+;E*IBgZA5>neVG&Ai7vHJ#TdZ|>Wp? zjCGwMF{JzC?+gl48zNF&+yu5TzK!h-bA!bFD`) z@Dy>4=tirM4h606)DPuG8>?Lk!4N?Q@b?JF5n{Cgpc!T>RYO;A;|!DzpSACiRrC-XBWBUd7*|f6kaznY-nHB5Xkpdo zYAyXIi#YS3iaw{ci3}*!ov09NVm4k55~9~gjwkk2Jx;8QI-rFSA0$#-dt22$&Zs~; ztW=^`&1~)W5w}Z?9G+IP37)Byj$jA<;;I#i5i&1K!PCF(wXvf`Z(xNbhzTw#_VoJcg_wVMA{DsreaNghO< zR0*BYPoAkclB`4BF=rw**Ukgyl01N%5bM!!=k6I6(SQ3>A{D85|1)h#2dq|fReRM^ zh$*#_sFp=unD@;q#M|Z;<=4FDp|4r>d#QwMHgL#T{MQW@NA7R9i79lmq)stO3q=B|al> zu1U5eZ-P{*36@A+>6qQs+K;h>6j4vLVk3Uk`cLv`dxWZceUuZC)*p_fLqS@Yt5(2o ztO%~}Ga{jOAW~vsKFQJ%aJ3j#;wr>E*`ty-K?Hv&i8CTdCBU5)+BFL1lP(^qq9t** z^^VlBTA{Sa5sySR#AJjLF>2qa@>4Y+QY=;|V;_Jy(y0~N8GUr8?koN1aCF)}82A$z5Q7*Q&itgl z=X8CmhF-<$hP&4lO8rJ`VlKeG4ZVkNk#X;!W<*k}?pzhy*FiP2sF@PuCjtH;NAk7? zvmdGY;}x{D|CDDk+(VBLi@Lt2BQ!|m!FTlP-V3w0+K-cNM6DsD3aXM2Tp}J-tf&=K z?I=~u;7npswYsCNUEhAHK6l-}3{kuu>ZlMZP1Wx0cgz2zxpS3k)p31S;hce=vZy*b z{ob)Fz{-rhHL1;N|JHt|q-serBUWfc0p?1?0(Nv5{}?$W_Aq8i=ZoGTPcVmI#QYQP z3Dp&VJ1gJ%C{V3MKoh?;?xlFgkC|El6QLq2Y0r|zqK>Tl};{qwlw-e z%|_~6(wY8K9I5Yd+DDMHa~;|aJ9qaYS`GbzG30y;NxX5Vt_tUqys7TWRo{`j&bNSs zGU6J2L2!XwI`(>)T@VfEaf}iYd9M2z#NwUm8gfwWjPE!Ir}jv^8%GsYu6v}rRZa4_ z#s3#}LwCo46FI{aH$)`VRCPZ8#vYr9CNsoyV zqqc}ar&V2Z~%$8XFou5mED^eh4@V%E4&8|E6PD;Qz^)GWvQ ze|%qpGlStbN<0H(4}j-n9#6IIe2O_f{(8kZkk=ATQPW(JO6lB0vxDG9clKR1z0l$OcDSks?Cal6MygL() zGhiNmV}ZzlQlYf?$#@{p2v&}h;5kY_JV9)QZ;NICZ=5j+oG16-{Tz?Bs2-S(W>fPVng!I4*mBSc$3(j(CerL>h*+TGpE&wol!#cK5``Ag;3*x zP$xcAS7Tm}h&+RpP?Rr`d3(|B$xZ<&|6 z4tOSk9FCQ(6M$xXN)pP_wvODc0`F*;%vmv`am`jnd8yl$_!T)=+d# z^R22PRVI$E@chE?-_a( zUj>ON`@86+s>vDIL~o~GYUrZjcBlr3iPl+Fm%zWL3&1+%>ssmN{Oa>n+0{U?cx^Ut zNQno%WP6H&6ggKwj>uc#jCx0Pw94K1r1^q0+4()I^TA>z)fs@{4)#Hh@BOR}__fSS z^F?jJ@3(X4Tipq;gs4vfSw6BS)!I;+_Sh)*Bwj<$I{6^3QYd)hR=p$JTm_bK!B1Np zz#F>`lA$b$w}4uWr~Tcc(NteG=0M8-9(Db0$1ZBxO6Sij++IElJz=L?L6`mWKq{Hw z!9_064Ea|#w$7@xfeojiwkVB#J)TwN*LY^1z$fi3K<3nnJI^DB>J4?Nt+RHWzKy#2 zwyS@Q$NrgUEu;)uLNue?RTJ{SAGiCoZg|QGf}NV{yDslKQr#0G@XoVA*WwQ_gYDm* z-wSD0yA=(uY6J_+1ALu8#J0{$qwopl6#II#jyO2Ih^^YD)+mgLyiu*QNXD$X z1XZCC`IWE3nv8Q1m!;FPk3ht1X^bu?fy@XLi-wnbB1L-=N`o1+V_lHV4%t9T`&y)l zniZ~*6^YcmT;oyaj}&rz^HyQ5f=cIsQbMe+M%fA)J7!kdT-{iF)s>2i_VWlASNlO; ziY^~my`g*^W)J(UqN}%4#A>C|+;^$qPqYqJXL}N6{f-_{vS3aAyy|R-4X0+VfM-~LjFj~?1a3kTA(u2K$eGd%(kgl^FAsZj#p{EyJVED zXt;uopYO&M@`IWm=i+Q9UJ;i>4i%kBj_%po33xf{a$m?}U{mN$mG6Kd8fs|p((sf@ zb$yCwF<1oUtGTy1AF0&ZFxNw7lv`(~R3hrC;Q#po{7L2aCHK(EggdTQq^D8)sw=6{ zghH*Yb(SM@CY39_Pu8JbN5E2`Jy}`fd0+_6ZOTDU;61cO%I|hL+l;(ZJj-QgHA2b3 zvT}Zm5?!9f{Sd8)0tKyg*{7Y{VCI?*U4f!M;=$Egd(USdMX6QZsbEw4`nv3Vyazo- zw%J+laGsODQlrqrpf75qbX{;%`;;~h0Ge8BQm8iMD>IdB0Q#c#N)P0aLGg~GZz^1a z-39XLC`FoYqs=wW&_At_X$K)U46`SZe#us1UxRYB$+PITx(huu(Hz&K{Hjza1>r%u zGSy-v+92O3eGBG1;vJmt(mg^3aatK9n}zG_YaQNkXo~l;D70zyhSX?VN~_Y3s+h*u zCz%0#i#AZJul-$=vMM`gBd*0o5t>k%vOJ^5~ z{vq76D)Z+PPr~YZ5JyTsKS1f_2kbmwmkm8Eof@6D3Z>b3+CB}t>|IAtTI7WKVx}b) zcl91dl7b#bzEV8lz#Z}_{@s=WSqe7Zv zHODx!jq*(lC7&vp*x?P3wWE#HJPUaMG*>e|?sdpaj3=}?iKnXUa!&;>lRH)|=!4+D zKTr|S(LyMR%E=)M*v3|ls8TB$?lcg~IMWrg1ZVJU2U?NrIZy`N1CW|~r`<=#h*Beo zR29@l$yTmA5I{cC&8jLW0dGv-wFUbLtmG-zfg6=oRXz}7gVf~K(^;XaMt0Bvsey!$ ztuen<{gwy6m3`ejSdoM~XhKox3>;X2oku0P#ywV=Z%QRnu|J1;;+~FhDhzG3WyRZ* zn!r~3JsOW7s$s7=1D-=o22^+4K`Ec4-^~+h>=7>@+OrPXS79_dx(=lyLhNJ5jqz6Q zi5yE_g!<^Re{fmRW)nmVP)Qb%#vsiWvvVr_ujjq?lV;~-21swQ{K{y&Ih`R z4Hpq4xa4Ow)|F2`@1#HS$F2#paLJ1$t1+h#)T2~@%}d}*$Y-|lRH~{P5$zgrU2Jj*sxYeFjFy z|D-0lW+ar5AQZi3e;3iH#>Ky^Ny;aPcd|aB?0;r`ltigBr;D1VUM)5u9y(eE=j}b8)*1E0 z{RQdtial*dNe@llilUd1O3B*d4_aS`cg~KCL@Kv^RX$h&SEj-4$GO(Ns@M!w2-YCpQ~)KlMDd zl}e?usWPgXYNQTQ$EmZ_73wN=(@k{i<2KlBxZ60lscs=|OEq>)qvojlCiflgfzO+caMj9 zg!Wj_BdW*B9v}B;?$P2!dAWOa^6KiP^Af$fd)?F_j+yWwWC*7ue@F*y~=yl_S(~{sW;nO*W0uAeZ9x_ z9@jgpx3%|^y<>dceMMgnUr*oneg7C3KJe{9_YCqJ^z5J)2Cp9c(crHJrw=X|ynArt z;C+Ml4?Z~fXv)}>DJk<(;!@YAeww-^H8=Hi>Yr)Gv;k@B(u&fKq@7E&(&ZS&kt~s}7?vUI`xs!9lb0c#<&CSf+m)ny2Qy!DoCvRrn!o2*v>b%;#i}@4s zXXLNSUzh(@{l9*-6_d+i2SiTa@jc@)hN) z%QMQ0cMaJ!X;;Cn?<)FLOsMd$SX!~JqO8JJaiHRAC08j_K2Z5c<)q5VmEn~yR=!{P zS!G^japn0cx2mpHo>hISc2s3mFRFgZe#w5TCbTB5W_wLh&FPxoYR$C|)efl*s$Et4 zTJ7hxWxLJ0`|j?yd+P4U-K%!5-u<85AMGyMePZ{;-M{VO_Vm~@c2C5f<$G4{`E<`` zd-C?=@7cGfWzY9}F4T3cORoD*T}$2fbyxOMd%gD#-#cRO+`TLIzP5Mm-uL%r?5)__ zxc6NB(E2CpQ|saXzo-8DhT#n%4eJ^wXSd7(z>-$@0Z{323h7O3@L~Wxos9Yt24^YRbGZ4XlDiPe`~e z;EchAgBu(X{2g@0ekoH^=BLD`zMJ}4>eke})HA79(>&6A)80xePCJ@*KJ7+2moBDz zr$3fHFMUb+%Jk3E^V5%}pU=1tBDi11gp36lt1`}JcFGLPT#@-XMDUKxx}80C4%zw0 z&RIL3+?li!K8MS?H!C#jgRG5Nsacg-7qYHr-N+WQhi1>nj>`}OS4v;WF5<}A+H zm~$xSQqJXEA=i@ID|aYFa6oQEZdC4PxjP|(TXV1Ev3Y&-9?x5pSCD7V+nskQ-#`Dc z{O2Ho-_GA&z!aDZdK8Q|GiuD6zCloXV-lpHO&Pzp7_^b?5S z9i@$>m&@GBx|EsA?kgKx_BcfF2N1!TWmRRTAc7yUJ!X5-w!VC2`I_>~@{(OccTL_^ zxa&y8gAlHN`b&YJRV^)Oyzrt({T(T*-fGy? zkO>i7)o`MbX%rhRjr|+L8lxLuZrsxN7ep}MQ~GPcFPWnRk%5W(NH)U}#hN4LHU5&U&)&3>Q# z!}rhMzjS}{{#On#2gCzk+;W2megq=;#H}+J!M9E-Q4GJ_THN-Ka}5W7#n9dD3|_fa zkb4w$Q*#r__RWbm{cn!B`3U89>(Z^uw|>0UeB!Yab56{LG3!L@i3umR!+F@rKBo?y zYB*JYJn#4$$LmjyI(~_wPR>6be)5x(AD)Og5kgVNem-{PSQXMfmUgWASjDlA;4BHo zR^{GgIP*F-^4O4LQ;uFay8762$Lz<}9Q_raefK#2cK#f0A?JtpA8tJya(Kq!=hbJ8 z@HZkGXYSMQV;YAx4ryZQ&ooY|f2kg*)WhFetS`WM;FT==dzlm!HXR1=T?BvQanbiM z;4f4z+6!X`4EXDqi#~+$9*os6UWBm%Ml_5CGkY$Y568z~^n=j}{u1Tip`8}~1;PgyVpj)P$IhtXqN=7Rg- z2sGy3fC09czkBK{^K0R_1I8CHK-c*nz<3`9=sF){oewsh57wL?6p%GP5RMaI_`w(r zW9a0Q^M_2Xo^Jc>l>^*NP z41fQ7=K;NWKx^Je7{g%-vpgq?DgQciBp!=L3VF0G)0D9*ff{{CR z&zu}MehXvA*r++%;Rt%n`2@xW7;iqhZO-eDu9>s;(I@A;_Gr)?@WGr{V1V7{fE;tc zMsvoD89e6^I1YW}@|+=X1pagS!Z1?Q>_12UGW!oWf*)sty=T{szIS#F97|vn!AOI# z4aS?J^t0c9<1!eDFd|1jIeRG_tuPkD0KI2F0R#BVzK^12{WW~UtgCPY+Oy6Mzh@T2 z+$^x$tb&K9&B})($UkcxjMrd9!Wg6B+=jp~fCC{o-EGiKU#DrPrDnWA_on;OV1FF& zo1A;ogP_iWRpHJs{QbZAp*y**a=%Hg=q_|O^*#;0Q3g)~a&g@LLz5XV)2r$A^n3IM z`a}97nEM(16}`nd8?HCfU(?&+Ns9BX^Na@1(uFV@=_}+eeF@K)SQu|p6bByS4#O4$ zP~Qox))_3_c^(Wva_9G89E5S6qPlp)NFWrt?5C)%pg~tSb_2BHPq%7{(niC01_pS7 z2OIOH6r}^C>VnA}9iU4GyaWLT@DZ9RN_>($6Ty?>DaZNW6s0Gpl)fjNPlEwE8-R`> zl%k9p^3Vv^9$;$^6O4Rv&jj>LAg}2vxt0b|lo|M$fu9*eSm*o@Il|*6x9#x*bmP8fnNP= zFhDo_c@XG5SmQWvgg=7|bRGh|9s*t+e;!&3_d!PQMKJcmxI||32jAdNf51ZjEieix z$|soI^ZA3K27E?QzFo+*uNRz0!bpN~kb?g_ll%<)ilPRAjDvj0^&prt2Z zv5TSxzd=z$29f7OLD!*E9Ov+S*kp1(><5Z^cqfdj6g3>|G6IJBGxENXpc(9n|L^^4 zq~4*{Q~RlRsZZg*a9OPR3_9^$@a?!asF&TRx=*9*)Nk;O=6d%jn$1+E<|oZ1%@wMN zdPTEIvjsNhZ)<+1Rzq3;Tys_Pm*xx2-*Y56`uQazbTirF(ZfY-8 zM>SA2)E+m^ji$bZ*TCPvzC8{4{J&whehvPH@PDBH|A@+mz5H6rMwP>kz7+NZdDQDv z4%H0*9eEbDhWc2;Y4n;-8iS^@#z)g%W7Krf^wspycxbw5yfqJLBu!V%gPMLClSZrY z(hSh}YVOqx)C|&?H9AdC&0x(C&Hb98nqivm8ea3TX1L})%>$YdnvoidM$nAXjMm7S zUYbWVV>I_@M9rg`v6>zlKg~EzZ_Rkk1dYFDqGpn2vL-+?MdJx?9k#$e3M-&2gH(&4{ISgwiCST(O|Uem1AEYgH&7Hgi@yr6ke^OELe%~Z`a z&2&wW<}ppMCPWjeS*nTDyrWsKc~|qE=1t8y&0Crknw6SoG|y^QX`a)p)~s=3G#_ea zz+adC*v(zDMDribLQS}4gXV3`N1FHPG4!L_Xl)EVRvW90qy6Y{^muxLHeUO*HbI-H zO``qjiS#6TG95rqp{LT*w8`{zIuPEN%%C6BF4HcjgS9KPE49ziA=+oPtF+H)pVz*i zeNp=o9ZJvCzDz$(KS9sZzM@^NU88+f`zoJy-jtcAfSudLBJr`w_iB z`?2;D?Wfw$w4ZCgpciVt)Na&nq8Dku(r(snp~L9KbhtKOTR=x>3$;bGm0qGPrk83< zw58fItxa1_N77N+UG$UmQ*<;Pqpi?Z(y??L9Zx^4to~$($CP(Y7fz?w1>6d(a+J(YmaD; zYL97;YforTYERKG&@XDgr(dF9reD#X)}GOxrB`duY0uMZv=_8LXfM*QYAi}qLTZ`$9rf6!~Sf6}jOuWJ9&{;j>Hy{^5Xy{WxLzd^srQ@k6!j@R(+ z^jq}XJWapDGxU0%158@yYx$x`M8x ztN54sSNPTZ8va%OHM*L%^Plja@}Kda^Iz~^@*DY0bPZk0f5mU6ck^5Lt^C*Y9)26Y zo!`NK!+*=C@Tqhiy_Zj;>-ls(gU{r5@>zT~pTp92Grf;* zErw@9Yvp@PwL$0Q#y^#T}SH}9ZP>tpVo2o8C@s(EPYPbS=U9^l|HZQMqi+R zpfBpQ^d%jy)9D2IvQDIb)ai8wol)nZGtocMS9B8nGyMzwtIn*m=(^Lt>F&{a(!bMx z=A&c|b^YjT^mY1%?m^u{I&WQnosVt+ zeUrYW^VJR14blzP4bcr{CU4W`^~?iIPhEqqQP-qv*6q`^Fuj=G zOds6|-AUak-S@iFx-(2)rXTa5?l0Znx@)@Yx*NKi%tN|c0wuUH-hxJO7igxxzzD3s z37v$_LKmScnAPAzM7Yu@t8ORJ`1`EEzKxT+ANEj>(VTKArg<-hEBG;^g>k}oVS?Zc>;o{3_f6fQ7NG0{v66U)R2KQQsaMdoQHfk_lD37459;YZ;o z;R=&1{4D$;{3`q={4V?<{K+h1mJ3&z70gQJ8R0MCZ{eD7UAQ6KWS(VK3AaRwc}{c_ zHKIH7yhw|T$cmiUN$f0kVO|isirqx5$TKf8FEKBR1DRKt)#4y=usDQSBMxO=WnL49 zi4Tjz#SzR}=5=u-^9J)KvrZf(jusyg$B2(IZ!vE(?}%eXKW4o+P8=^zVBQt|#fjo1 zak3a7P7$Xv?=kO-)0hp+2h4}!bTLp25@(2yiNVZ&n2*E|F_igOoGCsoKEZq<&Jt&f zbHusgJaN9bfccd9Ok5}~Vm@cS5W~d9%$H)g7$I7jjp7nzHrEx5T%_cf|F~w@eC?D!wbeC%(_5 zi5tWZ#1ENtCR3~ut3^ArQ>+nd#obJnxJRrL_losmgV-oGG1*Lx*v#aL`@|NpRopKg z5D$un#KTM;lP`WJ9$^Z^qvA2~I8!K|5KoGy#P7w^;u-O*c#bI&&ojm11*Sy&LA)ql z5-*ECia#->OqqB^{F$+dzlgsw<;*VeH}QAz5Ajd&s`!`qH&ek>ir1Jb@j6p2-Vkq! zxAc_WO|N0>OpV^8m-J@6Mc-Y2kKU81Wp?X_>qqEEGJEu+^rQ8UFm?Jd`bYI+^?v$s z`tkY+%wDFRXpfAmVUN=j(#rF%iGT$*r^l{8leLQoF zIj(=5OX2bDg=t+|+N=Z`bc&Zm|^WrvFC&EvwO|=u`D+ zth+v4pP|px@6>1Mv-LSF%`*C2mSs7%lRi(MuP@LS>WlQnY-hF$+m-F6|Bcn^f7k!P z@~lq(Co8a`{;K{j{ond)te!RKud_z|4c0?{lQrpY87NjVxUpu|V$c}e+3p6~z!+He z9s_6SWaw<@V(4n=i4eujyLN$i7$$%X*-A=cY4h3#*c%K8|l z8KxTo*#WGtA&4Dln86M*JjM<-1hYd7A%;+Ps9~nzal;erFvBdvY{MM(VRnS!CBw^x zR}8BSYYeX%USmfZ)*4;yxpq0C@2lpA&#Dh!pZKReM- z#ZEF*vy%;WLye)|z-y2RF&KSTYliEF8-|;PTSkhV zZgewhjP7ipkv1|$mJKp;#!kl0#xBOL#%@Nfk!NQZb?jqCfeki_M!nHsG#WjOCN{(< z8O=ru8*1!syvOLt&NSX@yw7;QQ8xB4dKn*JA2;?i_A>T1_FE<(IM+CjwHoIe7qCm%rN)KEMaD4WVq>^5!f0h9*(l=@_DS|BHkyqwE;U9P zql`})pJHR#IAgRihK)DI8sm)d?9;}ljS0p?W0Eo1xXiemO<)s^E7&A9nO$aFX?(`` ztZ|j`Id(a_f?a8R-uMFhjPXU|OU9SkXN|8IR~y$DUp2mFTx)!tUBy0Ue1mCtTXOqR~zfuHSDX#24kbK$=J-k#;!H)V_#?AVBa*h7+a0|jR%Ye z*>&t&?Ayje#>4D8#_x<7lP#&gE= z#tX(Dj2GDt*^k(dJ-j>~U_bHb>CwxhH~T63na5y{As$0LhIu^fF`WI}V}!>@k5L|@ zJs$BGR*xMX-*|lMk>Zi+k;Z<_ zZu3a@$nePY*vW2Zzwx-@@w3M-?6)4jdi>_`JDcM1hsU2DS3Umn_}k-}$8|Q9P4l?n zans`#o6csinI1kmuW6rVVY-}Z(3klXj)_nV=LJz(_&LN zTWyLkSxrk=yJ@K@(iCNS()5%m+7!dqu(hUGb~n3+tz-9^;!N?Tr`dY8fo)`)ObMn$ zw%L?qN;WNH_nDTPR+v_ro-sXZT4j2UZDCtY&$Ij41MET53#J!MFPUC8y<%F;9%2uh z)|g&pzhjS>K46cs$Jpbhd{Y5?!c=G~G8MBYO(mvMQ<=$TDmU#iRj{Yn?@g8LY4!|z z)>LJxHrY)zrdswKd!D^u+HKmy{$Q#z?KRc27flVOMpKii*|g8pVrpeCv6oHz*&j^@ z*q=-XO@~Z}P2ZW0n2xen*q=?uOvl+@OeahyO{dsjP2ZbNo6eZdn$DTdn=Y`wvA>&s zVE9_PABPe`+*+0qdPaJdGjWo%N_vhnOV3L$NH200=_To9=@n_Uv_^VWdX4MO-6O5#Jf+vU zd!;v|H>GvbThiOoJKTNT{nBP>i?mhxTG}RUmv(S6*Mswts-$Y}0m&}aNVQx~X}7dT zs+0Cg^-_b>$n}z%q-L(Sw2$i}wMebfe(8X8P&&l*<@!m7rSG^0r6bZ&=@|ErbX+>V-%F>ZGn_ZqUpmYANawf#(s}8E^n-L!x+GoZe7S+rkJ3-vAnA(qv-Ar$So&4^ zP5NE>L;6#?D*eR`;f6|obHk)-+{4^(>AG}-8^Mj_MscIf_n1AoN6hz{?=#=ejWNsS z9%e7|1LmIQUgqB1quf|?AI{I*mm6p9XMWK9klEYZ-|WMU=O&m3n0+~a^FVGQH;J3f z1#nZ$gUo}?L(D_X!?>y3H1osUbn|d7kP9-8FpuPBm`8Dsalu@Od9?WvF4R26{HS>> zH`DBA9%mkJo?!MjPc%>B9_OAgPv&NEv$;9kTyubVig~Jent3`mkDG4}GzXbym>)9- zn?tw-+#)W_{IdBKZn1f_d5!s1F5LVY7hzs&e%<_r`AzdW&dMz@zr`&zzs*H*QRa8d z>&@?)-{YR-p5mg-@0&MpG3F1lDK5^*XC{9GV^xx4)ZtMa&85;l6%IS!#!)xHRqZ0%>~>l?m6yx zb1U}(_o8{f`GEN#_mcS#_p0$A*JYeZ*>1F9{>0{~3y>02oy<>Th zTW@*D;%(_~@v#iB_;T-B23iJL26OLOhFFGLhH>v(9<~g(jIfNfjIxZjJYpHcZLmDb zeP9`D@w1GxjJHg%_**7gCUGBf|KUEeOy)ke1X!kUpKzaYpK+gCrdp<1rdt9nLEIPI zmzEjaM$2Q|CQGm-#1hJVWtqus=C)WKw>)8)#cj3Bw#>22<-WGev&^?Fuq?DJvV>U{ zTf(_*mI!XU#cEk%S!#*2L|LA+JY|XIc5vTV)>>Y-yup2IdDF7a@)noErCK&wzOroQ z(kxpnTP6UGl?Uo&uZ!F(hQY@)lh9%9C&ShFMESZ*_mMlxQCC8F$$>Vlf@+}3H zLN3cvWGS|kaM_kpOPR%HDYxvhR9Gsx97~m@n#<+#xO~e+%O$SBa@q1DSI8Ave&UKP zS1dnUezE*&`Hd^#N-e*0Wt@#GxBS8Fvi!+aSguCScU#I<(s+`UWpuH65{ z)>}nK&AxHF_x(_bO@RU}j3kp}B*|nF3dKr+7Av&46^a%uT4;;AyYu4iuEmQ(ad-FP z?!No~_II?`&cPgH<>1NLtd;BfUDvFf)nW~?=C$Ut=C_6hUk|=vEf9P&_*U?3Ye8!v zYgq6dYq+&=@ZI2h)*@DG@crP2!H=vpt+j$5TWeeE1V0IWYONcbW36YcZ*5?0Xl)ey zEcm%KG5CeGaq!FFSJo!hBx_S^Gi&qU*THYBEvzkr-&$K)lY`#{zqhuwwz0OgwzIak zcCe-de+d3)?HK$i_;c_VYbR@GYZq%*Yd33Z@YmpP*6!9G!QZWE)^uw|@DFQGYcFeW zYaeT0Yd>p$>ww^&)`7vlf`149u@15hwhjsYYaMDG7W~gT+&aQKlFEhTC_?42E}#Oe z3$2T+i>W~C66;dyGV5~d3hPSiDk_Kywyvfq>l%u-uC=bSuD5QmZnSQq80%*17VB1u zr8w(h>k;cw>oIG#^|cdU1<_pJA=53CQZkEpy!a6Dq&;sWr#?j0&|r zx4y8xw7#;ww!X2xr3z35sY2Et)}Pj2R2UUb6}AE9O0_kzB~qHLv8{ZyL+iBZHm9y=p%G>tX_S&*+`)vEE z3RH~k02OOHNL8dNQI&0nY=><}Y)7doR8`wCTQ(JEJ8nB+J4scuouaDSPTS7d&f3n| z&QtMJg6#rTgQ`i@vR$-YvR$@av0bHVQ+24iwrjTQR6W}b+fCaos=n>E?T+oP?Vjzv z?Sbtf)qrYfdqg#&5~;?v$F?W7r?wp1Guv~j36(@Oqng`!yFj(DJMALXl4@m_?6Tcu zciTO7uU(;%?W$d)T2pPPwsxOgxBKme-Lw~_+EMN8RqR#marSEV>h^f51C>H`q&nG~ zP@SnRR9C7Sm1-YgA4qk#53&!o521S4huVkPhucTkN7_f(M^kB3x_yj&tbH7nLG`wO zxBsyJwEwdIw*R5}P<`!x?f`V~9B~|V9CKtlj#HDU z$&M4$6l$vDq~jDdjhar)p#F25cARmXb)0jYr)E;K92cnB)EsKAd0|C zb3CV3P%9lT951O=j#rM?jyKe5$6Loc$9u;I$4AE}$7gB{wbt>4TIcvmt#^ELe0ThC z{B-XQTwR<)B)bkJ9wTKsDr$d zIz%1jMP8zg@G|e>-PBRu!+Uv!S9y*1@j7*k%I5vlaq0whk~eshFUm*o#rWdXDe5#I z$(Nwc@Fn?Dd}-<|Uxtt3%kt5DIleq!fjUQ>=VPb~)J5tNAIn$dEAf^2DtuMyG9SlR zK5OMPv%=wxA`{I9lkB!j&IL* z;8Uo()IGiWa@UHGolL%tiINFJBT~z2!N6^KD9&~X!Qb-fh zg$%lc&{OCo^cMOEeT9BPf4U@HN*Evvq)XFfgh9e!VTdqP7)D3YW$9>PxG;h)CyW$E z38U%q!Wdz!FisdROb{jtljsU`j4)Z4LdVh->B@8!;hb=ut}0v*E((|EIN>r~O}HXl z6|M=_g&TBrI$pRb+@cfc8p3Vij&N7FC)^hv&^3jJ!Xx1^T}yZ(JQZ^2+H_sIo-@K( zjIN(cu}9Jk=!VV`bR%a;XDMfCXBlS{ok%y%Wn-hA<>)54jC%!Vj5F3*(OHR3qMJG^ zJFC#m=;qFb&PL8eXJcm*XOgoi-GXlEOm%j5_Hd>-({ri#o^&f`FK2IOA3E9D*V)h6 zpKk3O;2h{2l*`KxaSnA3qubDJ>GpI7=W6E~I>ouxxz4$s?&#d$-00lo%r1c zo#@WF>hgBy4!VnTr*oHcw==g|>&&9N(%qaFoEM#!oR^(foL8OK=v2D9^P}^V^E2Ip zP7_5@5@pdPxxP zr$>k_>5*b9dX$(fwiernZN+wCdwMiIM(iM_&|~Rw^mwr&J%OG`PZB$coy9Ii+=^0{bE^pj}{*Rt1rqQ$L*@N-w2a1E} zdGvg7Fuj0YNG}qHh(pC;;&5?!<+k+@h~A}$q| ziOcDY^d@?>4WqkagVr{J}hR5`^5e95%GX{P&_0a7LSNW#bfkQ`k0taXN$+_1Z-_VP ztMoPcI(f& zz82qzZ|VE=1M!{so_;8P5I>5a=tuNp`ic0Neky(uztTDMGy1vsjea41r(cRc=vU%T z@t62p{6oK{--v(3fArg2(*q?!zsvPK0;E7GD3=+hB$|Fte~=jZBmIf~oXe1Nl0^#1 zbwTpcU+Ay7Mo1|AjsBi%g$VQy$w~i|L`jll$tAfZ5B-b&olBZ4^dCu;G|5N*%{52- zx#YPi6_p~SV)Q=-q~Z)pkqnVaL%1W0A2XeKb%F)1%qV1lF=DORc| zRgx-8Rivs+Fhfak3@ue-7^%7xFC|Ddq?%GKhGjUZwp53)NOg0`_WDc+lb6XSHIN!g zjif}WF_WJOm6|XGq$H-G)KqFFHJ4gQEu~gWAtp>pmRd96Qkz^Fz8zCoYAVrLIyp#>UvCRH?hvLrRmh>`vvbM(xzapozO;bR8NakpTErOAVrhxAlrg1c(sF5qv{G6nt(Mj> zMVSa`EmKTd#}t>=Gm+8;X`{4B+RT(-N=jR#txPFto0KVSXG%*uq@B_(X}7e8DI@J= zqL{K$785P)W6Ck*nF>q{6U$U&DlwI%{n7#HAX7y;BpsHHFjb|a(lIGpIxd}%PD-bk zIO()>hN&i5_C=y24av;-#z7H6}s2F5QrBGBuc*OfBh_bX&S3-DPSs zb(p%+J*FO0pJ~7}lACbmdMUkP zS}-l8*GwxWnQ6_mk={serFYVM=>yZ2X(xS@J~8d3&(as^E7L*xCViKFNI#`t(r@Vx zlfrbA{xY4I&P*5SpA0g}M9w1zFkP8$a-bZ<#NmbW}sZ286;O=1~WtC7&%t1C|8mzGeenSauvBMGhB|7tI5@w5puko zAlHy<%C+R$avf$QGfJ+@jF#&$W90gB1G%BxNKTX+Gh^i@a+2JX87DWBo69Yj@p4PK zm7FZMmfOf}<#x;jW}@6)?!Zi9Cd(;uN4b;SS?(ftWu`DwnQ8J^c^orc9xqRjCo(hS zNz8xpWO<4_Rh}kKXJ#_9g%W}SSESubCgZ^$?0Tk>uB z4zq#TDBqRuF`Jmp@;mvx{6YRGf092lTbQl#7x^o*P5vf-mwzys%ywpn{8RoV|CayA zf0>=kF8Lp`+Xc)X7rKZmk1N0x=n7)?GFdLG%jUAX94_7^xSY&BWg{mtbnRkZFfU!ZU3-{UuDz}-*FNU8YrpG&>!9n9>#*yH>nQVv zdFwjHykp)oA6(h4BU4Z$^{BtXA)vdXGZr$x?fhBAncUyNm zHo)E9-NBv02D&@CJGnc%ySTf$ySY=@AU4?Dou%A8SlXS&GVXMDhP$V`7t6AoySKZK zyRW;SyT5w?Yhgp&W87oit4r( zy4SlmxHqx|+?(8+-CJ^VDvU=zipW?0({Y>ds+ptlj<0{oMV6b+});U%6kq-?-np-?2RF@^tcaX5F4H ztcUfoif6KC3afgidZu}%vzljy=ReO(&n(Yu&m7NO*2n6ed7k;61+1SnJPSRGJc~U` zSd%TvMtGKbma)Y=%h}?d6>OwurDv6AwP%fIt!JHQJzIh;>Dj=RVoS4S*eK6N&nC}i z&lb;Cwk#X%+2+Y)%XzkYc6fHODp zJx4r8J;&I}o@~!?&k44Q=OkOzbBc}goc5gYob{aZocCPtTx6?xE_p6{u6VAp)!BG9 z!SmhogRSBD>G|dP&DQk%@%;7t^MV(>#G8k$#n$!)uyxqFY&~zFH^>|8rM$G4Ve7LE zysVdF8+t9?5N}?#kvE?=zcmrY!h!`HpyGWYxUZ^cCW+BvrWB% z*Xb46W^8kBgtwTtxHr;U!duc?if!R7?JeVtVq3DUyb0bK-kRQ8-rC+eY%<&0Ti08U zZR4%)ZQyOlw)HmhCVCrtn|PDFO})+7c5HiZbGC!G1)Jh+>22jr_O|x6@wR0&f zDmLA_+PlWP*1OKT-n)U#V0*E>y(hdU**@M=-qYSQY+vtL?>X;z?*;Eg?$mZr4Tzp2~)zA!b%avs@N1eJCYrxIM~q&&yG<9#i@vjq{xbk9jmw%kK$#= zDT<;h8arO`DZ1iU48>H6DiQ1irI=D&iBw9k6P1!mDW$YhMu}3&vXj`!O0-grouZUi zDkw4RR3%oas8muaD^--LN*p_lovu`4XDHR#|Ja%AETxOmm7T40Q&QPE>|A!9(p~AH zq$%l2hSHOr&n{4Uu?v;n>>{O)(pTxH^j8Kb1KGvw5@nDwm|dz2QHCnR*k#IaWrQ+P z8KsO?#wcUiD;u2H5b)7iDk4COy%Cc93VrOa05 zD07v0%6w%3yPn;kEMzybo7m0DB4x3%L|LjVQ;dJq@`gRAyj9*Q@7Y7j z2j!#kN%^dNQNAkQ*u(4*YH78M8pU2_uc&3&t7Lrr7vtLbWn z+EeYN_E!6-ec1=>BlfYnT3y3FQP-;L)b;FBb%VN5-K1_-x2RjyZEOzvOwDAUtJ~QZ z>JD|Mx=Y=y?os!$FV!q{pSquYr5;cZs)yLu>>Kr*dS1PtUQ{osm)W=MJN3ExLVc;e zQeUfY*!S!Q^{x7j{iwcIKd2wsPwFT2v-(B-s(w?yt3TM!>=*SX`&IqLep7#|f7HL~ zKMgcwziULxqXn=(v_LIL3ub?6ltyce#%i2q(L&f?>~HpuX4P!$U(K#LG@kvZ37S(A zHA#~-m*(bxL(QXkHH9Nw9xgyj&}wjjT1~B%R+|gb>S%SfdRl$0f!0uK#07JdmdMds zV~)|9Xh~XAt(n$bYr(M`r?u2taTYCEYpu26Lb$wITdkeeUhANxXdStHTz;(+7s?gj z3TmCTE?QTuo0h6|=L&IQS`RIa3)j-M46P?uSnH+r*7|6DwSHQEZ2(tle8>tpSGWqwF8_>JE$Gf4r@oWqnw-bXva7&r*Nv4 ztsU1+XeYH(+G$SXeA*f9ET?PdwDZ~p&aYk6E@_vwE811zB9!oDIttIy`M`y4)=E6YXu1g@OV$(8qsKFKHhTwDd8n~U*zd|scz#d4K= zO?}OL&AG~46<-&ws;{fBn=jSZ-PgmH#>H{fxaz)1zR6s?Z;EfKZyJ~2o9>(8`_DJi zH_JEMH;1di)%4BfYWe1IwSDt_3w#TGi+qcHOSn2*UEg-!4&P4SF5hn79^YQB9#@}h z;Jfa-!8P>V^xg8^<{J6#`0o1d`R@B3_#XNmafw`G-(%ks-&3xMFUR-H_uTiw_tN)@ zOY*(;z45)}n)=@P-upgq&3qqypM0NvUwmJE-+bS>=Dr`kpT1wd-&_mdAKzc!KOJ<` z3D=TqrRUKDxMV$058_&LZS-KStxoB*&giVpaqYPFx`peYhv<3re0qL8R4ydg1 zy`)}BFU|Gf()2Q1x*o-4=w6N*@dKIppUR96N ztLfGCc&M0i^hSE3-dJy< zC+SV~X52__l-`^h&5hy4>Mit^dMiCyZ>_iC#&P4h3EV_|u0D^Oq|etE=nJ{Y`XYU? zzC>TDFVmOnE4V4#RDC5kjhoKR&{yfJ^)>oheVx9Z`;VKcZ_qb#v-C~+W_=4cTi>d0 z(=+w$`VM`kzKff~&DD2v^YlI3e0{H;rSH@C>j(6M+yecOepo-kE!28JHG`dMx5>{{h9vl{vF(L|4#od|8D;t|6YHVe;;?kzu$j=JLx~@Kjc5`KjJ^?KjzQ& zALmZ_Pxw#zPjRRHr~POAXSp-}bN=)G3;v7#Oa9CLE8JQCRsS{aoc}s^-hab?(|^l< z+keM@m%HG<=fCfNz+Ln|^gr@H<}Uf4_@DZ7{LlQ){V)74xy#%Y|10h)ca6JlfC$oBlpP|VhrUz8^es@ z#t80BbE1kMW-| z)0oBmHD()gjJd`g` zX*V4f)#NRjDOh}_(-cj~lueiEw&pwd`YeX2n|{+UO|z&OVHPusTTC<3 zQq(MAmNZM5rOh&Clv&n{wnSKpndQv#mf~gwGscXyM4A=NN@iuVilu~E)r_;0G^?4_ zEv3wOOKCH~tYOwPYnippI+ikKU9+B9-x6guFdLeUEM?6^v$5I4Ofs9A&CKSOXtRac z(rjfWTgsWO%{FFRvz^)A>|iNxsbHp<9W60tC$qEJ#S&|&X!bSxnf=WH=0J0hrIMwx zIoKRxsbUT_hnd4IRm~CRNOP1q+8kq!HOE=vEY-~Mmg?pNOT0PJoMcWmr_ z4Rg9V!&1}y&zxz_veYtXn{&*$<~(!0xxid#sckMY7hCF>ODuKGrRFkoxw*nzX|A%= zv(z_Nn`);% zmKNqNbGNz2($d^(W|{jet<3%A0rQ}F$UJNwF^^i3Ev?OCX100U(#AYto-|LHr_D3w zSxZ|>JM)}*-qPN@U|uvYSvr`P%`4_r^O||xykXw7q*ywdw=A8^+m_D%$Lc(c?O-Za zf}q@TX!!s2Msuaj|6TuFxqFiTKNmtk?$Q!szPPT*X`S0;)KBh~UNN;x+yC7w`rY>3 zK9S?UJMcSC8vJ^159ssbTi^svu$wuY^sQmuZ%Lfn0o3DSoavjqCA}XbJ@0-@KLrR9TS+izJo7^AOS*&P88E3nS$$gy(scG$!ot07z-B}}}t>KLA z(#83Io=$hBwM%c8)~j7x?bfqp7X~^3 z=m9`40{Q^Z$AP{I^nGB0fhi1(2~0LHr+~Qu%uQfE0?Pwi4A^?WwgPq#uuFi=1ok+v zcY%EeoFBLt;1YoA4BQmp_5k+`EHqerU`Ync9I$K$%LNF@_1%j?ND_n$hmf@pk^^~7 z$lC|Tg9>VTGcwPusAv_wwVt!TJGg0@!MSZ6MfY zfo&7m_JQpM*fp@X0sAPhuK@c)a8TeV1&(BJ%mv3ba6ALv4tyN&Gl5?RLOcjvK^O~8 z8l1UxsVm@o2hKkrmISdfh&MpW3(`Q4wt##MT+6_X;4TU7#^9a>?(3lDPQDHV^$=)f zK-&&lZrvju{7u0a0LEL0C<(;}L-D0h{5(X4L1Y|6c7VuH5V;Z}vmx>?l*kJunm~zB zP|^Vp{gf3)QN&RJ)q7_sPh5phC5VQxdJFEqRgjaXj}+XK=bO*d@i&wp~Wa@aRpi$(6Sx0+zG7;L96P}su{Ez z0Ig;~t7DKH0?ExFc|Ih6hSqJN^)qPG1lsI?Hix0jEok!>+QvfLq0sgsw9BnB4up0e zp?w2rpKH12X3Yjb`)p``3fjMh_V1xX73feOI*fu2yP?BA={oT(9s4R1?ZStgUy6a8gyC)oxVZm*3fx3bm5^(Zku%vbh!szeb99{biE7R?9goz zbUOp7MIbdDQjbCRVCWtX-Pb|)H_)Rh^jHf$GNH!-=y3{q+=L#_pvPxOBaoI4(j-WW zfV6l>YXE7jAT2i}GziirK-zpr+X!h{kaiBz?n7Gc^M4>c7}ASCx(4ZGA-y`J*N61n zxLYqs9|q}DA$>8VZ-n$LNIwnfw;=r~q`!xZK*$J#3@>DqhK%Zv(E>7Z`;j9c<3Gq) z3K^RqBMUMvLB?~)_zOJ?LQf5PmW7^mpl34l>;*kXL(kdJa}D&|13gbe&+E|hIrI{t z*8}L?5qjT(J{6(QX6SPm`c{U%O`-2G=obh5&O^WZ&_4?LUxxurVL*2n@CF8&FmNsm zssMv#z~CSl+z19AfFW&RXeAi>5r!3qVJBg@3d6g=@T)NV35;j~BaXw!yfAVcjLd;i zDKP36jP44fFTt2p81nLSoRo} z7lY-gu>2UTP+&!WSdk4Y3&P4|Sh*Wk{(x1}Vbup%t-$I&uzC}$J_c)4SknyFtbw%% zYa7GbnXvXRtaHM;mauLxtjmOT?_hl>tgj5~Q(%1-Z1BN`Hn1TZHip5*DA>3IHU+_^ zWY{zVHhqH49U*tRdW##jjE60!VQU<09SK`s!M0kk?J{I`hs@isy$5VR1v{$3jvlaM z2<&(cJ40Zn20LrR&J(aJ4t8yZUB6*>S=c=kc5jB=7h(4&*kgk|)nQK`*s~h;T!Xzl z>`jEdb7Ajc$O?w67|5ClSr=em9@rNR`$oaO9kA~+?2m>03t<08IM5IdEQAA3;b2iX zxCIX8z#$(T%78=L;V=V-;~;m(^Y9}$!o!hXaAXr4ISNOuaI_*E9ScV&QfqT1y#f@;O zDO|1%SK{HyBe=Q=u62UzZQ%MoxKS5w9D$o1;N}gu)fR63hTEs$_CL7O3GRG@-084; z)8T%5xc>?stc8b_;87uXv;ZErhR56CNhmy73r`t%x(sqGkdq0|I>U1TUKD{B58!1l zc*Vf0ckp^$?pg@ESq5)Kc-sQrUW9jz;av}S_Zr?8h4)9{!w&e^3qJmWPaEL#DEN{D zUkk$5weYPaeESREm&1<`_%R56hQQB3@GAg*?S|jw;P-y`69<2bz~2Y(ZzckZ5RWh! zVK>54#BjuT#P*0o5wnrxL(&!VgkhdW7!ZU32^eq;133&Fhk*+*@Hqyl7_<_D12A|F z2H!-g7E+6m_95K{>1)WC$ecnp4B0uzenGB0a*L3=fR+ffG(gKbwA@F_Hw>wUA#*S! z3q$^4-u{^P73M37`PN|mFw7r~`R8N)7Z_RyLuX^?8!S*73+%vx8W!w;1utMB5euba zp{-cx1%^o&Rvp9IW7rT3n~!0a|MxcGO)z`}hR?_F6Bzy(3;VHfG8UeJg|B0gidbYm z7P*T>-lDZOTI-{=JzBS;bvN1q(AFJo*=T3b-VN<*(S8^057GV@y>U-4UQEQFbK-8w7b^(2*(ANlk6VSI8eHT#A zhk6;*(@%Ec)l7e+&ALqW=jR`O&D2#$Yt|q45DtFPinx z9D(LeG;^?MK`dGmiw?!2JFw_Yj9@V$1|tSy#2$=zkH!30ECq|L#9~jexQxY#mDh^5o9^b9P02g~HaGVxeu9+t_$C>usK#i)f?mSEWySat=L{fW`F zF?tM^3&C?w?WgcXZo#r{}vI#xW3m4dNS1FW9nq!qo zSmh*E`HfY}VAVcY^*mPnjd7(ht`o+M#JD*aw*li$V%#mP=D=#vSgku&8-vwOV6|6R zy#Q8E!0IEg`g*K>2jgXokH+{m7(X53k7E2~jQ@iPg)l+IglJ6YiU~t7;TP6$V2yOF zF$!yZ$C}l!W(w9^g*887t*TgSDb{+4wIi_hNUVJU>lDE{rLj%|*6EIQj$xgPSmzbi z^cFmWa(9>v5f*tifj?um_8ViUk7jj_p9Osa}WGcf5ZHci2% zbFgU+HuGS!y4Y+THv5Fl-Pk+{oA<`%W3l-XZ2lTs1YnE2*rG1B7=ta=V~ZcyG7ejA z!Bz#aRXVm>fUR;c*@MZQF!?aHu8pmyV(Z7)#(`~8u+27X^B&uVVcXK!wmG)lg>CO( zyVBThE4F)u?F(Rg2e$8x?KfllAJ`!lJIufi53$1+Oo_sjKA5rwQ%+;bSL_&p9jjr- zG1&1uc9OBvVC=LGJH5otk=VHdcFx4kzpzU(c3FvC?qHX{*fj>b4#ciUuv-9jtB>7Q zVrqU&?TxAbVd_y#eTdzC*u4dI--_MuVUIBEk%2vyV~=at<29ynm{u9nMq}C?OpnL( z)tFHPGpb?6ILtVP8DFud4}12)o~N)^Y3$V*d(FXKH?X%Ad$+{iE3o%N?9&kYtiwJ} zu&*8acEP@*vF|GEdlvhC!G0$8Yl!`ZV!!R!?=|+9uzz3dzY_bu!vRq^U?~nbgaf|f zz+yPCHxA6gL4|NoG!9C^K?`uu9USby!EJHyDja+Y2j}3B{5Yfx4rzu%M&Xd1I5Yr< z#^TVvIP@6~bK;;@BW*ac z8ID|nBM;)pr#Q-iqnhKWSvcwhj(UlseK5B=Egbs?$A#gzia4$_j+=zz4&b=&I9|o^({TJQ9Df@p(q)`n7AJSX$y0IiQJnk^r>HokElydEQ?B7u6{ilxsaZJn zH%_aJ)0X4(5S*Tb(K_9;$67-4K5LJ zNo`y*5|=E;C1-KTZ(QoYr3tt+1(#05rTcN|GhF7tW#w^MFI=__m;J)!(YSmZF5ipG zzv7B`T=5^Sc#kVhT$zF^*Wk*}xXO#GQgGE;T=fuF+i-OkTs<3Czr{6mam`^|TO8N6 z$F)arodwr5!F8K(eR*6z0M}o~4MlOof4JcdZmf?RPvWMUxak;fw&Lat+`I`lzrZaF zZi&JzNw{SeZh3}Vi{aKzxOEe5J%(F<rDSB{91#W>3NFQ+OQkcriSlipTfk@lSZ7 zIi47aCzj!fU3lUMo;ZsqZsN&6JXr=$HpP=Y@#I51)d^2c!&4ja)LlFshNlzobT2%8 z6i|8v163+$VxkxDT{6IXv2hV@S z3l;G~L%c8oFC4}TSMj0+FIK~gmJ}c&QIwT8Nh};H7_fxfEXRh?ghf z<=uGsJzlAdR|eyi!+7NbUiIfT9PsKwym}X}6~t>*@!BN3HW#mL#A|!-+H<@fh}XS% zy%=6Ehu3T2^;UR&JYHXc*YDuh46KGd_4kR@50wt@bw3LlMmliz&Gvi%`AL#2;Y3d zx1sp9625JXZ};Ncr}!=(zAKOK+TpwH`0g6Mx8VB<_&}p9Ao7P5e9pKX1U#7x7C7ekqAx zM&g%k_?5!1L-Fe>{8kjdHNtNz@!JdhUL3y<#qa0vM;`nUi$Buw$29yg7k}j5xsN{s z@u!AAYva$c_;U~b{EffD@K-DRwH$xF!rz_o_a^-P5dRqXr#=43#J?{5TOI#)#J`L1 z?jBQAb6YP zZdB&ZLFR5alFuYhG|AJI zq3cNKb`pAkguW&P!bpKgQeY4%u$2@zN(wThU{z9Z1Sxoe6#PUAl_G_DkV5N7p*y6| zGg9am2@57+;UugQ2}>nm!%5gq5*|Rp<4E{K5`KV$esB0VC~XCnP0GDBpE$SsMSPUHzhUP|N~ z;)*1$e#CWzxCP>FO5CT3$4)%WiRUEod?emT;_XMgCyAmFWdu>K5S1rt22r;Xtsv3b z5^WFhDa1FK_)Zev9pZaV^f00)5WOMMTN1q^(T5X#EzzG4zlZpH6aNC@zeX#Ws;*he@%2q<9P|K8zIKONxIckt0duUJ`kpln5myVo8a{q{J># z;vXqFos_&!O2v>;i%F^9q;zvqdOIm&BV|gFGBZh;k0h!QiP}QSQlxBaQg$zi4kgjO zN%Rd;E{c@bF=s!SwRUX!ZHr0RJRSC7PHk!n^_ErL|*OsY*K z)ozpOVWfH@slJQEyGi^65`T{*lpqPKNR2$CMqyGTp43PtH3pFy4@k{0QnN0pxti3n zky>L(t#71u15$e~sr`x6sYU86Cw2akx^blLc2f5Nsr!r63nKM8k$O)_{X(RERZ@Q# zX&{gW3TaT5G)N;2-jRmQNW&?l;d|1^K^pZSjh2u`KS^Q)NgPQM&ydD-NaNk4@nh2X zFKI%PCI)HJk2D!UnoK55vPqIkl4|`w6y5h<2;LV4aPIS*WHiX8$cRG2`q-Q7y-HR> zLRPXjS!rlc+M3E}4|{JRtEJ3rmB^~TzCYgQ+<)Mn*SY7dtP_>>XEmd(nz2pI$W=D= zl+7e%6RB)U)y$D<<~B8RznXbY%`8*1TB})y)vO0arNO4aHCYV`@V`loUps+@N#=OfBF zLOGvO&Nq~Ek#hc~*3?pKMyNIO)tb|4ZELmGMXkM}*40w$CaHC+)w*M9-6yr)Os(Ip z)@P~>25Q3*wc(fAI81GfRvSyyCJVJ`mf94iHvLqajnrm)wb@B+c2}E^sLfGobE(>5 zs4@ZI#~wf+JOMxe6JsLflkHxeD#CLMN%vnJRRx3jMdu z+FgYnQK8`~^pOfJR$+rw*rk69uhmgYb@Z4DucpGMsqhpP(ON}pR1v8v;-QMHr6N14 z$W8nWaTnC_*6O&eI(}1~=&DX^Q74|N zlXcX|>wR zdAmxEQpsg1Ww=UNt5OnG%6FAIQl*Bfw8koJn@Vq_()X(LS1MzI$~d7;w^OG>)ERAc zCP1CFP-i{W*+g|tPn}z;&K*$a?yB>()cKX_yt_J|tS;!P3!Bx2H|nC6x;Q{xJfJR? zs!OBPrD%1jOkLJdm*=RykRZDesrMl{`u6|V4hN^3s>UvXk zeXhE`TV21SZZuLiCaW6(>c(?*v$wjrS=~%jH}9yMW$Ko*x)rW&-B-5_)a@newy(PV zS>5TZ?yOXI($(Eg>h1=0H$&Zht?qSE_gvMzS1Pl!$~>$x%hmn9>iz+B|ATr^Up-i; z9$Zror>KX1>fsBO)mUZCQCSHp>#us$NIhDn9-UW@&D7&K^`yIc5}=;eP*10*r|Ifh zZS~AeW$UQy87ezkWq(jPja5!7l`~r9tWY^eRL*CW+g9c7Re7c=FGA%vSNYB=|Al%! zSv_}C&;O``^{OC86}C}@V^rZWRd`bsR;m}h)r$@4g{OKEpVR# znXX=GsaMn0D{u9xT)iHmUPr0drRt5fdb2>iS*hNnsJBYJ9i`qLQg5?VQEgQ;Ruyek zMHf`jC-ttGdS|8HMW}Zl)%zCeeLwYnhI${M-al6#M12^fK5SDT($t5~>Z76hXsbT% zS07KQk6+ZMR_fC%^~qCxdZ<2Ys?QVDXCL)BSAA)vzD!bIeAJg4>T5mqb)x!uNPR6- z#WhuNcU5ewinprbBdYj`Dlt$cOH@guD*2^KhpAFGRhp^3byMGVsBcB8%utn0QDu8n zS(GZfsmgwOZ{xDeojz7J=M>& ze~ahUui5HXton6J{i;;IP1WxO>bHyfeNz3-Qop~cKTXx2LF&&A_2-QGQ>y+NslU_J zUsv@vUH$#4D%z+Db5$`!Rk)~%tE$pORobY^eX24>RlZeK8mg+Ds&Y_O>8h&W->eC$ zjY2gyR6B=i-%za*)f=PwFjU`$>S?I{1!@|UH`D{54qyrF0FDEtU?GBoZ(qYxV9sG*M<-BDvMYV1Lcv#3#k8b6_F4$bM%Tm{WQXnsUZ zebgL@nvSS>7&Vhn^D$}`p;lwm8i`sPP|E|gvQfJ>YMY|=TGZZ&+DWMMZ$7^T>P$u* zZ`ApB`~m{_CLVFRkcS1WB+IOK{3Y|XCSqYsO=#)d(0J>A5yAQf? z(0zisTBth!b?2e(GSuCHx*@1rhcvkFG7R=(7+iD zlF{G`8k(b_6B@>&;Tbf1iiX8#Gyshbpiw#+eL-UbG7{w6H;oXJ}E5mi^IkJ6hg`p}?>^4EMwE1`OY!l{Q)pL90z@bqlRNptT-aFGK4S zX#ERqtkLEm+T26i)@Zv1Z3|$e1Eb+E+6AK%F!~6i?`UU)c2;P&1no|s-3PQcK>LYk z?}PUDU|bEx-C^ti<8T<~!}u#q3}CVmCP!eBi4LvM!3`a9(4iO|$D?BqI{rkbVd%6C zogTr|2&QLYS`M@NFf)ePB$yqA*>{)^g}D#RAHt#!EDpfp2|D*i=T+#OjV>1GG7DWU zpleHX9fhv3=%$Bm+tBSUy6dC+W^{jv|2E;jO!Vl99--**1wBWhX9#*Gqn8GHH9@a7 z=w*&x>(FZ#dL^M(CVF>4?<45b6n$LKw=Vj|pSO3C40XrQ(-`^!!)!3jAC_9MTno$B7(M~R zGcckDMtEXmBa95isO}gQj8UZ+JqM$&VoVK;S%@*$Fjisg42(_2I75uvg>j!Sei6oh z!30Z8u)~CtnAjW>2Vmk9Ox%HqhcGb@6N@pa9VQLIq(hhtOkRk|IhZmCQvxuh7*p$D z>O4%njcN5TZ8@gx$FxV7R*30!F})?Gn`8P&Ot;2#2TWg&>H9D}0MqYc`cq7Q0V_RN z8NjMNtUAN053EMR$_7?TVC4_1a9Evy)p=Ou!0IEce!#j0to2~s9M&CR-5b_JVZ9pG zTVcH));_QfhII_A6JdQ8)^}n34Kq4pMsLh;z>M{nu?sW8G2;SeyoQYyY)oO(4>l`d zvmG`8ut|ZcW-Y=jH_Qshtjm~P z6SGHQ_G--b#_UAQeuCM5FsC8r^v0Yym~#npK4ESH%pHljn=v;Gb3en@1h(T~I|sJ* zuw4$@gRl*NZ6s_@!S)Gkzhj;O<_*F;d(7L9d1;vU4f85sR|9q(VAmCPePL$_yNR%~ zf!zYwxxwxZ>`F0T2lJa^ekaWDf%$_m-x~AhVg6Fg--Y>sm>+@p$1(ph=4WI6S1f3N z1!h>#6AM;g!7(hjhy_(x*dGhmVc`xeJcWgiu&^BV3ijHtZvy)^us4H!PuRP_J{0y> zVgCU3d9Z&6`|nsZ7K_}l=ms3B!J#1>#=*f24t{WWfW@`3xH}fxVR0Uo)WMR5STY_< zmSf3fEXl=^3M@6m(hXRefTf?{XaYwEI6A>`GaUE8(G!mTaJ&G=3M?ChWm~Z90hZUt z@=;hGh~s*dm4C6SKUVF)svB_X0;dCTItr)TaQcna z9kJRPt7EYGAyz-f>JM-RoLj(o0-P7Y*$K{D;JgpcNpL<7=bLc;3g_QgGa74FVa;Z& z*^4!|u;v@q8e^>;*6zjHlUVx%Ys;{%4%T(Sx;a?49qVGS?jzP!VSOL0pN91dvHl>| zzr_YUY#4?OHrU{V4e{7;7aQJVqhO;xHg?0tG1%yUjRDwr1)G{<(`am3hfOiqbPt;~ zvAGjA&%|awY%ahSO>D8omhISb5L=F8%X4hi$JPbdnu2ZG*k+AwQP}nr+v{L^e{A1~ z?MJYqC3XzOj!oE+iXBDRN$fPn&e7O86FXh8^DcJ&!LI+XYZZ2-W7j9Rw1mraxNL+= z5q6Kn?q%5RjolZp`y=+$#h!lHvk-gsV$VtJd4xTGv9~Gq_QhTY>~+K54D9`YeYLT# zJNC`RzCG9%jeS?KFCY8sVSi8Tx50iF?2o|y^Vt6yuC?LX1FrMo>I_#`xMt%(eH>VT z0|7Yj6mAXSW&^jyaN7a5Xt-s-?H=3;;r0XWwcy?Y?mgf>3+}7n?g#g4@TdWg?(moo zkDc%chR11mJcUOIJPqMF0G@8}ya&&>@GQZ>Iyg8A2c2**3;Z+Xr8t`rn@2>Ek3~xJlyTCgX-m&n$3hzvK zm&2zAd@SKJ89oc)vlc$v;1dR))9|?ppJMpdgs%mBd%<@we8<3d8hq!%cN2Ug;d>6g zx$ymoL%<%UBBTRC zx*=p7LZ%~RER>Fh0w+b9fQzm2z5qiBtlOi^g2SHA@nQ4 z>LRQ?!ulg@3c_X~Y%{`w5EhNFc!b?YSTT;)z|nR%YK@}@ar7pRX5nZt!nF|I1mS%V zZjJEW2=_yH9Kz2b{650V5K$Kq0}tPz8zHh2B3B_Y4Uv}+)gDou5j77{ zj)+=|sC|g?MpO`@q7W62s0>71M$}_O6(Z^*qT3_7GopthdIF+d5q${Jp@@z{^uJO$ zV)PJWikR_;u}92S#2iM<8N@t7%tstEz%eHri^Z|)I97mTe-PUMvCfE1L0k>Q86d7J z;>I9u1>!a#E(&p%aJ(jtPsH&9IDQ@{8sdZ@PI%$O8Jw(+ljCr5GfoEKPAMEobj|3JcjNEm>G1xPrIgiA>HfJA*HwnySPB*r1}2@<~{ zsX3CSA;}daMzSW7>m#`(k~<)|8t788i>>jNWG2J$4LE+G!3NHMcOK) zMIbE)X>X8Lf^;*a_eT0Kq)$NlETp?2Jpt)Akp2egzmQ>wjPb~DLPiKO&LZOtPPfPD zJ~%xSr13RKh|^U#V~8`WaV8LF?%+%b&bGkWsW|J4vtMzpAI|N;xfeLE zh4bBUelN~n!})i(&l$tq<91)%o{8H#ar+eR=;Dqs?hMBr2i!T1 zJC||iEAH0A-9EVMfV=x}HwkyEaL*j~7U14t+&hDNpO9G(nLUwdhs>?WbVp_)G9Tl< z0q)!4{%YJ$!~;z{7>Ngm@!%dF>fqsQJaoas`^ZwrYKg3&$Xbf5lgPS)tRg%z#G^%c z8cI4Nni@=~F!Y zhG)I;Y%ZSNN45^K8zZ|DvJWFW8QB++osaCd$Sy|qFXSlX)IrX86`~u|v z!t+{q-UQDV;<+21AI9@YJWs>(TX_Bf1+`Gn4FywCun`5mC`d)YBNS?)unh|Ppl}ij z9Z=|k!ax)rN8uF|{;QVa1@NL7UaZ8619%aS7kBZZ2rnw}QU@>1@NyVluEEO#c$tQm zSMc%$UVg(X4ZLcMSH^g?7_Xf1Y7br|;?*_0dXLv#@!A=$!|?hNUT5L;cf4tcH~-V%H?DXSg*P|xCL3?7;caWY9gMejc)Jg8^HEeEMJ6bkiK5jg3PI65yc4|Zj&}?3 z&JXY2;(a^3-;4Jr@cs+l|HcQwhyM7m0v}TFu@yeL;A18}HN>YO_~e35$@r9u&pP-# z1)mS%^ErI}gfHFj#RFeX}>rk>6CBZ03LdhkRWTNCNO0`ki45hDd@IDaQk3bStS!pSQ8p1}+ff#TvLuu}M_DDlx4?H3eD8_x zWAJ@3zVE~LWB7gx-#_9F1%GScuPOdc#oyWZy9j?*;;$?I`rvOQ{$}ED4*vc`MGI66M#UIZ%t6IQ zR2)UcX;fsP;wLKWp|UM1d!f<^l^&=(ipo?}-a_SDRFW_5p7KgsHsS-qIme^cpGwWsPr zHG#^RDvjz9RWbj4KSf`{j@U@-CZdTFQj6?B_9tiaA2CNSGJ^l)Gu|YN$WpR`qDe8J zjH0Zecu~$$o>Pjcp-By6YS>U?Ej9L0Ba|A2)c8n^GHO(^h9+xtXN>`@Vb2;XStF1& z@>%06Yy75WU21lq=5T5*qNXP`qo{eFnw6~CoHcu}=6Kee&YE*r)1Eb#v*udX+{T&* zSu>0^kF#b9Yi6?OS^FAmKVt3A|NK|hsmnU8Sf@Yh>|~u_*2!R z6>9C~KOs;ngIZUql}D}D)GFgYHSZsQr`?;{^QgU_+DE7zOYJAr{y`mW>R3=`40UEv z$B{Z)sk4VV9@Gh;&ME3#piU-r3aImiI#twdM%|9o?MvM;)LlwlSL*sx_dazCsQZ<= zRjg~wx?NbeFY8*e?l{(+&bo71*Nb(JvThRVUS>T#*6YW5KCBncdRJNRDfOyT&yaef zsJD)KzSK*jULN%-SidRj4`%(ztiP1?_p*Kj>tAF2=dAyg4QjAKV>bAY4TiJ9LN@Sc zgDY(CnGGu0un8NQv*92%v|_^*Yax*fHrmfdm)Phx8(XmPLN>n1#^2dwB%7>b zlXGlR!KQ85bTOMov*`miea~if*lY-!ZDg|qHhaoug>3eL&9&LQH=EC7^8;*tjm;~m zZ$Nz$>UX35O6t2){|5C7ssEAsKWI>$26{9wqCpQD%%Z_=8l=*oj4kT1g#lZbv&B@l zSi}|w+0v3NH?rkf8rGuW0vg89@CFUDX;{uynrzjCt&G{KCtJ;8tDS5W%~s#odL~?&v)v`OyTf)**j}6MJG1>%ws&It?QHMO z_UUYYo9&;`xH^sN(6|GQr_gu_jStZ{mB!gL{!WtyG%=>hK$=+7#DOO3X|j_h2Wa9; zlQT4VOp{V}XvPj**kKquShK?_c5r8h@=O79N1|iJMCqsFm}4ePWRdA15NAD)SRXhXu5``M`#*J)9W;S zNYiYZ7SiN*|qgivBwW8Trnpx3oF3q;nER<&FXm*2UWi;2LxdF}F)7*mQHZ)&G z^GKRMp!o-y|D{C(TA0ydI4u^@VmmGTX>p4dk7-fF&N}SelAVp&c?dhtW@k5c_GRZF zcD}*Rui2#myYyt2N$j$WUDmUU3%hu-%W-x|W0%Y9a*thJuuCPo4q?{??7Ep@$yjwy;ky`^2-)efBA5Up@Bi!oJq*yN7*`vhNl4eapVZ>{pxp z+OS_&_8Y@~3)pW9`|W1GL+lsKerfD?nf>zF?=$0 ztDt2KTI$lWDJ@&mvI8x<(sDd49ca0omaeq)rDZyYgTotfxCw{PpNALW?p9Mgtl`g6=2j)~#e z8XVh>V@Gl95{`A}SU-+Uu zqdCEe6GAy5krS#ou@xt-gJ4oV1*iJUJ|98O!rX~#M3Hm4PG zdKXSV$LXJF)sj~IX*Gvdt7#QPs{&e8(7GwD$J6>St*_9!fY!yFLC$Ev83vrujx&05 z#yHNf3ICnJXPUl=F&fUtniJY5B+q$$hrR_-CuBB}RZL>J9Hs|fLRq zrlTnx|D)pwI!>aa4ILNKaXB5=(Qz9cUFqmc$22-#reismDK4wSWfol4hs%a>**GrS z!)0Dv7SClRT;80^dvp0zE?>#z2e>?q%d@!r2UqBFg*jJ@=Za-q5ylngxFU}$t8=9V zSFYsBM6UeKRlT@s1y{v!)g7+-L#LK>>P;srI_;%X6rGajR6wVXTy4bFgSgtBtKGQz zCRdlxxiy`q(%Fm7Np!wL=dWDTi)$uu%|B@Q5Z8R-+D2SEm}@t1ttZ#UaP2Lw{m6AS zxUMDFb?3S~ecW=ATOM)CH*PiK)*jqChFj-x z>ppJ1$8Fl&X3lLxxNQ!%ZQwRvZac?q+1y@_+dFalB5vQt?P1)0l{;Ei~B}an~j8%IB`1bZJ1B&U9Hsm)&%U zrArcB?$hNtck6I>8}7E`?)lv9%iXuRrxo{X=AOsg^P78HaqlSZb>d!s?v3Z(H{AQ3 z`&x3}816g3eaE@)DffNh{ubQt!2MUazk;q>bZtRbXS#aPHJGk<>H3te-{@Mw0~$Qg ziw8FHKnf33(M^|b&FR*WZbRrcoo>777Dl&6bSt9UH@a2Qy(Zlo)4d(tyVKo{?#^_7 zMfV@{s6mgO^jJ@iFnV00$6I=8(sLj^H__9No+J@(L0Xb*XaG2-i7r3 zPM_-Z=}w;&^w~t8J@mOp-|F=3O5X+aT}j^{`o_@r4t+~`s4fp#@X#tAI>(nJUoDh*YNOm9=^lFPkFeUe#Z2hLcas_yGp-j^!r4=pZ`d0`ZuP(A^lD0-SP6lK!80q&klbM~$71NJc>k^$Ek@RosOU}px- zW}qtrA2P6_Y5jya6JZ_Gk6Sxr!m-;!Alstfx){O?8V>< z49;Qj8wM9Mq$5Kd8FG@L%@{g{p&J<*%Fr~17BKV=!)nn8!M!7KRE~A?5R)` zTosSE@npOq<2y3G2jfRE-ih&h8GoGdPZ?jz1RW+cVZvx8 ztYyM>Cb%-emkA+ExXFYpCgd}rhzTW3Y|cbWCXQ#K6%$u8aVrx8nD~^5KbSO-NvoOU z#-!6s%4M=*az`eQVzLvHgP44i$*-AGoheBY=w!;GQKux7@3X81DW5>I#H z=?Of&m8Zjb`u0CFooD*;%v7G)%rnP%CYNVh@oaCNUB+|9;UbN!H-Mr|}i^qBK8880f zCE+D=Ub5z;UAz>|OOJS|ke6HW@_1g}%*%m1c_orpZt==TUe)E* z5xlyJSKW9ul~*tGY96mv@R|XyP2sf_yynAe8N61?>ju0&lGkl`eHpKB<8?1ykKpwe zyk5l{y1Ze=8`F7XCvRl&W^3Lw<;}Ugxtljn@aDCD)H`ntW4Ix?$2vlcRI1GBuD70Ilt%zDbKuY9EVs2Lx%=c8_XWXVUf`Di&G?cpOo zK1$=GTYU6^k2Uz%jE}APcqt!y@NqOBXYlbuKK{TbI(*WEPg?UyCqC)PCv*5@5udE# z6Bj=5=94f!Il(8__~bpGYV&CmK5fINUHEi1pDyLojeP3Ir>FV!J)bq=vmtzD$7ehF zEP~JO@!3aa*JpNTX7^|ISY|I{_HJeeF*};s3CzCD>?h2A!R$}W{=uB;%&E_ z3z-Mz)o0#7=GimPi+SnHyUe^#%&TC&Ci9yx-<0`1nLmm7OPRlh`Foh}!TfmUr!)T| z^KUW#C7)~Xxh|h~<@2$8K8?>;@VOtKpW*Z8EYM~_XBJFgfg=mnvLJv3ku1n%!5bEQ zVL>?ytFzFIg+o|4pM^VE7{bB}EPTwu0=}ru7ajRxHeYPui*UZk;)`#5S)VU^@#Pf0 zoWqy9`7(|#AMj;4Up42efqb=tufqB28ee_q>-v0c%Gaa$+Mcg>@pU9$$Mf|=zW&NL z4f&=I-^}Hkt$gFhH{pD9mT#W$&A-x5zOBx;wfI(#Z~OD@e7;@Ax9j=Vk8k7nHkofT z`8JzH8Z0tr(QFp&X3;?w1+pldMJHI4%A%(%DrC`HzH7vHt@v&%->u=hZG4x&ciDXR zn(w~wT{+(y^Zj7Hci{Vjd>_E~DSUr{?;rAgF5egNLv?;=#}8)w(2F0Y@q;rz`0ztI zKRo7#GJdSdk8SvI06)&)M;Cq!;l~Vq{KijO{M3t|?D=T}Kl$_1S$-^7|@&_vZIA{Qj6fH2K4bKf3dWC4Y?P4@drR<&R7J zaf?45@kbtiyylNj{87PjO_uAjyeG>ivfP&COIW^|~|GeX$Z~R+}e;e|zA^-N{-*Nmqmw#9A z?>7GRq)uu|dWU2O0s=box4WxQ!sqQG%y`}mEss37&rl@+N28)_6%0-liC_hn2qB8%D zW=_|I)Yw;p@I#9SV5jpSJ+h8UpP`YNw`rMAiOKg7QPaG7XB20h?YoWkyaud zMS6$~7MUrsT_ivxO5}z}foRke4MWlBAsUlJW4UM?5RG`zI4c@AMdN{JR7s6CQe%|V zSR^%^rN%C)5h*opN{uY3Q7W2sMN?li+l!`!X!a6KE74phnukR*RW!3j^Ow}5)NCU) zEv4o{sTnLa&q~c)srgfCHJ4ibrIwAsx-JE z4a%fpLuuGc8rn$1?b0wv8fHktC(^J~8fi--6KOO|8aYX$0BLkl8Wl<7deYcJ8qbi% zo1}4sG%l7V+S0^Wnv9SptE7pyG)a{vFQjR0Y1%`Y+DTJaX__WYUq~}eY1ToSjgV$5 zrCF#nJ1@=tg_Y9WNSa$pb0=x;CC&4s`8&~v=v#`ut>`Zi{avE(F8ZOOe^c~di~d(J zXe0)PVlY$;Jj5VH4DzH!V`rS)uSy;oZMOY1CYT_J6Zq|G2{vsBvbkTwUTjjyyxkT$=hZAWQ4LfWpE zwr8a6BWe3a+Wruu8e-H|jLgNTw-^l*qgi5fSd4O|otCs~C+#LkyOq)|P}(I+yEoFl zm9#gN_M@f!Y-#TPol%(#=P@-H~n|rF&cHzFfNBm;b8Ee|_Y?P4eFr>7gk-`bm#1(&MD` z)Rmq+rRO^7=_5Vkq~{mu)kJztm0l~P*M8}BS9-mW-a69TL3&3@?=RA)hxGA~K6%pD zRQfKJzV6cZz4YrT{gR}AE9q}1{clVEVi_<}25gc6S7l%W88}`B`pdx2GDuGb*~*|h zGN?)h50=5MGB{U;n9C4<8S+Dh&Xl2vGW59&t0}{l%dkwb94nTNVwohC-(~m!8NNw| zUzXwDWkfw0(N{*;$%un8;lfQta*q3~smz!tGu&jxd6`imHl4+0h1j@= z%_*5#Q)Z5knQLWcxXgSav$SNEjm+93v(Cw^BAGobM$0RCz)d>b2iDG zQ!=-{%r%y|Q)TW-nR`WS2a4@6vArv{A7q}s%$q9nVrAYZv1=iAR$`Yfc3CptROW}t z{LivrkSuVK1Y6y|h*KYNS|?8F;&fS@9*a|fIK7kA4P|u;S>0Y% zTgYlhSsf*---@%LINOQyVR61L&JV>oPn_S%8WUMFQr0YxH5X-VHCd}CYxQMqds*9A z){c_3Q)KNzS?exq@5{O-vaXk`+bZi4WZeT<_e<6r%KDwMK2z3L$Oco{U?UrnWuuO4 z+%Fr?$;Kkt)K)evluhxn>Ar0GC7TUovz2W2kj>9!ODEZ4C0q8%mO|OuQnrqkt=na5 zoNTR-ZPv2wmTY@2+bU#xH`yK~+t14OEZLzgJ37b?TiFpLJ6_0+3fb99b}pBlyJhE9 z*;y&OoMcy&>?#+Rq2h8tT;9v>rn0-Q?6#NPCuNVO>@k%+(`CgqqwvxTJve!-a zUX;BbWM3WGXD<6D$v$Vs_jd8VEZ$Y((_DPUiO*8;aS@+z z@ktk-OX8CyKIP)8FTUf&*I#@;%OOoU)LjlOkV8A=&|NvKBZr&H;l*+|Ru1RM;SxDq zA%6A5ubcP{7r)8kw_N~f}TroZ3*rm!F?onf&|-0u$u%YNk|h387(18BxI|E?2(W& z67pU`8%k&&3AK{YEfRW8LW?D=wS57eo5UQGm;{N*keDkHb5~-XNKB!`{FY;F_@9yhNoXPo3nXEeBm_#rNlCaW37L}c zOcGv7!Y4@_EQvOfxKa}LNTQ!4CQ9N*N&GHJ?IdZQBqdAICrNH0$$cbwf+WwAksk7)Ztl$(S!0TO?zjWcW%(sAQa$ zj4P6HS2CVR#!orjUQSPv(`)6lx15fb)4$|Q8#!YtXGY1H6LPkWoZTd6!{ltHoc$=@aa?VH2#mc$Ma;`$oHkc(~PVrRKHKrW7zi|6HHj$HiyKeoODs*0X#SHwI|Jn9jV0|JMt z0v2poK|?7y@>B1;s=WONg{rZh+it=*NON<5uYOB ze~S1&BEdr>_=|){kuY2&%ohneM8ZXpkS!9;MPg}@Xe|;eiNppXv5iO!6Nv*w;z*G= zNhHn|iAzM{T9LR-B<>f9Cq!brNK6rlnIiG6NHmG-jm7nD;(D~WK3QB(5Z9lI>xxJ! zC6X$LBzKWiUnDgXNr56MOeFOeNkc`_B9XLDB%KmT$s*~INO~iZeux_oH=M-{4{^g! z+?XnEJQ6oviW{Fraxsyt6UmiCvZqL{FOr*zWPg#|StR!q$Ds?;$~BEvzxftTil!=Zf+1akBOT};%2J2RbSi+61Vz_TT{iYb>h|zaqFkJ zU0U3B6}Ov++dakY5#shFaeI!qy;R&@CvIO5w-dze6mk2VxKmQxaTa$Pi94;toetv8 zcyZ^Ixbs!qDHJJ|B4w&bnI}?~iu=_5sYj7YyN z(m#oeaw5Y;WcZ1UVIpIf$Ve0!Z^eC`xbG?MHx>7z#r+s@KS|twB_5O%5A4K)7UIEZ z@nE-jkS-pU5)TdHp_h2rQalV254(wn{l&v^;^A)b@Q`?zAReZOhp$DZt;lR5GDAe> zK#{pfWUdyOyG7;&k(n;CT8pe`k+oQ4?H7-n#UnrQXrg$uUOc)i9z7F}_2RLwc-%)k zo-ZCB5|7hFwwcH-BeMNO_HdECT4d*oCpO}Vk9g8bJQ*UM>=IAzh$pIe>L#8J5>Jyw zj#1to*Bin+TvM+cs5@=+bEtL6wm&O z=N965CGp%xJP#Jnhl%GC#Pc=c`7!bQl6amho@a~aZ^iQ;BDa{xwG+9OM6RF64HLP; zMebaYyGrEl7rAlbg^zgAO1wBGUZjW@kHkwMUV4a^zT)Lr@p7qnc~iX16)y|KtIFb4 z3-PL#c(p*h+9F=XiPyEn>+a(9T=9ChcvC^VsV3eu7H`^$H(SM<>*7tGc%zE9LcFyT zZ>x#7jl|p5;_Yzpc7k}jO}tGPZ~usQ?&4hw@ve_}w^6*iB;LId@6E*fYT|uY@qV;; zzfio77az)t4=u%qDdNL2@nMJfa9n(d6(2PC9r5A5_*h(g93wvN5Ff9Kk1xfi_TtlQ z@oBaAbWMD&Ek1V_pBISFKgAb2@x@nsi4b4r z{PYz+2Z^66#Lsx~^M&|j5Wnh)U*Y1{R`KhqP^^XGC6sWX%n{07p=1e@g)r?Drt`w| zUgTSd{0<^NROAm6`HMyV4^iMO3VMoy$)aG5D7Y*Na)l~{>MT@mp#}-HpHSBb^`uZ= zi$a|!tRf1Bio#i<@S-Tp5QV?QZ+r3ETl|g?zekJT%f#>f;&-a}{YCtd;!gwdXNdT- zPy9&`e?E)9*5Yqd@wc1!J3;*2EdCx7f3s0c`yhxbinT(q2oxKOV)Ib!0L-ev%nxQg zU^WA0>tGfOvrL$oP`o&bmqKwX6!$~%eki^O#aE;FB@};;;y+<-3G+HI?*a2^Fy9OF z8!&&15*8?7ixQ1dq7O=JM2QrX_zt1d{!Ip9gs2Qr1EP&~pn{kSaS$Q};u%B%Py(n3 zcmW4MTd*Fu6g&;y0bhfEA#ET%AzMOrha3*M6Y@4>4&*nKEP;~MP;wPYCZJ?Cbksgx z4BbWOQc$WMN;N^Ljwm$)rOu$#N0hce>AEQ09;FAN^ca+$kJ6h^`UpzLqV!Xgev2~2 zP^J{h*q}^(lo^9EOHt+y^zP6%f_^UaH=zHDvdvL;8OmNk+50H_0T#Bfs0fSdu&4)% z*0AURi!fM3!eS0AF2N!T7ABM{j&c=Ht_jMuMY(<`Hv{D!p%ejpEZ4yD3CcG^ z`Ee+}7*=Iq6$Y!_uu6bI4}%>HHDOo`!$TOp!@4T0>%qDytlPr6JFEx5dK9du!TJKM z^I+2#Hp@`K4i&;s;W#Q}qCx>|tzlaawhLkV3U>8j7X`bSuv-Ybm9Wc%y*cc|U>^%( zc^F&67zN`T7>~i24dW{qKf|FI97@5#1r9!Nm<5M8IO^co8jcZg91X`+a6AadL^$c- z)B#Q-;B**HZ{b`P&h_Cu8qR0o{0=VF;L-ptfpFOkm!ojG0GGdTZ35ReaP0usK5!iZ z*Ku&23D?)CI3E>rQOOgPf>0?Gl_F7T7Ah@8rS+(^8Ao-Xig2+z*&+yu|v@H`C9m#E=^ z8qHB-K5AS-O>@-rN6k*C8G)L!QFAS7Zb!}isCf-FZ=q%eYCb_NYt(9tT9K%=6t&i) z)=tzqfLiIO?StCksJ#reH=y=T)INpUPf`0D>Xbm8N~q(5IxSIW4eD$~oqect5_Rsv z%L!fs;I#u@SK##=b(^AYTh#4>x;;^MBI?dY-KD6z9(7-#o(<}?L%lDk?|}OCQ9ls% z@1a2hGzde3f8gx_Z!dT^f_H0pN5gwGyw|~dJG}S9#~MBj;L{C0ec`hfJ}=?(2@PAI z;Sw~wg@)hZYY*RG_>P3{Wcbd7?{fGag6|pl#=-X{d^6yik4Cf6=l~jJqR|&Lc0l6^ zX#5`sh!(ZcVi8)rf?p{7`oJ$5exu+w8Gdu&w-kOK(Xu;QUP8-EwET=#o@lictqRcE zfYz>PT??(7pml4so`BY?(fSkGIHJuMv^jt_nP~GIZGOYQ4E(3SKMVc}+8WSy7TRt@ z+w*994Q+3tZ5{%OBfuH~l@L%L0Z|ATi-5TZSc`x?2sn*^1O#Lt;1vRXqMbL|wMDz` zXg3+{j-%Zpw0nVezY$m!fnEppDq#{@#SdZWe2(E+R#t05Y@B##{M({QSA3<;|f^Q=DC4zsU zy#eig(7p@W4@LX&XulfmPoVuhwEu|?26U)_4#DU!03DX0!zpygK}VvaD>}AD$G+$| z6&(+tV>~+EK}Q9hTB6e|blQbZ*U;%VI#)pF2I$-jo!g>wM|2KH=lkD)%j&7dl7KU#9&}|#KC867E zgy<3Cg^;EQ2|&nDgp5bXT7;ZN$X$fIL#R1IOC!{PPzQv%A+$C^2P1R|LboCGB0>`p znu@S;2y20`$q3twFcskf;T8z5h46+5_d|F)gm*@G4}?!a_-2IfL3lF4zaYE--D{wG zFuD&$_r>Ub6y5Kmdk(t4M?`r%+bRFJsi-Z4tlgi zk1puZ7d=Ly$42ycgr45$xduJIpl1Pkl|!$Z=rsYoHlSB5dObp~pXgl{y$7TB81$Zs z-n-Ge5PclcXEOTiMxTr5^BH}e(Ki@<$D?ly`d&ug=jc}g{VJeeb@XeFeqGTo8vQn* z-zoHaihc!%v_oWFMD{`CTtps0WEvvBA*wW@JQ3xOsQ!qWfT(qdI)JD+MBPHvGerGD z|I+AR1^t_#e>nP&ME@1&e+2y#&_5IX6$}W%fZZ5y3j@AkU}X%ffq~61FaQHPW8gRp zoQ{DDFmMG1UdF&A4E%}cs)+7_=-G(gkLVMKet_tw7*rR7x?|9A3|fRit1)OV23^LW zhZyt~gG*v?ISh8k;5ryQ1B2&d@JbAh!QeOyF~^Wn7*ZZX8e+&m3|WXFM=>M`L!M)Z zilNpRS_?x1FtjsoH;nMqI;)TNsgn5&0OY!^r6vxfUaLVB|53%)}^n zjH-=M4KZpxMkyF=z-V`jZjI3cFnT;j&&TNX7`+dp6EHdjqcbr&7h|F@W--R>!nT62|?)_^KG+6XUmGd>STH!h}#vIE)FmF|j-* z4#vbin3#`AT`_4cCf&niBPI{SNQMF$25CPYlvxWFfAO@A~9_OrY*s= z&6pO0X-6>a9H!-BS|O&F!*nN1uZ8K&F?|81U&ZuHO#h7Oe=$Rk86lXl4l}Yb<0EGL z#!OAo6F>^O&p2kcSv%)cJIA$%xtR0wj1+!jYmWtW-nC*qx z0hrwnvnOKqD$G8H*~ysw0<%@j3C5f#%vppvF_@EpIX^Jhh`B8>HwbgPVeSIVJ&L)p zn45*U1(;`xd9Ik}iFv`8cMS8(VSZK2_r?4`%pZvP(=mT5=Eq_F1I+(`1tqb-2@AZi zpgk7!!GdvE@C*wIu+V^oHLnel4LA-i>0No)D266v9v#yF2mB}So#dhieZ^2mNmt) zFf1E|Ws|XN1D3^O**7e&jpYro+z-p!VR;uU?}g=4uzWj~-^B7fEHA(ci4|5@;e-|4 zv0@!oWMaj8tdv+;9xL6jvL;q~V`U4h48qDeSh)-<_hDr$R^G!Z8?5rcDsQZcz^Y+b zH4&>;V%2`E`h(ThSnY(>W3hS#R&T`W-B^7Xt8ZZS8?3R$8Yisrz?xcEC97#>O?+xDOi>vGF-JIboA0HU(kR5Nw))O)IhKC^jWwvpY8T#O4fa(P2wd zY#EO&tFdJ}wxnUpCv2^OtpV5?g{_;hH5J={ZNAtx65B3g+kI@e#r8JXJ`LM*tHA0 zu49)8yRERhHFi(I?j*z*5Yrkls}XYyF`ux<7JFJ@&j{?GIEa%qaI!5<_QJ`9IAxDh zYjG+Sr)_b%BTgU184H|=#+m&%a}8&H;cR7`?Siu-aCRZiZpYa(IA?})opJ6M&V4{^ zb;Qm`>}AA$!1;8iovB=T>6B|wz%9BmwV#!1YBN$%lmNo6Ry<9l^M9Q5m$a8t}Nm_ z5mz5^9S|3dxLJt1hPcPLYKg1Wa5V~77vSoCTz!D6zi`bN*IMFQcU(J*Ybm()2k~x* zk3{@@#P34f!;P-EF$*`2;l@)Wmqc=H zBnKlo3dxg@yd259k$fLFYvN`*+?<4)J8|;?Zh7FA4{n9x))3s9hFiyQ>m6>p;&xly z9)a6Sar+={pT?cyxKjal8sSbG+!>BLlW=DhQjAD(M~W{}f{@Y;DZP*~94XV0vK%Rw zk&=v*=Sca5yApS;aJLrjj>p|(+)c;b$GH0esS>HJkvbo#Yms^ssmVxvfYfKWXNP+= zaW5G6df;Av+}nbCM{q9=X|0eJg0%5STY$6;NZXIJGe}EBS_aZyB27WM71Bo`{W#L^ zA^jQBzahgM8P>?Chm2{+IEjomxbKDggK>Wr?r+BZlem8q_dnx-7amN;gSmKc6c4iS z-~}E64=dtfARf-e!!3At4G**MP(fySWI7_V0WwD;b1O1ak(q_ezsM?yEDL1WAj=V1 z?#QZzEFWaGLDmFh%|g~;WThhO5wc$5kvkqu!=pkxcE)30JRX6^Tk$vt*_DtTi0pC5 z-hu2p$j-zQ2Rw@2~QI7Bo$AIr?v1j3{N-V=~XXedgWU7TO-HVR7xs8j7cZjlVjW(5!b=;x9DtYW@bU~^zQHSNylR72QFyf;ufE`Q z6TI$^*NJ%j2(Q23O$od);!SP5X^l7C@g^2;Ug0hA)`+)t@pd)d{)4wy@b(toKES)m zco%|qqw#JN-aWy4cf6l~_XqJl47}&n@`*5WmXfmp6X(#IFPRl?25aia(SoP>w=TVG4n11xz_Gy@%-sOn;Csk>3RQ z{>bly{0QW)Lw*|aKcYaOzzGGdQP3U*Gf}Vv1+gelpgKYA2z4sdjZlA~&<2G~Q8);N z3s86hg-`I?5x;BWcW3W=XT=G#f&*oit0KSw4%`VDShRU(Mp_EdG_|(`o(>%~M&TBuk9Z9!6q`a};GM z8c__SSV9p)ag5?3#dC@egazSCv?4|m+lXJJC%KxuNaj)2rW`Mo3dmdmR!P; zTKOGy7S#2mZV+{AsoP22ZR(y0T_ol%?OZOc2YA zVVNx~^NM<3>U&YYl=`F8-=Y31%Q~=Z3zi+mvd39Aon`;h!h;t6w3tAP6|}fZi$a!b z!*bCqw}9m~vD`0O7Nez(mR7W^LQ5}NHl}3=EsxMLjh4Syo-FUq@-0|Cn&sEB{3lvj z(8`Zi-Dq`~R_V0*PJ=fMel!Hr5Jp2J4bx~?Ov4r$&e8CY292PQ)_Pjo)7qQX?PwiI z>lw6OP3v8>{z9A1wAo9WBec0ln+LS{MjMqCzzXG9!GRUrSs{!S7PG=eR@lc1Ct2YV zE8Jv-T-w^v)`Pa*v~5G%PPFYo+kvzlPuqF4T}#_Nw7o^!N3?xQ+n=-}?JCf&KJ7Zt zZV&Cg(B75y)oI_D_HAh2k@nqbKbZEDX}_5En`s|I`%|<}r2RA6f2F-jV`&;4Y4oIV z6pd48Tted(8V}KUmd0x|-l6d!jn8TPK!*}^u%bh2I!vI$YdSj6u{s?a(y|qK(>amOxpXe1 zOI^A|&}9f+7Sd%qU1I5Smo6Xa>PFX4y7r~(5W23U>lwP{(Df}{ztL4?#S*Mog%!hD zaXl+uV8s`#_?eaLS*af@-Dah1R{F%s23B@s<>ss$!OBxvc|I$zWaZ7Q9LLJv=w?f| zI&^DExAt`FO}FWEyFj-Oba$kCW4iaE`*^yqqWfmL$I$%@-QUx_kREz^)SyRadPLD< z2|c#c;}$)hu!;+-jA51itn!^zi?gaFt2SX(e^w1;)o50o#Hx!}bv3JQVbwjXn$D`P zSk0Q%2C>=!R?A^^9jp7YdJwCJu=)U2U%~2^Sp6eCE$Qh?&kpqLN6%sOoIuZo^juBP zt@J!a&&Txq%^D?HqZw-qXN@JSag{Z)ShE3Z4q?qBteMK1*{o&8S~Xd#FKZ>Rc4gLH z$=aV-$BT73vCa_I8OJ&^Sm!Y7+@%-ku8#HEv$!u_y4ZhO51ij1ByE?sl z(t9Gkm(Y73y)V%_o!;;0{f9nQ^r=c8ANq8o&uIEAq|a{pT%=D1eLk~caW-^j!}@I4 zjtzUU;dnM&#)dI$n8k)Fee2S<34PnpHG{+jjpp%9vi!`aW^&|&&KE3_%WN5WRv=A63Hg(*yKE$ykgS|Y}%Mj z=d$S@Hhs#bzuC-{%{sB!0yewDW)IoyC7ZWr^T}*}lFh%eg)>{UXN#$9agZ%C=_lw{ zmwr+7TSC8^^!vk>4cT%ETV7zxG`2Elt9ooTldX2MRU%v0Wb5f{eU@z;*`^)aOk$h; zY?Dp@a`bOX|KapsPXA-{&tzL0ww=wkr`Yxd18f=4mH~4ZaDoA!*sdPi^|C9l`?K>jcHYU(XW2QCozvL)JG&HPmon^P$1c6uWh1*BXO~;-Qoycu>>A9j!`O8h zyB=fLY<45N8QCqE-6Gj-0=w;Gw?pif#BRCl_M0JOh$TZD7*d%b?HCflki`r+!H_J5 z{AH*+L)$Vmf}sN#I+dZ@82Xr@FB$rYp??{sW0-+qwHVfrVSWq?VpunZ^>hFGf#c^n6CIV)S(mD#bxvIcO0FUErW34tmDH798xy!Cg4G z7YDE4;Ef#ofPzFh1&7w;&{iDUkwd$4=mHMi%%O)l^a_Wj za%dKZzTnVL99qC(E*w^$!&-3IA`UylVJ|q`oWpH6+?B&UIXr;F7jk$KN01|GaYQgj zjNyoF9C4E)^&HuiBS&%M3XY89$S)k_#8C}7Y6eGL=BTe6ZO73~IeHgIU*hP;99_UM zRXC;%$Moiy2^_PFV`4exF2}s$7?oqob8HokZOXA-Id%ibp5oXfj?L!S9~@VTlIMKvO)i`M^CmrUbG)^wh$&)$x z6eoY;l!~0vms2)y$^%X<&Z*ToHJDTTaq3P^y~C*moYsKThH%<)PCLPA1)N@u(<3;2 zFQ=z-dOl}#;*9B>afvg2ab_@QPUXzqocVyW^qke1v&M7QKb#fE*|wbBj=N#dj1kTCioZp;Vo^!o8w+rV^ zoS($`AGpAd3;elYBNxPR!CNjQ7dmrcGcN4Mg|oOYh6|Ip@EaGE<{~2(`E$_#E?UGz z8@cE@7ro-*vRv%L#htl$F&D>h@m(%9aft($_;blZF1f=c-?`L=OFMJvcrHE2rMX;Y z!DRtlHj&FVa@i3sd&cD@xV#CM$8h;Wt}t+gKUehSiWsg)*sL&DXxFQ4QAZXoExIJVHr1^;)ciE zXv>WixiNqnM|0y^Zam42x!m}Xn+)94gqx;t(^+oH;pSr8?7__qxw$(x&*J8t+#Ju% zDz~_BOCxRx;+CG=GLl;W4Y<1>cdy~@ zM~rb~Oiji#WlRUg^kK|M#>`;Ma>ndn%rVAXWy~kW{N)}e?g`0i5Wbxm?uv2q%}`E^JFWY?7@@KJUN>uPw?a$p0eYq8a&m4r^fTt z1)fUe=~6shji+1ibRbX9;pvw=W5qKqc_xZyrtr)?o_Wu+c05~)XNU9b7M@Mw*)*Qb z=DFfLSC!{l@?3kK3+K57JeR~+GPWFJ{TSPgv3(djh_MS8dx)_ajD5n`*F0~*^PPGA zG|#`|`9fZ3&I^IO(2W=7@-%~AIg{!$ zX&93xGHD}|&N1l*lQNm~j!F5vQIa<%@y0UVc*tZwCPy-P7?bxi`4p4C^JXpH?8BSe zcr%VSU-4E+-m1u3^Lgt8Z$0O&_q_FkxBl?9a2~0i8)I8pE;JpsKH=FmKF-^y`dQ4l$v;vlBDNGc$&nZ=~zBJ$fvjY^b4QGLFt;gl`!RPNbMG+s17FziMI*k5_`#bW!uVkvKkVm+IDWXx53l&)7eChIM<0HS;>U6PIFlb2^Wz?V zJi?D>`7w?kZ}8(ie$3{l68uz_pX&2d3x0~`r!oArpPwG`b7g++%FkQ*`6NF-=NET= z8OJX-m}ka3FXruHUM#=r__aU3Zs*r{etp7kCHSouzg^&W@Vghk59Ie%{GP!dw*1kE zKZ5w92Y(FZkL&#Lg+HzNvlV}i=Fb)Ud6_@I@RuupjpnbF{B?m!aVj=c0;!Cra-Js8 zG?1nfG^xyQ%=~EPFJ^u|3r4VD9Sh!4ZAG;=)iqR)P|amwR~GJN;Ya>%#@`qCN6$Y! z`DX|JB=S!I|F+@Z_58b^e`EPKnSZlnv2wClh%A;M&H72Rjk36pEIwQo-zAHGkmk

Pn}gEkinO^Y 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%0DP(j|leh(e+x> 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%0A(YrhYI|A|V+mt3o^AfXJ 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 z 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≻@aWTearn*KF^8!ZPnT(JaLg_)DbGH5sLbER)ydyn2-12&{{46t zU`t}#_eqC8zK|&(%w54wm8y4ML`=FRL;2q((@rr;+L1+eh)&2Fu#pGke2qqiC%pag zkz5n&kHj_;`GrhI172bS<6$LGb){0ZJ27OBo=_;aBI(x?GU3hF|8y!=Y8@?Aj}=S` zu)(#^{c0Dof<1Efd->O-!^eBC+o>G!<;IskgbHI2)%FOlGPQI++;*qZ+4LY;%{HD) z&93CXuzt42A?w8jflPSU^6~b&_Ua?QJo}(G_sLn>hZsq+FQ(jlC==Tm^_FOTeDs#^B2Ry8 z`O;GNmCQ$Db|O!uWIp%v(&>P=nQ?K}>o*r}1BqhBvRfm0b#EAq#a?Qtee?#j zJ-vuE*&w+(abIkmMos?xRPm0i)-;7t4iMY&Q2BB#Ed$O|?G^p{e`Ug{uH~c!VVaf> z)!lhdd-uI}75m@Jq_Twa*h)Q;jCbf?!N@d)?oY^RCko-n*Y|}97PR_VDd`6>e2xTB zR{t%E%T_a?bQ!DrD0l#w!a6QlM(?wd@$d-LjT`viJdkZ57P ze};TLBIBFs_`76A3#}G~tnqYe&Mv-%^|xCaVy2Ontu>I&YHL9$1ZoyE*EK(AA>*Fw zlE)y&SL9p5MQ%5v`{8j5ebj$9EwJg2w0(!qrsh`i&1^upPq-IWoS#WLcYqckzCsw` zs27BPQSgQsip(4I@%6_eUxZn;Z3TX!^f4|;$RmHp|>7^P)ds(touAB4M$P4;$=k}W|Te`{Iz`**@#S7K-=Xf2( zPp=?zSPYk-t)bY;);@;Q9_@vkX}xM$yW)L5C*;5>et|clUQ=IC>6*>nTU_}jL+)I) z`O;<9W(EeE>MvZ}e+W$p3|RG%n0_Q{MCyKn=cFC>k@-OR)Md5?J9=5mS6UtV{r8$f zXKPBmoYLV@#60txc12%Ke;6au{$dRI;q$!qvtqjOZ=~X~*ss zhtxjio|-Y|Va&teC3S8;NZSO`tU+4!H_}$Vx_a~KOR`oWohDT~BdzyICN6t>W`>OP z8uvnA+&GbhzsHbX@9&?uyF&>~Bd=h`KpXiw`|^em{y7=THC8&Crt?73XiTptJ)${? z%y@tP{d;l1ry-zUT&2|ls%=qrPH}41_UJTaGn?S+6^py1iNQ49{+E7N=vgrH?A@<3 zAjY#EziYbsmKeP!y8oF`4A|^BQhNXmljKobfXU?IpDq67(Oi78CAs*A?@6w5>{(&< z_X)EK)B2Y)|TeNdRpS&voo-;+dsg!JEiR9O- zBi34ZZ*db(3aScNQ5doLYw%>a2GQ#SIAzPN_Li0vTWf18Dr#%DR$B5a0TQd`;Z@Fy zT7Tpfz1dM{XD!nUfz=B!6(|#7*Ey z(JtyKtb0I!dvNgfSOoJyVq15LP5EPgpMeE4OjU+w9tLKg84@6PgL=~I4SVF&2RZ`4 z;s}E!!Q!DwsAeEluOTNm6zQ$HFA}E;dQQxQ_MU-RJvD#NAi4%=9B{;Ykx-T}ORtVx zVeYkQtFp$)a)*)J%)uA>v>!b|?(hnECcbd@0eSsS+hshe^cKE}6Td0KHv+-m`@ne| zvjXi$UJZM0t(BL(8(%B5Bl2753jEd_%Km%JSO(YX#rRt$G91f>?swJGg%|7#g``nB z<^|Q|`)Qr6!D?Y;z7k4%@j^}gS&fRvz9(kyiCkoxAQ-~Jp^rh{A-lLWn|Uq!aYa67S z+G&;oadFFQU)<2__rky`?tJ;C*!#D=}Fzxs0Vj)>4) zWefsglaV#oU9(NB{F`_@XdFiGM&;Uo5!℞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

05Uk{g6tZ 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 aqi02WVMbwAbk4>v1M|0m`7ii||K9^nFNt#i literal 0 HcmV?d00001 diff --git a/app/src/main/res/font/gmarket_sans_light.otf b/app/src/main/res/font/gmarket_sans_light.otf new file mode 100644 index 0000000000000000000000000000000000000000..c588d3eec568fef8ec94d58ee29dab3254880160 GIT binary patch literal 842968 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 z zaZht5RyC7ta>Nl|xpA{4H@>O+H&A+>0=r|IPx9TZ*TTORhv#kSiByxpEQYO8+jYhY!3KNz2$NYBEskDek9!wW#kq4fN|Bl0?87U z3OrpeOGRj*dXMhgP_X6@=RH|VXd};V_~7uN&qNnlGgb8y!$?X+uGqTvlLiu*YH?LF zoQ#r5K^E|P*w&K50snhk&vnrRKAY1Iu@R#+2Dqv<+a0!<_sw20H`jf}iu9lwXvoV~ zH*Lw=wtjmW`2$}e?0Vk9<7{L1Pd*Cv6lq?Xr7y4M&1u&+_ z!lKg*uY)}Plajs%X~V|SPTL5$H1-#sw#o7Zj_sxV&}ADJct$Kc@2-g zT<3^P#a8qPZot>$hXI{gnAVw9(>k*YreT9G%1k0hk&)S!woV;~WLa_alx(lYuAL2f zENJZ9*Fs_-m7SGos=*^+by15pNLj;Xo}(So07@(uwZKJrFuTeV@G{I7gO}QnDK3#( z_y?0Gi8_|Yc89xVQsn7i7zaTLsdg8Nkl&L+ub7j?Dci}I9JrR2jRQqD$JY1N==oLf zsKOHmsq?_4lLW2b5_dNCOFTEC{Sg^Y*skA@BN`fR*z1(`%%LQx% z)j_?6<vZw6dEvHWU_mfgi&H zFV#xYDwl8{)4PyEWftT}#ss}WaNQ-7nWJp)N%VFP_gE=AvmTYWEVaI7Ko z{&a$(ZhJAUn?Y8@-ESp-G0h(qHV?eX&Ik6O2@F@qbZHGh7!p!XZ*4%)=ev zzJ1x6`gtxhkEZ@{-DRt#UC-p|APVwQ9@TY;XNdBs?C?y5pq2Ip1g)%mHSMR3aHrOY zHIaQGX$>XnBh2xWYK#`HZWYz7X^dQXJPd1Z$+xM8NxC`)=?Z4~njGnNNQP>}H$3TU z_NCcBAIA0j%zJF8_|1mvD{sYt&5kDND)uOouq4IhE{>>@xbZQhLfoW$zt`xizk?nr z4q8IQt7rYcJ4j{lOx=qSlTa>TL4&fzLC)v1`gm;EtJy|HuGX?7@o+orq38x3&m-n* z%|L7JIBls?l6m|`zRHAGc9FlUoVTcwVW=d%?v*P7)K6`IOYbNy7RY1Y1FPPq z?Nzb2=iV_YgS|QRZBi`EgarpQD6I`12L(w+eI_17XI7PWXa!^W5crePMru%i^+dDB z%LXpd00c<%hi5Lrb8Qkdg8xFtNb0U+O+0mH?d|pzcP^Q=Xjah|;Ay(Iwy|R7l9`KV ziP7v6@lI`0lIXZJpX{6R9*@5NR8qX~{? z@Tku$oegNbU+^8%S9p9}aY$qv^a+;fNUe_4Qk2u#m4uX4)-~aYZDCMK>g#?KQ3R?KNPGPw{->eSh7jQ%`}B(?iU> zpW6Tz7%DHTu_cdEw+XnyiXDkS+qpW(9)vBwLZqR5>CLJ%m^&i%*YY{yRrPCnRpm*` za7Kf;S!dP~N7uoM9!dRE6y6x*VKh**kdL990i`*tq$)&6R0B_-Wj>?4Ku@3LW09IE z$dhN8$R^ANxbcqj#vm`9<@?p!?M_)#p%!R3v2m1==-!sSWuEo&a5+kg(jEUDFx z-qXH$JjiI_`SN@3^JV#=d_^`P1yRk`OXl^-@^lQAMSXeE`>qMsahM}BOM04^jxy*; za~@O?eiI8XnJwrgvrLEWW?<_m`+OO!muA6VMe*C^ZDLe$scnh;D3#=hxJe8&4TNe; z0#YOHMQoOYYP?RP8evm4PHa(2Gz$%I85&AuBx@)Y&xB;l<6ee#9z?8(_e1G)-b6fxR*hdWalx%=lY0&xd*fnQM}l zayMk+&JeE;t}WQSf7dfRo_uQiUNJ_dLr4zQiO|Al@)#!$&S^|UyJ1h#Ndbb%lc5Sv z0(gu41(&AqM36dGw{NTJN7yH7*KAl{VI};^V2|p6?dwz`H=0W1M#TAa3ublF@5oP% zmR*hSoUM!Q1Ry8|+U2nM%-kTG6lLHi_&hhsE}nVJ9D_|fp#i&p!m^yZr}BvA?3uOu zR_F87SfGc<65Jm zsQ}g~Ak%;Xb29@|g3Vr0+_F3yK4pz<=5Zr=X-6!VhUYxK;7NZsD2T2F@gWdYn`B1e zIJox&u~FP6`fn;a4fPq!9S8lA_machV2h0(z*H}n7+#n_ku#CDgE66X(OGS`bSHG> z)0}FX3ntQi<+D6yIO`{elgDHpwureWsipvog)Lz20qUBfF3cTkZZi<^ewTThQw~OA z@F5XnLX|f?`OI7avjT@sxl*N*@8n3>9li%jWcqt%m-Y93xeeRaCCYp#T;0aPO*c=A z((bC|1cTdzUD8%%KY8@R;4K zKc3nXbHUTaV;iG#?rNSS3cIs%OSdGtUb#`=O86OerzgaB8tIT{Aszf9VR`!$Q@X-^ zK2~OtR~)^}I`>IHh3chV$!?QXpv6qhE<1M5;5EweK-sU}EyDrq1=w`5dH4_1pLwOz zBk<%ChwAXy^h(dYd9oRpb9i(FQ}@$FG$o5lx!0$Zz;kvPQ2X{Pl`Y1*=@IizoSf+0 z^Ze&z$+lN!P8n|#C?az`^K^#RGTvFXo2;!7gAxWds_&d?vPacom&@7xO+^lW7Vn$R%LK* zu!*A|7@T3Y7PrzXOF#J#+qTKjzi$})lW`(mgNgVD2}2zQc~=$aq#*iWhZ0r47!ufyzOGj}wxMl|13Pk_d; ziizi)Q4(&c*Ykvytf@++1e=J2r4fAYt+gU=@-(#0IdDw&m05JoQQJ#TIeTft#Y#_m zJanRtp6ldxeXyay+!ju?J>$u=4mF@2`w|CCz>Mmn2kYBGdmj0m#{4go{cmC^5_(%Kz5EvZZpIT6=u7C>a7oCXVkRSg~l0otQzgHki z5B-uKL){tXV(w0=zTAO>_7HQ|fS;s{-E7a==N~#i@^ z01RQja<&KE!U6g$4j0IWY~~~q7hUWom1>A7JpI48QM*TCj0=mHeAf+mbr4Tp%ET7U zfC3U#`hJ?nfjy2Q@c1-9^oiawLepE;!Ql%Xzlq16MtFsQCb{RMu8l_?d6`H_$1EIQ z^c8#V;M;kR=WX4v4VT7_sh)nKId^}5nc$2;h{2L%>+)TgBTLAM3yJ$7G zwQA)Svs2H6B zjD4sppq^$RTPNr$S)DHg3#NE zhvB8ds`?RK^#@ROr|gC9m;%|=?Ujb9nYXJ{Y$>|M!&MDz7(5z}d)34fx>`L|KP?C= z4E&wcyA%9+Vl0YEgfz>>Fx8Q#>?tnPzrP?AXL@n&$oOfU!x&Jo@R*xGNFwWis5PR1 zSXiPPF%Pk@;D6Wy@ITGMg1^MVQn;Erz9BXMA(^`_xIvO`VjK6a&0l?pCvRk377m%} zqz&M65<{^8AeK2C=(+EmEqM4-49O=boNu?fYZZ9<%Y*LWw5zjbYzzo&A|FH>nz5lU z?XXqx{=`belmo+SQ*~o!`Y}|#qri=%fAE+y^vj$G=A_=bLLF6GXaKjei4U*D;)I)z zX|09~*ePUy|8ZGy7g<_ zUHgxg`avuxZ007&&XQ@B^SH(k1PV{F>!94kszn2D!KzJ%LNi<&zF*RY@6@pqRAXAf z2gS?CVH9!@2V`9y`3tVfw=;Q%+KkT|ov=NMd5w%QWA7)ELI+Q1%FGC!qL@nJ5$6~k zW9`A1WrU-1yYnz;u7W0CDYhF{$|l+3CU{+a49D`cdnYfQw89}LEiud_%F52ufPR2S zjiR|=!lq@_1dBL!HtO`4;d0|)B2HH+Q&%YraJt|k&`MZ;MoeRceQDm+!h**yEbnWH z=>&PNRB0sLL?5U2_UDmX*(!M)x7y+l;dp?01Gih>|G$Z)kLUg2xXj+Mfk&QWZm^nn z_W4AK-VC2@1&hM7BMI}cz%#N}~^m&*eUvYD(Ubu@V}$2;-&)Y0O5bhP}2 zI(n??D!S=)iYj1~oX(oMN69^xJN$XnL+S$RMt3jO+h@~3+a~ky>u}+|Uhg&N1=SY! zZ5oXYDhnG6dUQPXD3#rjhi_uyg3MY*>G5s!NhMe+#A0dkHBl(75U$y=PHQvBkrfob(WANFIcWZIUfKB zguH=(G=u1Is4EozHQ>RM~5cG)QUnUO`E z_iH&<7L+VPE^HLKipY7Ji7lF1oh0|*s)k>9JiO>xMG0})s3v|Z1lhoEczLSF?YRsx zc@@oK5xj4}y!;`Lf^Jw>c(6Jix(=dHeh$x znY{rCiY~y>(weEkoWV>zDVhPQ-;~=PVXy`T{sQ7<_>oPh4CaW?)5-)c-2H<#s((R;Kqr_5@_h7^n{Dj!;MqPns8vW-vc^& z{L-@t{Rt(^#zSHo&AJh)JuFOV&fzM6c{+&ZT+O0AObrm{sS<}tU%o1h`RzsO_Q1S>&-R>?oKP@^|saU z4+!(yqFp5!kMm|cjxw&w<9pLZao1+Z5-LO-^A7NPht~>S!}&1Zi?B1XoGny`xGj?v z;?4F&0ri|mp1qQ|XI#_## zo)x3jqYuC$=R8nLMR>^R%&G7}d2dolFDeS3KfYYYYyVJwo@3xl}!2 zzEAg2SZQ?^12p(M7vS%mUhsDl!q^9_iFjYmhK1!KRyc(GMkGKQfNBmrEua9nSKcM> zwE@fXE_pr*9wA2lMJ|veo-nw2@_8mFlW4!KH~lbs$pTLVg$-2e$ej^SewhUOaJ&G8 z6UcSE_?<^$A5!~_Ux2>p!c+RPM!?*3bx($+A-O6_RdoSo{f&}bW2FEfmQwTy?E5Hq z{KDI``=sCzie@sh2>6SRsd?5h^$s0V^Q>cPo;BAZ@1>jIOQ7q-FH{4mU~PbtsUA)y z0$QKeKqpC5x z2fQD(n0b|)d{GnV$Wi~ zQ{))2p@4_ujd%kLx@f4AcnVxJt-~$eJSrKoj0z*8{hfiez{z8ng|q zA<0)9@00$9bGQOOe26lEUG3o~=i|xha5*WTK9Y=2e@Vh0!^~QZA>ix(ml5yjTY2Gr z3=^U=+|-4t$~0Aj$DXLTVP>sbxB`UA%B&_Mt_vNbzWG(i2(WMJjXMRJ3OwEvz*8$4 z7C8;3U8#7KLI=EJ!GV9&Jb15Z9=r*m&X~NUBUe4x$x&vyi9|2D{2k+y!~uW!B1dUSm_|%f6T|^abAA^_Scp zo&;7jf)b|^3bm>0NBRy1zcV!U9brC`@)BL~#6r&Nm5Ip{E@6qTVm5b#Xvl51`2;tT z%mpk_(g`x04X;D|AJ9$aBg3zBiWvVgdCYr0iK!OcaXTx5_nJ#$0dbC9;_0}2%BJ`q zm}eFc^Nddp*SLNo_%5Dheq-dwEDylZ*lMgfYyrB%00-^uFs-)C`^zccfX?dZ-U~b& zYsu;|Ztq_5Gjbwqi_q<>yp@UOX&V^~_g4LLANNHLc#ni1ZUA@5#XSJKs4u=i6?F?9 zTD%VKVUb%L5uagt`cn>hge!4yKf-cwZ-;|>o(kbW4^%u2)I`@o?clz;*TKEKo5}jJ zMvkbVY%cRkj_%$6H!qSaLzQJI{d6j($ zQzVy&Ul-T~JYH%7#fGbQ@u#^JdiT580QD#|-|o5v0Pxu$B8;-ox1=_?oySMAq3Q+T zN-{AOlEyRH3y|BUIR3BqLT+I?L!BjGb(z`JS*v+8w7x@mS~`QXd(oeX&2(M0@U=lA zyT4l`iNxleP1PTW7jZaUrUJCj zJvJ&r1W4R-XhOIoGz1;r{+^D&2VO}7psgfogLcf7I3RifOp+WeX@t!j+Tsn zB)7lp8|gEbc^^gE?lYJe9&@@JZ>YknPWh^Ppm-I4)$K7?ZC z(k1q&yn%pk*UH~vLIYX+8r*^B1@!KE&gpA3ZL@o&^?;$DSnR=*`uk zC}lZ>C!sRkb(Yxr_A&RgZ%V7B3pKZt`M^<#`4iS5brQiG2Xb~VU4nTMULhOmywq=K z0=oX7g5kZWA4J1Qhg(fa9epBIJnO4Z$1H3s+6eKXyu-*0{kX z8aG%$3cv`P@Kor)Pm5D@*v+>NyZQRCBQ#kyro}ihMOO*FI-g}tf8H2SAjlD08u6&^ z8r0^SXkeLY>iaTKg}-Q2;pq}oVW>28i$1Gnl+T;jsKr9mM?|2@w_t$eqdo(agY%DW z*EspEmR_&RkC@Fm@-SxZdTJ}TeZhV&{0kPFJT^twx!wlw=Z>o&2=)*oX7S}2Ak{LGv6%{RWh!g&)ab(>&*6j z&mT)aHud=%h$87mW6{7a%bRC3>#~0Hz^s9rXFT~_`g6}bd2(~+=96dFU(ER7?D9n? zvraDBGjmG%l-p(wB#I_ zGBt=I z!Cxh6AAx-lH?80FrOSW?)^jqV3FjA(RzPwp7xfsT;yT6C?}t0m<3Jc5*AYb;u=0Qy z-bD~YBtktCxa~{aIG&&jn$H&?veM{gR+4peI|}x#P>wjzROZWW03iMkh2ib|e(Gl2 z#KZ!^3Zi0ffn5PR;{pN;mPw7?(HAg{6#RwmWNpx_eO-7&O?HNGf~$bnwR(~}R+jvX z{~JuKJWLgLAy0e-y;Jl$``Nx!Mu=3fFTSH?N#7ohkvDP&9-I4vnPMW3nCfk4I*c=J zsqOkpT*W^;xfA%>#}$twPg>9F%MtG1anJtUJ`vQcxxWK_SEd!+IfMRe08cpKn~orN z+oAZxXaX6S3k_(l?Fe1ato}8q*fy?j#8v#m)1G84it!`K))lfO7`mJ?U!c|T`6Aob8tnUjCynP2)R7dyztHLf^6h*z%>tb)%P_ZkBqNu1Sc12hOX^N-_2sSL(1!*cpuwy|H zU2BXGbKXNPE_{@R zv8rV5<)2zprgSpU&_{9x@4Q?veJ9npNlA-k{o~%0L{j-vkSTBEIZ7vaPD4vUeQmnW zhpSRRU(}H*k$&h+-mY~e>3c!mQ#$-9u<&$em*nv`bV zpWGv8NiH*zZDEn?|eP>5k2Egi2mDKEfmyB z?*#haUYo}jx_Z8QVl?EyRh!!eNPd*Ls{FiB9!jV}zbl6cwaosAf+%S;RYavWa?fqW$dK3@s6 zBg|xhWh+=cnQI{vg;NS=U9YrOkROp+Axl*U2y7{Z)L31o@gVnu zElLLpI5Z6v=*rVxl1#$(r6t^*xck&WQswSKX?^(|xf5QJs_1zknT~eJytZ1EjaHhF zVO$L^+^+@~N>-%XeJfIQnGYo}uSp5aeI+ee!k zjjZc%dh9HfpqMv8-dYFbzLIST&%kPUs0I8*+ITsQW_8} zKTz5T<1M;%s~N&9or1MxPRpOI`((%N{p7UVn6rFbrKy)C{_^oeRb253NyBt54cZr^ z;S*IFK2@dRQ<8>bsx&O5S*kWzee3Rg1n*KK%wHMwn%g6v|3gYAkwB$i1oA58A&rxH zNaJK4(kNA}%ezoXG;ryg?oI(+xw6wv<@*rXiQIIYLZm9?gt^?0CYe%?i-!cc3hP1e zMnxau%n_NBoT69u8A#`I(y%|eQh2OZIIt&eRk8EMjr%_Q%+cFN436j{ITi{LQq_v| zcGr3Gf+$hmBsqRXt&qDs|5wwS)b?zFJ!Iz8gcbcUOIWve{|QGnpEEJpxbOdbU3z|Q zuJfb4g3egmh17}UVKal{qaM!?wr|+Hb`2+|P--@e8}8;B z)bRVrKMCA$>z?p`;_a>olIC=ZKo3=Xv>g zBush_HCQa4em?pldpv&g^;(a%@)*rN6r)*-LNt4;sSqipx-H)gcx3Nu zkKq-z%6-_CV7aIk+e%fe$m^4OGEJtQUzg9x*J%w- zN!I%XmLgTLqs2(%J}I2s=e3&jcuFp@P}I9U-XSmw*vXQ6a~n@>vhnnxn<&jA$%(z` zv??-B2H&`wrK>?)&!$8Ej$NfxT_vT1gXQlvGb7`oq9#h!z7jP01xXV+$vt6PNoSJ+WQM z3rOy%3&|u^BiKpNWY5Z#+Veb03~y*j+CrxGJkRM%fmg1WBrpsp7MbT&Kv zh&;Hfn%pT&f&xKUeu(jsM)n}fe1KjFH_$cAiO6QZ-$kK86r~hI{w!qG8|V?jY?zJ5 z&Z9>!@04w1o68{sbwe0&-O^6AL1-qK#|!dd(=rl-iYz$TIJAWMYmBR8h-^9YlNali zod!9be55G$4rQ1}$PGep# zeM>2%S@5R61mh9%DmkI=Pbq16=zLj9T2oVAU3~Ks4w$ZzJHxz9?&eW6Jlkp@ZAC}X{f{W|#j0CGWAmn}g>rXe4pl9rs+Q#B zb)H=_l_TyZa_dSa`@q|(N*cPWROKt)i;mR>>XWTg1-Z3I-pUjpd|tjLpQp8$%(jX| zTa?U*s)!n+AtW&@>%E?LNW+@SQn6qvP!{l{ARa4<(|4!tr(l{nzO($NM>vdaIb>vy zlfvz+Gt7^&q{*~m$QVaEMnl>$dh$@6x3(&Kz5TbR-8aZy)K&v(s|PLO`-?XOO1PXMJaB2ZD^>I+x1S1LRb^72l+Fy6jhYz~r%s+U z#iBvVV z*(_5uxiyq3S0H<>fpY!@5Gl~J+FZJx*On|3$bCn5UMOw!o5^iwX#nMt4I}TP*93ki ziS`%76D$vxM-hd9LYp()kWLbrz{wX|U(WgZUYLDjO%}lubn|m}5*t9qUiH{*S(-;& zCR#PdXU=558M|I;KA%?(d5j}+|pijCcd#XHjbiY{)>ZLOD`71M*UwM zleTo5=@O&G$5qp7~s&LI2q;RvPSV1GXyj!pYMy5P7yX-n)z-QhrwLKmk| z`nl7`I=fE@9Ma7(JZoG*v~I}mD^Wi=$*0WZD%bovcI@OwPTi^jG#u_5o$nbdU0ZC_j;P`l!iWK1vwmz$ib7*5mBl=9zO=eQBl{VLliMo&9jm2Ojo*tW zHf`tI=bSAGw0(y4+wAEyHe&AdDChoBVSM|{7?(@i=eCpMFVc{wWfwZL6!Lnxe*Eb7 z-ya{?v7_(6X3cz$Ue_Iys?%Yws(zI5z>hf?jI;E_VdM7)k3pxW62}E~uH!RR@U>F@ zYN<1lP_IleG!=wVzOg5vL{7LV^fJSu8+j?& zL<#jv-B=IPbUL3^h0%t*r^`{l1gMXy3gi7)zzfwiH*{N}y7Ql`2nk>^Z#6)a5J;W&CD^n7|E%o@bJzGNjF3|v$kl5q{|k_%)C|?$@+^4 zeY?zV;nbo_Ms8o{{&`Q#%qMbnc_*%BeDC!A)!9=|IG;$^%+1W>C-#?g^Plza|4zkM zrKO>&-M>ZJ%QXFeI^A!&2)tvPdHX%!wSDdB?#K7Fx84fW*U_mLf;YbozZ`J7h{sKd z$J*30cCBt-pvQ*hPX0mjW`;U@P8uy$`CQn2Wzs#T z1Crek;ljFo2S0V}H9!oD=qpLRh4Ie)^TVa88-(p!PZnHv+O<77X|wZ*xT4TN$0>8- z6BBesN2Re;@fsbvrNRu>gbc7wS{(|*J96$DJK-ABM;uR&r20h9I*gnp6~Pr#&yux;yS^u%JRdWKLWRjDAzMxu$c z5Q!8-Hjs*PfRl5)>7f_NS+A_o_dc6llSR6dz5c8h`$F;2p`0Fq*grD)bDy(+u!=&O zk}5g6kh8>Pfg(FU6n9UNYIq5O1G7Axx(}Eo=~f8=QnePs-WZ+aM7D)W2gy0TIU%T? zJB}Q=xPya27eoF0JVTj{Gr2e(ma6Vi+bV6W=oE4e>ZZg?b_Acd6WJWO3I`0YsDR-d z$^J*O*9gXa$^&K+av6MOLdC(CSDrI zX**fk19@EuJIxy<4ui4^6vk%Rn;*=c8lB|#P zv5%4`SqIW>h_K=Snsi2Pp}ETMk|u#y3TNwy{j_dF?&Zn-<@eBD%uBX482$8Yu~r$# zdWkX_;Av#o2-#LtM?|uEBLuWLGn*JzYfG}(u)p~YLHoAGP9=!C~wGUUh&;(&s!?~ zCz_6Ax%_*B}OPEmQjO7DNnHtuMDwN zWw3Bj@A>#!p>#OW$q?r4#WC*&&D8lU>j9tSr&7Q?NO|B>r^FM_K$T}7{|^sU-g`Q) zsP{`=?LFy_&rVcj7HRidr2-MCy)2wu0^f9!O79w$x4>#I3HfvRSB3oT=O}+rnED2D z)Hi4&X?l^kauF{U)I*d~644=Qe8dmYIs6bMn^)zf0zX8DN);Ul09XHC?loN}R z3S-ynJ_vM|tnUh*(W8eyJx_=2zB=)Hr+rV((|sSFb?nuLY+*j!78dE;uONKaLC5v! z1-Ywr#amBFc4oqfn4;j3j+5uaCdTU&XEyE)=c?(vVEkOUtR8<_>dn}_qGaJA?Ay)H zwF_&x!Aw2Z`p0&38WWzHNf))Jhnr+Wt`|`1zj~nYX0DMBw=nHVGwkA%BZ}9Eh1#naiQaBDIDfoQAW zcF>rJ@!|vJw>KX&^docUrnG;0(3Dk(;Rg+Ulz(Ek#VdMue$Ytt_R8S8V%Y%lF<>4t zId#72&H1TKr_x$}D)D(JP%f!Qk@-oUn?qGVT1j@F5PO`bGMxYXD?gR~?GwV;+SiUS z?FfNI6pOc9Bq>R7@o(GqCx7x+tohUaTRO$lmY-pjB+DB744eDf8TN0VPX`_`%D(x) z<8NwCZ%X^n3vWu{?YG5q`W~;HebvJS*5;6?o^7w3cRKdHEkEYe<4y$Gr=J+5f*#cq z*hq~rhdfJo{f9)p`%2xno|R;NG9LM!w(OO(WykX^dm(X{N|k=2=MN-|)YM3*OUw8BXw? zLQmi9U!T4t0&jSw7Z3!JALB|sEh#UEP`|fg29AwrxW1#|n)OudRPplT=QCFW9}|+O zS03^oPf~-V2aZ(5#ZeWPhs=_~9G|Ly&qdvtki>gO$-X*pXmh?wE*?EhX0N~1`#lMv zGNa#<>-{6bJUB#2%@@7W-~Ye2`m$dAAL}29{5?zFFn_OWAT)t$rno2T`CXdFn?>Sn zCOxiuys(e(z2e;}2PsV~zVMBmenIJw?8s|m)H1p9o~w@6nf)F~n>^hVlt(Sl zHC5_`m?-~cX_!1-vN$XBQEJcuDAjPI1Wl9~*iGPhs+11|rJPbl{6?!bwCj>o*(7w8 zE05tVv{LGo=F_pt&P&>Dg7Wu3@;zq02J*uq=VOIjO_L~!Q*N_U(I}&Z`SJ4-<|ZnC z3mL1IuSr?wpe*5TF&X3*!%M~!*rgvy{_p8hm6n1_>&TwocOrlK@!PFu&bHjz#F@F7 zb?cG4ckj8p3m48$4G8Fw;OYEN`j(_vij*|4bOei~gn^|U$UoOZn4##oV{yezb3 zpO8aqmCk}3AQDsLasy?ya<-(bQ@mIp4?1ooyHly1tfeGspEpdh}I-*}< zN2lPhlym}wvcorRbBs`|$oj+D8{|N8w6Ym5$V4M&kOSD~Gz=6Qa)xqB1f@-5VmHbU zA1&3mC<<5i+5kib-HS&o%e8|V@m1KjwR2}kBe8?|p<(eti_MCM5+-)yG_f6db zdiVWOk`jcj>bUk3_ng}-i?Vobd|+UY@sh?<=&^Z^ZnZL$Gj+A#OkEv_sf&1;Ndp?i znYxx4XdmEQU7CIZ6|lNV1=dmlBEXWrCB6MPCBv}T%446%-%Ks!$_urBT8J3ANH``v z)U(Z0b~8D&Od`JbpX5m{v?N*!#+%H*7uzXH(?d>#FFc@nKY@N%d-l@zDoNK(PSSNl zCFv?uNxI%xR3+)6*Psv;&eAnXW$7A4EM23BrHem&En7J;CzQ zj%3_&m9Lkuof>1J>?$_w8rGx7rSM;Vxm0xST-WUlo$s+`V$#HM$ze`m<5DxDC8?&6 zwSG%#u~YGuP#ohkb1&P2=OEF)hr zo`cR+E@z)tw4!)fiDV5SsJHiM$y^jx?OeAdf8+XsLb(HRAd1Dpwt`I?*KC!CvdZ>r zwh>rXIcH1e_GQHmTwvut$+j+kzO&RTM7~AY5(cqK0TkS1H9|zCbP6(RZPme zS!Q+y`OR^!If`7!HppufGSmD>-We3G$8ORsjNJ^8uWM$GjU5*?d4{k@e$1TgbGI`l z+h^n~&rQjrs_z)L81}npvTY^V_7R#J#q|l7%Q2#pd3nXUV`MpK&Qz-N<=AHQXq@NBtiZ_<`G zbVzXh`a?<%>t@jDPx0L?4f1f#3(WuJk={m2!8B9ZExxc7zG15@O_KdZd5gL|a^`At z@}X)5=lDinxxzNKXQ0THx)%vu{O?PT9*WQ8(RktUFCkoT*a054W7w z>`2|^AXV!nl=dU!_@$@tl83mS^6b%^@9b;J#`l#}o$iE1QgtHCd9{p6fMzS})%@go z$uUvjFJngiqzF4>u4$0S#+=pnl&s0`lA?+_GRn%aOsaH7P$tp%Z+%SY^jUU6JfruP zoF)mZ4o{rhiX9D>bK0|2thJGD(pRNrJILSeEFBpl-_X<|8+HI|OKyEUF9Huzmwg$t8c;XgveL8kMM+v zQ{rBJuWZWE7i?raUyTCwk_eYy)7Z@KDG-N#O0-Ja1jJD*ttM5fy zO9jbuJfm=Z9$`4raI*;=x(6-dF; zF#FFXhh?PP?IGoEbEbtwfjg3Tct6MqhyBkjBUy?QLaz-;H_+GI@D67$>ON94~*YTsVjMH1@^?rbk>E)y5`U;^1`NfA}%M|`haUKaFzN?xO) zl!Min7W$T$-0WyY{HkYb2*O-LQX9(>#UJF@ru2@V2&Ngzevv@KhLYuFp|rbfBgz}) z#!}TSf`=qd7kH6Eg^WfUp;1ViQ?_5O7XTvrFeUx0I$`BBJi6%i2)ld*>)fk zlfc~|@4CNy;!cXRr!Y{KR$8@O+>lNx$q;4~ASwD_-P zoG;#cS$3!7U5bxP(w_C>OZTRqGQ%R5YbBG| zUL=tW<*j&XYkzX*UqW#jbb7Z^S!A5KKC*#d-)xT3J8^_*F@MwZ^aPvsTo0+6^5w42 z9VN|1q4(7>a-I3QPHeL}00a2|$TIs}JgOgPTuiy$WL4*=JdB)z74i?a)ZWSeVEYFz z;0z-^2)h%fBh}BQs~}J02!kw9qSCnsj?6#hbm~Y-+5u+@wE9|0woea9s!OKA|3O=$ zD1q8*AVz7SU~Elb>gyl{qfW`hh9-Otv&K}5rni%_wktP=G3}t+A1GspX|srg^q<=*PL3V%RY4}?T*u( zOLM24ay~VE>y#+RsK_Zk({%iy6xGsEg+b17CJ0{+gV4LsYc+cX2YE6EWfXijRSLeX zDg_^Z_452S`<=jE2S@@5AmJ(&0VEWz{XqOxdpq~Q=Dm&=ShekC=tx+%fCJ-iC+HeT zRV;Yc&_}+4DVH1w&It#OF8Ivpv!lzFA8>BQzSYVDyg6E85lSRPoVBf%;h{>eSIB7h zKd8bMgw&P67d)lBc0YN`+z?c1J`c(?@VdB5LKDH;a7HbW$ZyZ@#pZYoU&C>=22cFU zA-WWv_*ZT$)^rc^_P!GS*TXN1&YbDIy_Pd;Z`Psz>b-kE&A)#AWL!W%zxWQ$)}=&= zQ<24$G1uLGg2SmwI{Stg>=Z|Vu95G9<9Ml(cP#_88NLX9AZiYAtkH#4Fvt~*&c#~t z1FrIxHKDf3g`Djcx*NVQ)}zv6=q3A-tn(LFX$aL>oswlT#cr|zA*OmJtuarN%2hmfLeyBUWFF3QRlliK!nesqvL>fJ3X`!^ zD_KnDvBo|uN@YGWHW9d@*F>`DLwrX2UsU#T%9Oohq9L(SFnPzCcLZE;kBGVx!6E>D7Cu`-sY z94#zRu9m$yW81PF4l1VQCRdQEToxuSwf}s*R?_aITnO#gYm&z$MI}VbzY9fc3O7*_ zS$|fQLayJ?ru>1DC$iuF;%HSmMU$P~sYE>BZ(mo^-4ICotUZuXAUGk{qW&E537&f)|e<%)|-Y9 zk0Glh$oBk3+LJaFCE~ZTwL{6z_-@lvvVX`U_35OdM0|vXIhY2BEc*+6ca}ZYcuFHT zQ(Dq{F5vH(Rra1l0(JY<_aww!;DE$)ozs|YA{xxGe^Ig)JJKvalq-wMHG}b*mb{iO zQj6yl!X7E$QL2*4X*C^#r5ZB3ZlEwVJXd?B$2kn65o?o^D z{w&f?WZcfzH>aTGo6#y(qih4LP%GHv(z?_o#N@)EMuk%~@?GH#;@(UdBi=C8+*w-l zvZ={V<&!^%CUB2Xw-#G#3ZUKo^&QXHQXzYvJKy|2mdmMo4=GM&eD`;koQTWkIW(z0 z^QE0AjCvZZzP%uN8ZPm-mkp7W_2G#*gTfA6M7CP8CRDgaO+ju#Kp3U$HQv!G4@u+f z784pW+A$_0E^n%C?2a!c|Kaq(-sM?4oi7w@FWKj~W_H2U)w&&_-PhG|8cb&62xs|v zEpgi18PmuP9MvzOjZ&6=0t5Obj(g$mAz88zVOq$uO(f1Vg4Kn4@lfJAO%JkTIvMU~OKmOgD9>$V0B18pFtw znOzYL57RYLrFhbSxaFTT)z^NIAGH@x>ibGo5ki`J%W5FjZy)aMeKYd6-@e*<=1jYy z`p&G4Bn=Z*U%7HRUUHfx(9@L)T!XD=s!^hZ|GA7Jm_v!#!kbMt4WKjN(PCA9C0Yuf zSM}EwW%?_L1TRGTYrC>SFX*qIk^XAAlk2Z>Z!Tqg$o1DaRezTvL&u@u2%ZXHrZP;ie6DGW0%^W*{GE)3Gh50EGKs=&?HABjhi}wG|O#k3OABw zIg)T}E?M%2JU&51FSEvHODkI5uOD12#cQg?i;|lh(D=rV7wI7nHs8X3=no-dU<~mu{%stMs`hDOoO} zWW!=d*P(Kd(Gz0*rs<{)_MA)6Xr5`=gPr}dClqXS+_w>8S_)^yM1?o^N0^47bnty}D-WJD_ickhu`QIm62$ojT@miWLEt&kI)eees@_zOtc05!&tcVnl(#i$7V^Zcigo{yTeHSfc+WPni*94xf6&T~L=r}X zqk)`o^zjl7J-AcG-FZ!UYrEQz2bC+)hu$Rkvo)*m0}T!*Or2M(tx5S#EQyBkd5tD& z4b|t0YTV*JSgZm)|7i_EfvOV<^t7ihpr5x?M3k3pQkQMzOJUC~6%6h9q`%CD{6J{W zKO=OK1IaCf`u!>IHgUso;!^e9iLSH*aS63j=}K=>s71@R)L_4D!HSb`F#Iq_TZYp% z^&$0MolE{dKFROEm0mCW1W|gsyBMFW=mx8`b7PWXrpG?ME*#fRYaq^xNt!ZaiacC6 zA)n&TA5Uh~Cq(84{I8UhYbQ}$nQ2~}(B~r?;AXfj|Hc0opu$mM95LlGNin`JqEMbc zXoKilwvA?~Y)rbT7*xL>wLxSu+D4;68U$5q%sgMlqPpML1~sM<_o+nQ%b3&{!csri z_kQfd1)~EAMnEsaY56byKi-*o?xNm{fGG};hNzUKg`7s}RTsum+GL0FpJ_=ENcx(i zqGb7yU$R^L12mKo8A}Z3)_FS~Ushxrha%}CiJj$Jz(-zi3fuC}0Qn~mR2MI_NEs7{(fHYsHCgnKs|8EdP6;KKxhG#q8CFf- z6bmtu5H9$wj9$CeaqY&nN7yVOCdQFwglNFe34~Dkm5Ibdp){AZe+5NXdpL))`cRRu#OM8>Faoh7vI*$J^+PzTfDwTQyI=*0AHjxj?0XiyaA&cF< z_9v{x_3Ql?F0|QC!|U3{znjk3-*yBMG1nBjZT;Yb3tP!qNxTp_LMPW_L-@nxf$Y{( z!}R87hUuDFB--F z+rd$C$ZjY%AcVEFH=Cknn|{fpUK-4DB;mBcHowQF{?=NgyK+z{|9p~>)B77u~J&KRk8{d z+zD>Il5xId5BIWh;P-JKf?MxPIxF(DBOh79Tc?RX%UO-+KLT;$O*RI0 zK3Di}g@ypT3uM6mubZh)4rTw&`cH5j?E`tra&Ag`ZN)WFEdBxR`pgMn14qG0z>EL& z+E$LSmaq8(a49prX8r#kh`=Ov{a-r|B&Y*5pG9)@-(EbW_bJn@Tf34oVhANLr65OQ z@-*(#QhFz12yk&45h&H@DMSanL=o^4MbUGLfGg|wa*BXH#KPk&s4|MP-N@> z)Yq15`~`~1(sSoS7AJQSx6CS|5$L?0XbXr&fatp>2XGpJJzo-yz(GzUaAnXJ9s^0uQsg^@L6T=3eTlIzCX!yw2FP8`R^N(GX)uLi4 zyJTjkXQz?x&ux`N_gl@($%!$sv65zpaC*a$ox2Vgt(hy`a_gAfNM7#go2&9-LGm)4 zM7+jVqOpJo0*(m8E#oW7HdjOaBuhzfrkv~FsS%luRk*NM6REgyx>gydBuEy55Xe3w zeWW432&>cqTq)sW)q|J@UnK_MBc+U6#;Y0U^W0=3IYGckl^}q8*^W~lC}P&74ibCk zdJg=NKtH7ZMbg$gPChR3-ccthg}E&mb|m6Kq)zGv5$EY0ee1{3lr_ydQ7|?%rkgUz z2*di)je7;f7tp_QHre(1$(`h-&Ks40F~-(f7B!#l)(u#s6H(=MkUiu%@@%=I+?D?I zk(-lo!KK)Fk4El7n1gIbrL0+k{5y@@E_P{*>`b1E&ST_DyO^_Sgx31L@o$sA$QF(v zoA6YPWc!;CNGS&=2-dQju@Si&hsqPYb{Q{>QNp$CD>`Om&6gj3^G)XuDN%@~^RQN} zz8ofNoaJP*ug`?_?CBlWrj7UZvuDq2|JpfJnJ4a&8!y+$mOo|`7|75cGqU9zrg376 zL*)^grrce?YYYoF9^0X{M!9n3DjJUtyuB$@`{xn4XJMYLo`&YGrs~*4(I@c01JR(U_WpSIEiu+$~8v07AO~j za+xTXk8(Fq?l#JOhjKrod>fSSi1OV~-WTPEp!^t=4@LP%l%Iz3Nhm)L<@clf$0&ai z<Gb7AOVeSd@F))vXc_Pf` z!+a&o&%*oyG%nDzfTlGx9iiz4Okn-_w6mc-2JKhSehUjXSagJi z2Q0i`(H|CrU@;sPdRUBu#UxlH!(uNi4#DCaEH1<1Ygl^2atth^VVMBS#jsos%Z;!+ z1281QwUQbY=uw^!2sbbtn6Xs2`e914TV)Gtfs+gHmv5uDiu~MVYLxf zdtvn(Dpo;72UHw|ijz@sDk`2s#cxoNzL!z)F)Ep%QYBQXj!Ml?sWmDMN2SH6l!{6p z!deS!8(2HQS_f-?SdWGEI9TVwdN-_3!1^ax{|W0ysBDhPR;b(_mAj#GUsNtc<%6hV zg(^c)B^_0^qRNk`@+WL8VN(q@I@mOZjVo;0!DcXQ!eO%*Hfv$C9X9)5a~C!bVN;5# zT2$?hs)?vN7gd*`>UvZyMAhx6x*Jswq3T&wy@IM=p_(?_0G4))Hl_l5l^*ayLWJnUz}elG0uV7~$OAHx1B?0PrGHB8W% zLst>HhR`*IZaj2TpxX?c0lI_GeF5D)=zfQDZ8)dFxdhG!;CuznzrguVI5X6AK+W2y z>4lp8P}2`JBT;iAYR*E<1*o|mHFu%rhp1(aT0W@dk6L=via@Q2sI>vLK1HqDsAWQ} zzfoI*+C5P_2(?2|dp>F}L+uRI{t&fKq4t-k{Wa>;M4i5Mun7WvG7$_0OaJ zA81em4eFsmGc*{A2FuW3I~trvgUe`e0}Z}GgCEe)9t~Tfp$8iFLBpYF7=nfq&~OSG z?m)v2(C||;jryMY9`d_6?f-jOMk_ya}4OMDyNg9)afBX#NSB zpGNbmXnq^b@1wa9EzHoO9$Iuni>_$V6DI~Ok#)XgMA&C!^&dw9=qeHMFXSRxQxV4Xrw(RWw>nL91zKm4sG{(JB?KGSO-kS{0&I zF;d7_C)L9XdQ~y(P+H_txur!1+>14*1y250^F?OW(zkR z-0HxsIo#U9trOgW;T8tBIJljG+ZS-V0=K(xyN@;Hs{gi zGTMBHw(Zc?2W>;qHV$oPqU{p2U5mE&(asF*s-aygwCjg5@XulZkzef9S(f${75YeGNIy6Iv_UI6d4&mr94ISp7Lnb=p zphE#V>_CT;=D=n zo?YSD2cCoB83504ct*o>Dm-Vvb1^*A;kgo?Mey7U&lB)e(9H_nx}lplx@|+ZgXs1% zy8VUjZs_iT?%wF`i|%@KpMdVu(0u{A??m^5=za{{Pow*FbpHw68NABF%LZPK@M;e) zFL?EX*D!b$!fQLc4#4Xaye`7)7QDWN*KhDLp+{x(=!qU-=rI{R_M*oj^f-Z@_0iK6 zJp<7*6g?-R=QQ-pMbG>2c7%63czeTp6ujrddnddYz_U^l6Dc9_SN} zK9kUAIr^+YpM&W03HqEspR?$56@9)z9|j*A_}IgzA$*#wQeHr>WpyCc?(JvDHCZpdR^vgxRE$H_l`W->PQ|NaN z{Vt)u8~W#=|0eX`hW-c9pT7AM{r`rqIee|)YXe^g`0C(W7ru?)+ZMjP;X44nqu@IR zzG3j40N+IT&Vp|;d{f|?1K&09JqX`V;d>gsU%>Y+d`%co0RucRpf3jaVL&(r%)o$k z81Nwme2IZIFt9NOcEUg}4D5q}ei%3$1A{Rz5(6h=;BpKs!oc$wcpU@pVBmcWl;Nj^ zUv>CN@T&vAhVXNPUjY0<;Wrh2d*F8ges|!fU{Dndvc(_?gQ78LItIVt5SFDM*R+dOZa=i-v|DF@Q;N5cK9EF|55ng#^|OP?S;|47(EE1 z$6$0cM#o@uJVt+v(I+wbG)7;?=pQlqFN}VS01E_kK|pr|^g+NN1Pnt!C<0C*;4}ih zK)}xkcz^&If#ngXL7+7P>mslb0-GYxAAy??Sc1Ucpm&14F7z{@p96gX^ar575B&oK zbwJP{1WiTIbOa?KXc>YE5ws6MpCITwf-WKGO9b6Q&^H+4f-$WyW*Ekd!k94_6OJ)U zFlGhDe2(B|2o6E;5(H-;_%4EfMu<5=svx8~LL3p&03lrw;)RgD2pNr#EeP3;5FQamPK-5R?0$^Bgt7NA_7Os>Bh(F{eh3|b&TA<<_NEZa2tf% zBfJ5^ns(>g25OtQwL z>X_6Ble{r06q6=l(lkt3fJw!ev=5U$!lVY8Fn0y$M z|3pj;#0)@8C}Ls}vk)=M5wi+0>kzXUF*^{m8!?v=a|2VVV@gL%8HFh`F(nIA)?mtR zOgV%pcQNGwrkF6L6tNW%TOF~^h>b;T5@P2g_EW_Eh`0)fb3j}T#5F)%OT@KDTzACv zMcgpN`6Dg}apMp-32_;S%R$^)#1$cKFXHYY-U9Je5O0V0nuzy6d>_PzBYqy@w;=vw z#D9wTFA;wm@qZy+!PN4Ys>M_ZQ|n@CV@z$2sogPk0H*q5>S9biiG(UhXov)FB={m> z7!v%EunP(Mk?wTtLFFNH8L?JQ6LDSOBXI>1^O3j< ziJu_xJQA-X@gAmmV%k7Vi^R0mn06Y|6ij!;^j?_WAJd0m`b12hjp_3-eF>(o!}MZI z-;3$TF#R)3zkumCF#Qgu-^cVnFhheG)iA>uGa6w=E6iwz8B;K0HfAivj1!n~3Ny}O z#x2bF6EhxRW(CaDVrFH`w8zW_nCXINeif5iM> zvA`Y++GBwi7KC6y5*94Pg5_AS5)1ONU?Uc6!-Abya2N|NV8K-^xQT@ovCtU{>tSIV zEbM}X-LcRc3nydYG%Q?*g=tuL9t&?^;jdWuCl)d+(qK^)EE2Iuheh?Vs1p`Vz@nvC zRE$N3u;?Tf{f@;V7Q0|^Pb~Ju;-Od^fW@I$9EHU(Se$^x3$b_^7VpC1FR=Il7C*)k z4VGA8Ni{5S!jjrp;({e^STYVvCSl1OELn#o=di?trIuJ)4ND!cv=){&z|y8z+8RsS zW2qOG24U$qERDm`Sy-BarK_>@3oKQztO}MnW0@D0jl;4yESrO63$QE;%XVSeJuFj@ z;)Im?Na=`_0Z0i#N<31QB4s5~@{zJ1DaVj<9w}Flasw%Mkn%lJC8X9uYDc67A$0;$ z9vu*80m+Q{uRs$;gaD=1gSHLuM*6w;=Nb zGOr->CNl3L^H*dtWNDGr1X;b1<%_H!WQ{}CBxFrP)?#F(A}bSF`N+DDtOv*{#fni_ zF$OCpW5sN&$ij+Gu;Mya{EQV3vEngSR>DdJcjGgf|rl~=IxE3Etz zD;2CV!zxRxvc;;VSk(cm+_B0RtA=A$1Xe|3)fB8cgjK&ITS9hyWOqb%0LRBZa(Wb6)Ng4OX@osQL;uzEXI@5kz6Sp6ARe}&cG zV6}q$a>&;rzcTV2kY5Y=uE_U9zAy4eAwLZHQOKW${MpD~jQmvO-$VY-D6mC=GYaaV zzy$>@P|zC%15q#n1*1_Aj)EB|Sd4;P6l_Mp4iv~(V~#aeSkoA5+G9;$tQmwgF<6s; zHECFL7HfXMnm@3{h&6v>tr^yiz}nGRyA*5pU|l7wtBQ3su+9bR+F)HLtm}n!qp&U- z>yof89qV$jZU@#K!n*%Q!C3_afoNOwEZb4B#zaN2dkie>7#jmy3~U4i3l$8+K*bg; zzygu(l9EPB>F(}w?0Wb8p1t<|KR+u@th2F z<<)z6RV=SQi)~x6?Jl-`#CCw#juBfGv7INj%fxo4*zObC%VPUhY`@5BH>y+~d! zlh?ZP`josjme)@5x=da-i=Bel4HmnFVz*B0c8lEsu{$hwH^uIu*m;Xxh}gFmdj+xY zE%w93eva605&IotuOs%RV*fzw{lz{(?DNFFPVB#m{ZDb|C=P?fVYE0*7l*~-uvQ#4 ziNkJjI3NzX;-D`MCgN~M93F_nb8)a02WN5c6bFBC_%4nM#c{Pb?i0t;;%F?6&&APJ z9KFObP8?IjF;g7##j#Wzo5ZPwICT}LKH@Z7oW_aMBymy|r}^TvT%0zE(++XkD^3T+ z$wZtS#mQHkYQJSU3hGV$Cfo;$@;PdqP+r)&`itjV@%$!Ui^OY>c$tZpwRlB~SG;)r z7Vk;oydx>|bcqfQ=xp+5;PfPLXDn3KRXOj5L5uZikvqpS0#79$nw8TeG zd`^jvvG|yX&t36x5uar7`Csd^__h+?KH@u4e7A`2Zt*=JzIx&tB)-Yw*IN9#iJy}A zjT65m;9;No0Ia!Lf$yY zn@D++B5w-hO_}(g68}i?ua|%}63|fs`b&U{1T2$)EfR2A0$xjij|AjNz)uMrDuMq< z;1UVckigv%s3(CpCD2*|?Ikc+0@Eb0R02Oq;4ca4DnY#^XsiTHmLOFLS|&lOC1{-l zZIK{N3DTCJ;}T>jL02W{z63pzpyv`~Cqd2<6f8mSB`8CJN+qaXf__SHX9-r8;L#F1 zO@il1@O}w)kYGP~+e+T{k+(DCt**RvlDARvHc8%Q%iD5!TPtrrN=PpWQI?R&60%4_ z&PvFA32~4RZwX0|ka`L2ETKarbh?DDkkGXfx=lj0CG@m}-jvYi66z$O?h+ayp&1fd zBcWd;>@NxHDPf8dHcrAOOW0xwQY3SEhVz6 zL=KS14H9`oBCklKr9>u4WV1vmNYp%u+9Xl?BuZPN^d;)LL^(>-JBdn?s4R)9l&CKf zEfU>9qI*cRqC_i8^c0ESBhk_FuA97@EAKSr-7$H0THb}oyZ;^2x}#5|H1TZ!?Im|%%XkeD=yDU_H-i5)Jn^CebGVoyozIf=a{v5zIz zPGU61P&~c1WDI#2u43Q;B;barP4DE^+=6_g3P5O1z@PPn7sM z62DpEk4gM#i9av#cO>3Q;yon(y~H<3{AY>(Aqhx=f+X~igu#+9K@#Rl!b(ZdkOVDB z(31oMNidd#>ymI^5}rtcwItX}f`=sdNkY23*O2!|<-LKt_muaw^8Sl_Xe}Rx$%jeu zVYYlYBp*)7hfDI|wtTRc5AO0IQaqDW#_NmP==5t2AT5>+K}nIvwN z#J!UEToUah(L)mbB{57ADT*e4Evfq@^{}KGN$M3zy)CKslIkLnmwW zk~UV-W=h&3Nn0yvTO@6tq#c$t14%QIw40LlSkhidn!TjCNScSF1xs3nq!me8y`=q; z^uHv%m!uDrbX7@TBo9+J!xl6gTgEhN)HGCd_T zKr%xlGg>keB{M@Zt0nWZWVMp4o{}|GvZhLwmSpKm))mQ$l&pNoDwC{VlHE(Phe-BF z$sRA+(il-x0rJ6CcyNUo;j z?w4F0$-OMO_axU+a>FF|z2w$NZlmOWlDw9Z*G2M_C2x-8ZIQg)lDA*-v?cGVi~m?Q;iQm|19G^Aj+6zE8Sz7!ZrfsqtsOF@Mce3wF`u&or%kix@Kcw7okOW}Db zyds77rSORqdP`w|6oyD)niLjDVYw96O5s;2Qj($xQlu_LH>Jo@iX5fLUy2H)=(iOA zCB=QEc)S#^k>Vp#d{T;yrTB>yyGe1Z6cALrS%!)Kp3>q|{wXv!wKol(m*J zB`KRMWizB~ft0P4vYk?PRLU+(nVFQmmNI`SOOUcODa)0z3Ms3TvX4^sP0B^e|B~{* zrM$nC50&ysQa(+}XG{6NQf?&W{!-p76v4q;`qas!Qz_ zsnwL)(^7j`YHg(Ujnu|VZHCkqNNt_eewNywQrAN2I!ax4sp~IwBcyJU)XkE*1yZ*{ z>efr$7OC4Ib^D}FSL#klosra;NS%k&MM}L$eJ`mWDD~r|eumU9m-^?(_m?uAx(3oX|*(MmZqK3v{#z+q)A_zjHJm#nr=vw znKV6-CL3vTktQE$ij<~eX=;+DuhQI0nioj(ZfU+C%{Qd^kucg?#KFAA88he)4g+d>khqr^v@y@^PVjTrVGY%g2-Q(MUd~%g1K< z?{E2Ux%{Uq{~eeA?#h2p12^7)i}HkQx#<#V8Xu8_}v0I%VYWCBVWShOO||XBVUKe*9G!*xqRIuUk}PxbNTv4z9!1o|E1OPt(|=9 zE#HRAw+ZrXseD^4-}cD2qw>vAzFn7Z=JL&2zPZb{K>7AgzNN{xLiyGp-#*KCer}YXhvere`DrFU zz2#@L{7jIaCGzu^{8Er#O7d&G{F*DjR?Dw#@=IHO9g|;%^6R4fvX)=p5+@_euF}Bfpd7ccJ{Qmp?7!Pbc})PyURQKjY=kWcf2){w$F{tL4u&`Ljp<9Fjk$ z<19OP9ZN4e zE%(s!AT9N1d5V@7X?cT|4`}&`-%^%wKrR`|iE~2eEZ4cA-IBgAR`+&AjX`4*j zLfUntU0>Rbp`9A-Hqven?Jm*o7VUy*S3|o-+I^zkciMNQ{SexZqy1#stJ3~o+OMMh zCfe_y{XW|3(*7jv&(Z!e?XT1RHto}CU%+2O`RgKo+3=S)e?{|G7JpUqKc#esHgxDp zhe320PKW7qSVD(2bkLx~K04^o;Upc5>2Qk<=5(;6gFPL5=otR!)H1!qN5%i zZ_zP?jwN*bLnj3~O`y{(IxV7;I-T_CbeT>M=ww4DH#&vUDV1v3;ZPqWN#bQ?~$iF8{?x7BppK{s8xou%6~y4|Il1>NlE=1R9fy2a2f znQl3BE2dio-5TijnQp)6u1NP|biYXVt8{-!cUQWH&^?LnIdm_jdozEl@%KaicHr+c z{?6s^-}Got4`q6crN<(AY@o*(dKlB=Dm`w|<32r}(BlO?;^O-$#^cqjE&Gb4zuUqu;pjR}#;^|dJum3SW>D`{*UFkiP-YWE7O7Hdb z-a_x4^xjYJqx3eU_howDp!Yp`Kc@Fnde_nCFZxWU&m8)!q0dJ8Y@^Rv`dHD&gFgQB zc}Jfj`ZUoO`VOS;X!=g1?@aoxqwg;I9;2@TeQ(kCHGM={JpjbLqE)eyiwrkbWoWXGXt3`bE$$k$ze9tE1l!`nREf zNBWPW|8)9qp#M?&o6`Rg{a?}Fng0ItFJ*uN17Vv%M37Oz-(UYqvVQG5K7@F#iNvs zQXxvUD1B#O8wPe|U@rzvW1uDjbr^Vwf$td9kwM)VG@L;b7^KRe8w|S3pjQlXW6)a$ zMKLIeL8T1(j&diIl~Ep!@;H=LP@apjI?4x7K7q0c%4R5AqwI!q5X#{wC!(B-ayiQN zD1Sux8_K^K+?K&z7~F@!$_yUG;7JUg$>2o{UdiBf4Bo=v6ATVua2$hE8Jx%9G6w%< zNN<&_;%}WLO`D z4Pw|NhAm{+a)zyE*lvdDG0cEr7Z`SxVRsm2!7y8fc`_`3VG#_AXILu3vKdy)uquW% zG3+bDTQj^X!<865g5gsbzJ%ci7=D=HuNdyl@F0fgFuaW6-x;CAh*6A~%ZT-i*vbek zMx18E1x8$F#63nlV}v~;yciM8h!jS4V`LvjE@k9uMxJM65+h3(SB9~DrQt8qgyb#C!+^5T7}UI8NG(lTNu5I(b|kY&ge6Y zzR2hsjDEoAXNSXpj!fyv6eXq%W6F4@OlFEIQx-5~IaAb`vXv=2nX;cLhnRAdDaK6k zXUbcqwq)vLrmkn|Hl|)+sufeim|Dm*nAVnQ9hugRX}y^?o@uk0wx4MpOp9V#5!33K z_L*rvnLdo^6PZ4Z>5G`Yn(5n_ew^tSn0|}t7EE_!dL+{em|n|_w#?|ujIqp6WyS(# ztYpRpX6#|cNoHJT#&u@gWyULJcrzoI8BxqgV@3`$s+jQ~s)A~JRC}P>57iN^;nW!E8Tf$1*#M*_F&`$D9$&8Oxk$%$dcURm@q( zoIT7r!klx=xx}2u%yD9l7jpub6V9AC=A<&WC3Cwn_aEk}GuM#0&dl{^?q}wWWZr7# z-Dh3^^KzK?gZXorzmWNxnZJ|y2bgccd~4>rG2fs08O*O?K_?arVZk^SOl83e7VKuh z2^N^J;5G{$vEUgC>{#H=0zVeKWkDnhVp)*Lg6}Mx!NP?sRA=EG7QSGi6AM4Es1u9S zS@f7inf%+Ee<$^xvSo|-G4Onc#;@d2K#^Q38jA6+Xmds+w z0+w85NhnL=Sdzq&e3sO)ST>SnlUX*0Wy@H$nq`|kyilobiA?957KR!(50Dl1pAaw97bu<{Tq^;vnAl_sn-W9180y0J2Vm65D`&&pI* zmawvxmETYsf!a9K7NWKawQZWH-wUSlqShbZ^nyk`e)mc_uVU-!H{8<&tYGHMM zRxe`pVOF1JwJ)nPSzW{$CDsgQjTUQ;u;wIdF0keiYhJL%i#0K<$z@FgYum84KWitk zb~$TTvvwD2^;vtBwRc(jh_%mIYtLFQ)`qb59c$BBo6Fi_*4DB1Gi!gN-Wv5zsP{m< zKk9=~ABp;S)VHC&2lXSUd!hao^*GcEQLjP$BkNkRPJwm(ST}}slUTQibyr#UfOWR4 zD`S0s)-PxMG1i}D{YBQBvi=_HAF=)^>up${$od@C*RsBu4IS9fhYkO*;RqX^vB8%O zF>J_TLm3QqZCSx`| zVAC@;C9= zQDe(~wivPH9$Q|qjt*&W~&xk z4cThS)+cOz$yO(}da*T_t&wa^WNQXni`iPs)-V76eQLBvqca+P&=`cqFf_)aF%6A* zXe>ix9U2;F>_tNxjiYE7pm7n68)%rLVTFbb8qR2VqT!E5I2y5NB%zUsMgbb-Xw;+e z35_3YgKcfu)|YL{Y+J}SHMU)0n>E{t+4h6&f3v+G+ZVEZGu!pqeunLKY_DKPKXy!I zhdw*bv*Qgra@p~P9lzMwf}LI2*`J*o*=fek$LxH;&LDP1u``LC@sH8Lw3Dn zR}{Nju)8h0r?UGPyHBzEGP`fG`vJROu-l&9A?%K2cPhK{*j>i%Dt7>0zJE$q=|&w2J-X3s z*cZ>fboLdq?+g1ouzxuFC$WDX`q z1AlR#4+q9@U=9b=IH1V^9S-Poz=#7^Iq;AJ)*Nu*fIkO9IS|i*Yz~xjpn(Jb>;6Wo zHCmm}>VuXNS|ia?L2DLT3(#7M);hGdqO}LDgJ>N?>oi(MXqljO3oUcBEYW(2Ry0}- z9E5|jIJlRCIvhO7K~D~rbMPYvf1=$M?apZTM|%?5GtpKKxYP@FfmE;jk@-eK;J);S3HJa=4bmpU~}u?jUqWp{s)KY;>2QtB$S) zx(CqJMfViC=h3~6?tOHhqHB+?7rKGyMxgs1-86Iy(XB=I3%Y;MYlB{A^m?M#4?Sh{ zMxi$Wy=mypL2nUy%g|ec-bVDcp|=M;ZS;z@bJT*PFF5*|qb?lv;%ERzLpd7F(FBgBa5Rgf1spBo=vR)l z=2#bwE#=q+j=kns62~$*-i6~mIIhNV4UXUEcr3@$INrnw;Y3GHC~`uX6LUDB#)<8m z*v$zYP8f3H3MX!G;u$CGIN{ETH=GFLL<}dAIFZSTVop?X;(sIG(Fgsu=qsS#1O0yJ z4@Q3!`v0J>g8oeO=cB&_{Z;6%M}HssH_#75znGIfI5~xr^Ei2wlO~+J!AXBkR&lBg zr~cy9Ku(R})KpH*<)AQPHpGZK2B+K>KLcaaLSldS2=ZyQ)Zm9;*>L|qBxbq zsb8FK&*`q59?$82IemoFww!k2^jl7U;B+RZi#T1&=`R?xz@RGz{V*7U!9N(x!9Wdz ztr+aX;1C99Ft~=neGHys;Dmt}2L2d?V~~JB1_t>Ulw;6{!B-4hVAv7Eo*4GWa0rHD zFr0#+Du(khT#Vrw3^!r89mBmC>R@;bLjw%YV|WQeQw;B7_z*)Y46QMAz%UlW|2Wfw zGc!4Jlrz^kW5JmhoblsK9%ugJY&*_Q=Ik8K{>xbd&f0U)tB+gCe z+zQTZ;@l3-9pKz?&Yk1jCC=U9oH^$#Iro}#o}7Ejxj4=xb1su}1)MA6Ts7yraef-- zH*$U(=XZ1dAm=Y~{t4%;IUmCL_ngn-d1o-4;R{Up$iw3xG;tbGq|vb3+i0h$ptMg=yTy5 z7p`;R9v7Z*!IledTnOSqBo|`2kj#ZVE>v>iBNu*R+ydkF7&{&F;rd&y$8bG`>zQ27=Xx#Izhl}8(~g+-z*G@aWlTq6`VXd4F`bR+ zB1~6cx&hN2m}+5q6w@=9UdHqWrVlWEis@@ioiO#nG!WBpOk*)k#PmBi26JN$H~!_u zT5fFS#szLX{^nL|ZYgl97qxTVLfhunI>EqiW#;MO;859js_Zg1fBMQ&f^_G@mtaXXmXAGn>) z?JRERbGv~%y||;yoeA8T&z)`Dxxt-B+o4LD(yT`a|#@!d( zwdJl8cLTYbz}-~tW^uQQyA9lH$GslhQ{tWq_f)yJmV4UVGv?k^?pbi}Irm<1FNk}w z+)LtK4);EC?<@D)bH6Y5mAOBK`%AdLlKUIDzk~ZnxqpiL=eU1|`_H)V!u=rb$8$fM z`<2}PftdnkJuw@I*#yjHW3~jdt(a+Ib{MnMn4QP$I%W?rdx@DNX6~2;VHS>A0%ob0 zu~dW5GBczgw3esMJcDQ5c{Y$|6L~g|XX-rL$+M$8JIymAo?YeH9iBbn*>j%R^30iMo;-WQ zv$s5p+@KfV0{zo`&c_+?TPh!tiNJ25SxFnnTgF#Y_zetg^fElzSyK< zQ_d>|UiIPCFkUU?)hb@?<<(JMUF6kmUOnN}Q(i^$suA1n*p9?@Hnw}QJ&WyKY+qyR zg>4A7aoE=Lx+Aa0@_HJtSMpk)*H*la;B`5#o3U$)odR|}u%3hWxO`;2`n>^oxL7yA*|Pr-gB z_Dir=!(IdX-Pj+*{uuTbu)m7^E$l6^cfj5Q`ylM!VV{V72KEKmS72X<{YUJ-VgDP4 zb~q^D&IE=ty5)LzQScJn09Mo~xj>BFY4&!hVhch@B<8T#++c-SL;TaCLIJn~A zgF`S5(Kvj-Aq|Io94c^Vz~K`Pzi@1WV`m(D<2Vq7{`@3s^ho? zM@<|L;HZn^2^wqd`8ZeO+=TNF zT-xH&1($xf48vs%E>m%tkINEV*5a}Wmp!=X;bMS`5iVD7xq-_AT%O@#kBciVKDfNa zB?^~BT(WT~#-$3E23)@43a%Y+?TKrDT!-K~8rKQ9PQ`T=t{ZSYi>n2$cDR1PH4E3D zxV6P?9B%7z+mG9E-0tJ{3^zO6-ryFATPkkVxHaSU6Zg)z_r_fb_mQ|y!+kOCYPhe* zT?6;sxF5t_4|jds&*FXwcT?Q&;BJn)1@13!e~o(r?jP~!iN{1dR^V{}4?R52;BgNR zD?GgLh{vM}kN@!ajwg6_!m~e~WAU7h=Tba3nvVR@Op+<5MJ4M zmE+Znx8OY(?|<>u!uuTFm+^jtw*%fjc!%Mgh<66wrFb{s{S}|q_;kZZ37=v3jKgO# zJ~QxHh|h9-HsP}upF{W@$Hx$#OZeQx#~dF^d|u+?gpW5q0r-UD6N^s@J~{Xl<5PoA z6F%SZZHaG3e0$)lh_5ofBk>)N?-YDz;yWMTCHSi0yAIzi`0C^P0AEXdU*Y=}-$;Bv z;9G_75B%EU*8{&1_|3p?DSm75+kxK!{PghC$L}nD7xBA>-);QN@w341C4PbUMc|i< z-+%ah=Zzw7X7Xk=Z+7!WpEuWe^Ncs1yb0hTK0Cm@}G zTmni6s3PDa0Y3H80#6fY zMBo(yZxU!upe2De1UeGvPM|M=!30JUm_T4EfjI;g6Ie-L1A(6i{6P=|wI!$%LEQ=J zL(q7F))I7_psNJkCFl`B_5}G8luJ-CLA3<^Ah;F5!wFtY@J52S6TF{b1A=c6>`ZVF z!QlkQ5}ZbG4#9;4mlIq|a5KSQ3I5I7-n>=e?Hb-{^7aUCZ}8Thx8b~v=WPaWt9bh# zAw3CEB4i{X6A4izWIZ9r2{9zZh!Ar^o)cn6hz}uAgk%v?O~^Mwh0yMV4kL6rp-Tu| zPv`+cj}dx-P!mGU2z^PY2caQ^rVv_AXd_`Q3F}6f5@8bwTR_-G!uAt(lCVpJ-6iZH zVb+A%6Xs1=5MeQdr4Uv?ST$iygncEv72#b7???C`!p9IkjqrtpuONIq;adscMYuNM z#|bwi{1V|e3BOOcCE+g#wX7*+k?YqB;`QohU`3l!+Qo)J&ol5w(`6O+@V@>JU+< zi8@czRibVYWl59+QGP^45|vC;AyH*S)e!ZOs2@bPB)S99-HBEtdN9$Wh@MFF45H@| zy_D!RL~kZqljws)A0_%E(PxM@Ci*JTw}>_)`U%l*h|VCojOdTN>%_ZWyqm(iwY=NM zJ7eBi@Xm#Ik-RJ7-ADeX*NW*z%phVW5i^&VHN@;D<{&X=h`CIRDKYnmc|^=pVqOvB zM2rV9Z-@yYCYqS{#H10ELrf7dmBcg<^NE-r#6oOaVmlGro!CCaDiJ$`*wMsJAa*LT zvxr?l>{4P^5xbt)t;A{)yPw!Y#2zQskk|{vULp1Yv0lW65t~J96LB4g8%f-B;uaCN zk~nSRP7!yBxSPb;6X#7_C~@h;l@a%exZlM8MSK_HdlRoj{7~Y@6F-gkIm9m_eg*OB z#BU~Ellc9_A0hrE@fV1{LHq;at%$cF-kx|5;{AvZCO(4rSmG0j&m_K(_-f*ti2qFd zPZC;?(2fKJ68j$qNyUhc7?Y5Qc6lSDUGCj zCgmroEl6!gssgEhliHWmfus&2RfW`*q^gs;i_~+ZULy5AsZU6CBQ>7XWKs)A{YF{~ z()yA%h_vCPjU`Q$G&Rz;kamc))1=)b?KNp`q=k}}PFgW(4W#`hy(8(0qz@u}IO$_a zpG5j}(&v!Ai1g*8Zzg>w={lqzAzh#J8>GJ`J(%Np`jMeb#z->8k)cAy zbTa0Uv6+m0WSk@8J{eER@Fn8|8I@%GA+tA`BgmXe=3+9{$lOlmJ~DO5JWJ+vGVhZ4 zj7(QDeaH+YGltAmGIPi*BD0dr1~NaB`ID@cWc@`}SF(DMHGr(4WQ`?j5?M3Inn%`R zved{@Cu=iVJILBgmNr>O$vQ>WIkL>jvLMTitRS*JkX1ppkllyuNo3C=dmY(Z$=*Y@ z4%rvTeoVF<*FKIYN#;IoHTBC&!tbNOJPXsV3*Y z|JM!Xwj=j%auvx{CU*?ED&)>2_g`{Xle?ANedHb`_bj|g`SZwMO#Vvp)ydyXz8?AK$iGDX6Y{OecOgHN{A}`TDQHbWM+yc|Fq(pS z6l|g3AO#mGxKDu-1>qFrQt*jF1qypnIG)1k6wan_4TV}1o~Q5zg|8?KpfH)j91064 z{7g|Rin>zNi=tr^O`vE7MN25!NYQqRv?(&6=o&@$D0)nh9Yr1#g;EqxQ4U4b6g5%w zm7+fsx2L!}#r-KBPVqR3CsRC|;w2QXp?E9BniOkOe2n6=6kn#;lwxy=pHXa2u_wiW z6o*k9M{zR6nG_dLTuyNV#h)quMM*14I#JS-lKzwoqht&vDwNEoWDzCHDOpE}1|_>G z(V^r7CFdx)Ldh*k%qe+F$!kiSDeO|E5szy*X zo2pe*?V{==RhOu`N0kLtwp4jh6++c}sxqj`qpF;$2CBYMEmU`)x)0UEsUAo5Osbbr zy@~4WRO?V}K=l=>?@(r6<&2wrTsqvu3pPDdgVyQ`@CX1RvYAUE{ zpyo3*zo~6S?O)V(rnU#Q{iq#6?PzKzQahd6xzzqk?MiCbP`iQJZPf0j_8_%Ks69#T zIchIcYf9}sY9CYkoZ8pax=`y$?Hg)CsEwxfJ+*1n=2BZiZ8fz`)PAA%7j-SDYe$^| zb$?UWm%4$}4X17_b(5%5rEURro2lDJodI>m)IFfiiMk-_QmD(Ou95mS)GJayg8J#y zt5Ls+`rXuPQLjt=3F-}~H=^Ez`kU0>qy7=~PpP+|-hp~I>V2pWq&|%LDC*;>Po_ST z`aJ5JX%HH^($JfRF*MAeVJ;0TXwanL01anpxJQFE4K6fz(-1;KDh)+6e5A28jlF0b zMB^kH7ty$h#{D#&rtvzBRy5kv=tg4@jZriv(3nkQ5smdUex<23O&w|KMbiM9M$B3X)>khF-`8Cb1H2csT zOmig7@ieE5VnX}C@r?vREDq~S4X_=+@q zM;e;QD@tB@kyrlYRXg%(AbB;3yow^P7LZr#$g54{RRVdHPF|IeSGDBT4f5(U^6E?S z>IHfAD|z)dX>=xyZluvf8rzY^ZlrMlX&g!#$C1XVq;U>uTtFI^k;e6;aSLhOOBxT7 z#&pt{LmEp-VzmrBznh0sqkR}h(q$f=wq^T`w>P(t? zlBNNq=^fHEo-|D(P4h_80@AdCG_5C1ainQ4X-XhXX{6~WX(}R36{M-2G+iJ~H%QYx z()1Z=dPbUFkfvWr)8C}2nQ$PS67Eg7j_^Rj-z2;v;cpQ>fbijjk0pEx;d2O&CVUa$ zD+pgl_$I=)6TX-51B53No)^5Z)j98};>pWszM68>M^&qk45^E8$o*~wciS-*|{ef8jMXV0e ztRc-t(%gwv5=;65A$X z+d*vmh%J%W4ino^Vk;oFGGePCwllX-+dX3YjM%;+wim?q3$gu4Y)!;wCw6CI zr^N0_?0&?~h&`Ct-z4^q#NM6Q`w;uv#6FzZM-%%5VxLOvvxz;D*w+yIZemX$_M^mJ zMeG-d{Ti`9B=&EJ{dZ!2O&qSoVIYn-h@&@gj3SO1#Ib}pwh%`GaikMRE^*Wn$7SMp zL>%7`$G^yHLSFlj*J0#!ck+5Dc|DoDo=0As{paKJxk?d7VODA0e-gk=I4! zbvb!mLtdXIuP>6<*U9U<LKWH@uT1|sibD`A=X!Rbn+6%4Hp;algIt#6?;sw~y>T_uIGqe&w+<^E22>{X& zNIxKBfXo207{~@7`+%eaDFt#C$Za5>1Njk16MzeV4?r+L7l57sZvzYi7z;2RU>?9? zfE57i0k#2r0FVff4v-IU9H0i^Jisl0PXL|)yaf0izyja^Cs%Ot0w*IlwFalo;M5bG z27uEra2gLzQ^6?`oR)&qT5yU3r@i2m08Xjklm$-t;8YGy_26_7oNj{C18{l@PS3&V z7jXI$oSMMtH8^X)*$bR?;2Z?bZNa%4IQIePLEtC z56;QpoC(hP;9L&Q_27IFoNs{h$Kd=JoWB9*AHn%gaJDMb;Nl7{p5S5xmk@Ai11=rG zUE&r1nTXeP6TxZsEa^d59-UHehBL4p#BRq1T>zY2?R|?(DVb%Xwb|8O$2CGf@T|N z5m+cE0M}S>T@J1rz;zqA?gQ6D z;F<}px!_t1t`*=~2d-zq^)k5L1lNzj^%1x}1=nxD^(DCe3a)>GYZJKIfC5krP%Thj zpa!6UKwATC540=LUO)!`4F@_IXcW+8KsN&21~eY%5umw1%YdE*dJE_ipg#cp3n&Lk z1(FPs8KjON^#^GvNRvQ{1ZgEmaUdN8DI25$kg7qt4AM=I9)a{VNI!w}7f2l3oWM;B zZboo>6WqFkTYqpH3T|V;?Okx23vMyswjA6xfZKL(iwCzw|a291a3FM z?LN3Y1-I|O?I&>i1Kcd&4&d$v?tb7N2=1-Hy(75y0{6k-{tmcL1ovs+J{R2QgZol& zUkmP=zH`$ypZ2;9E__vhgLBe?$o?v3DX11*5o z6||n9^#`p9v|*ra587^^?E~6DpdAU?@t~aw+S#Cu2JK?dt_1CR&~63oZqUYq_7G^( zL7M~GBG6WVwhpxCKzkLmcR>3Pv`;|$HE3Ug_E*sU4O%OBv;q$mc({Xy4|o{BBM3a+ z1dk5j(G5I$gU3Md7zQ5U;4uL_rh><8@Q4DBh2XIqJl2B8M(~IOkKN!A4<1S2aTq+Z z!6P3$O2MNNJnF&Y9C%y-k6Ykz4?I2vk1xRETk!Y+JbnX@zrn)-9uDwy22To}p5W;R zo(w#L!ShY<>;axbz;hgU&IZrL;JE=j$Xu1K*+GI~sf^gYPWxjRxN(;JX@pH-PUp@cjUM6Tvqfe2;-|3HVll z?`iP81irVx_W}5R4!+-j?~ma72l&1M-)4|ofvf`A4P+mX4Il@C+#2NeAa@117svxZ z9t!d(kjH~O1>{*EM}oWntse+u#!Ab$(;OOSsB`7e+;$ae5^0zXgi3jn`R@aqD81Hf+t_)P}C8Q?b`{8oeC zX7Kv}{8GX182D9y-x=_`0)F?w?{AKVD1pf};-wXT)f&W2DZCg^&AZZPOZgYI3> z%>~^;(5(Yq9Oym-T`K5~fvya6HK4lyx|^W82fC-A`yO<^gRTkiifugwy$|ROpbr6k zThMm{eLv6-1ARE?CxU)D=p#YD0Q4(CzY+9tpx*=f1E5a>eKzQeKwkm+lc2u@`kSDC z0Q#q({|@xOfc|gL+rZ!g1_=yaV90Lp!SFU1Mu1@~7$$>ZHW*^TupA8Q z!LSVs`@nDr44Gia14Ahos=#m(3>Uy~9Sk3V;Sm_V0K?Z{cnOBz!0?>d|f&B}Z6#|?fz#RhoAs`3>+Ce}M2p9+fBOzcC1k8qj`4F%Y0^Wy!T@Y{(0@5KM z4+6>|pdJD)LclEucnASsK)?$K_zeOYA;1A9HJCiXqz6+lnA(A1{9#2h(UU zO#;&lFwFx~ESQ#nX%(2(gJ}zxc7kaim=1y|9Zbi-R1BsHFx7(T445u~=?0iS0@DL9 zeF~<}!SofFEMWEmb1;}YgLwd$M}v7fm}9}b63p*|c^8-uf;k<`d0;LFb3K?Zg83Gh zAA<58^AaFPY zhC|?Z2z(a;XF%Xw2#king%G$50#`%edI;PMf!iT)4+O?TU?K#jLSP02WgvDAq0K~flndu83aCuz?TsCGX(w)fqy|@BLrF@&<;Taf?OcT z6@uI$$P0pG2+~7P00ad=P#6SthM?{c)C+=!L(nJ)8Vf-aA!rH&&48de5EKbPu@JNf zf|fzhN(fpDK^q`wGX!mepj{C30R-)bphO5tfuM8<%7UO{5L5s`B@k2&K~)e`2SKMH z=sW~nhM?;ZbQ^*`hMuL$pF;362!0O1FCqA62>u;{|AOE~2)077 z9YP3%xIl<2gt$Y97lgQ2_a)3 zWCDb|3n9}XWHy9EKu8RPEQFAy5V8_N)6kk29HD+u`(LcWKPpCIHn z2>BC2UO|WjLTnJ)3PPPBR0E-I5b6n`J`m~;p+*QbLud$uz5$`_AhZ*Nc7xEK5ZV_) z2SVr&2ps{T;Sf3wLMK7!R0y33p>rWL3PR^Y=wb+64xy_d^gRfDA40c6=ne?o1EC*6 z=s^fQ1fgjVdIUm`LTDa@7D4E72t5IzH4u6dLeE0zMF_nLp*JD)E`;8P&_@vZ1VX=r z&~G601%&$LOFyA2z?DS%W9z)m{5cV~MeFtGbK-e$*cgy!OFA%<&%v6jG@A}f*nzWNldz3ERwqPAI<b0EHB^Aet3yu|OB&PmD>ATuTY5BTP>APCq((<+ZpO&u+-&Pv0itUsy zrIKuq#8!Umu*p21jE&D8$4s2~c8u^6UT;@jyY{$>dzmGE6q~m*Z44EEV-w-K=MxW~ zF!L{8&@ReR?9BT&_h#}*D)Ckasc0oeO4w=)QgbeuZ68r7W+r||{?P7+LyRHax2zg! z9=>Wp)MUft3g$V2HZ)`7S?rXze$>Ei%+wvbdm0%%y11m)PZ8^3?D z?Y%qZJL``xjWk3qUdl{ssn$M{o-Y2MKIlGMXdB9ZvmC@Gfud_RGaaV9drCoK(SZ`? z-w~(oI29?;JV~`luueTiC#H#~KVLulQX}yfmVBnlp=n1CF)<|;1$VoK%EY1(dKTPZRiOP=) zndvO{yVKxjA1@FAJp9nfgBO_#ww4>XRJ7_nt2HyNp-J`36i=_)de9HV*p;GH$4KUp zK+E!S%d!j7kEhgVq%v&OEiIzrOUDRY5)1u}`97!2ts0-~aC}Q8M)g!Ub&Xpy+`OBL zkyq#iS}y6M2acOLVmqE_T|)JdihSu!Dn5}4samp(x2~5Xg`3#R-6F-O{0o&OjDPxn zAF&Uv!uE7MDDUE@+$lpC;i$(ioNP^$ms1IEXQ}YszLNe+eSiOzwEA2PGX>BS%v4TS zSIo*c<;^PddTnh^UTTpaJaR5YsAhRR}% zaE|WRpF2nMHTdIP{nVO=b{tBX@h0Ui%ce2YSh_;IgALqgSbmTb6BCmXlh82V(J}pT znpd7tm5l8aleSJ?F_W2Q(1^MC1}{2x)x^#3esG!I+haYOhw%=;-TeMfO1uS<}b)!Oq{ocQ(QoL#|dMulZeJkbPSBdW=tIG0~9K(l* zWp$Q5jx2nUpXcM4nNogHfH*J4^S_zt3RPKs_&c)L$7zIk$-m|=BUECaxG3{bzE6az zwQ@Jy5i2dVa#CtyTH;|&1=HO=db+Ii^dWqjn2rbh6vNf?*2yOh)-&(>RG8;>?Ha>O zttt0QsY*B%e^DQ~-$nG8HlY1NQw-l-*QS$KAe=1c!WEPwmRnDlP0Gh%1F%O-Xc^PLof>v z^ibKs>XU}Z{rd!)(}kJPZ8-Bc4wWCQi9gL$tEdQ>-lXZE3#JFtmsW`z*A>RL^ediA(qODvUg3Nnk+j^o0#X2u(o z_eri!xDbDbd7h{9_D1fEdcPBnUv0DbN0^L6=~YkF2<5eC2>$h zi3qV@9N>{+9#6nlob&MKfFwVR7*G`AqD>~IYa5S?_)V+TEz za4G(lp8Hpeg6Kb)|5b`p(od(vh4|a{QFQE{>AND|?-V_bc}3Cms@%fkXaEJ&?kqWW zQ5D9RcY4xl_00GB$5{k=;cMaOg8#-B?5(JMg!MB0v`YM9??-u4l_c6yTLDf=*D9MT zh7VNP%cw1(l4)|W*X{_k1njJHRK%1 zVx~NFCfI1*O`5SYV)J~{vLVx>m@}v4hfDG#anybsz2NFeqSaQ>!zjta*DZ*hXIPi~ zUgk#A{ECNb|7E;bmylX!esHvcnN0NP_M^4Bi|S+EB5RxGhf|QylS~Ynir*?7ddV5 z_%)N(Ox((xb7}g$eCGWbJ%v7L6d!W9ikX3)(IXUkNefCX7$dEImaWWf4OOO2xa`$P z^XE8{@G!TIkZn%P^dn{7qcASpIU16f%-dzvr=2=@S|4#>_sq>R*G+T$KudCq%5qO) z`_5?&@%Bh6WffxVuHvo4AYJ(};m0GAFDHD& z)Zfx&QITuIct2+PkS5&U&vaL55HlsvksC%XjA))k3-c?FrRHn71ywbM?45{>Jn4xQ6Y{$m#Y|_>YHm$!?a3O( z=FzCg$hlF>w1P^O5tieEAS6o8Ihd>GKX5{~&tJE6;i>`Sg=U3t-ivPi_WoPRH;>%N zxR_s$-;O7ITuPx9orIp!RcxuX42cxo)HZLCAT$3y)Gt1Nyj+1; zi{|jYqL@)gi~gvsAxP=m|AkMoT)m{jiOc8 zaM5F>6(f^l4Q+qVag$2bYTM6zoE+6z^#37J6f^yB%8TVlEe`aKmT2paY6bChlqKxMZf`-vHEjiY zq@#{MsicqUJ8rf;2Ty(&&2?Zf(_EoTcdXpLrivyWJ$URu9`i+je8TYtmFKl}JfZR@ z%x4%~sGhlf9y8_AA@j#X4>885>ub_-E6tBioqo<;&=~kgL2E4oBio6fM`B8}btFA@ zB>PxKfkw>blWM5NccUzf;w^Q0Wm5ea!y&bFms&PSe7WU4dDZ>zwl*1?zDvu$XMUJp zQFXy^-V#Bl8>TVC3woSSmxT_|b|sqovAiS2sVBHE_MJYLQJq^{nwQT^pVBHGj3KwA zQ1sxv4^MEe=KL8I?IPQ@pUYH# zQ_*Gan<0_R>nc50@~K9O2xVTA>9`b}yI0im0beCYU=BK@+u>kiaJMb12AhX5pI-Fg zD$}Y@Uu=10eD&gR{v$IQPJcR-$u)H3fNfokT?eFOk2Hs8|2rAIn{CSe_;V#0{e0W{ zkIi@gD;W)6Z_?tHyk{RsM=*^Zkq1*_B?tXLb@P4ZpTSp5R+fM(e7U|L4U9~%G*07#y5NLm# zdA_Rns>ZSuXH*#P=bb#oOugwZ!dRLoRJ=1Y`q7ijEs=H^5UcObjmq;=%-cabc3X@P z?|yFmsl0p2IJ#8ZXEARhRS65nw&nM*ZTUTw)-uLYDj&(Pn1wmL!sf#b8OKs{nW~v` zt152Mx@AjOMlP7Ka^m{&>)+izbsvV0oBMC2-adLe=Th-0G)5VNE(Txw2a@9i6>Su& zdP}jYx6r8i22nl@T`2F4tLXTI#;89&Bru!eaoBVIJY{BAs#UO*<0_S3Ms#s3rOBB| zIf?n)MRd>|&l8M~OgOQ>F8-|E{vE

r2aSnK_qJ>l&3Umv6Ru<7yRU<>aTAXjs78 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

?F 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°QYrwL_q#AHgxH02yk+VhvqWU8w$pK`2Haqu1^KA z%_rvX{TN`qNYP?Lnn7g8x)L+4pKo2UBuKx7C)uUN7uQ@!y|wG|fdgmIcWeW(z%Vb9 zlW<%pcbvho0?>z6I-EB@N1F6yuQ{Ji9|Wdek8YZZ1scVHBBa08#n4|X;PyjIE07jc z5#mUDr?FW$IQtO?@sbD`kC1mgGV(4kdmQj3bHKEf2Vm@v;(=(4A%GxZz1gdHP*wIn zD;cnhLl!y^&Dr`)f3!_~cqZ>^np3ouAw<6}EjyXdkB-^b*v>5lD8s|_s0m;&*wT z)<}z6_#2;$XoiJ1^vX+7PL%8Tl89zKaaHrgL8RORU7S}&%1xC9J8B_+yYylovSxu| z>3Xmm2>uWy@4K~R4`wB#^Zy?_;}qq>nC^Kfl3lM}4YJBXml%RqNJL{I4ML|8Q)Cbk zmMy66cp->APS!*>te^<3EttdiK+KuSMek59dWUjRU_a(rK+LY038IHt97a6>QD_?_ z!BbJ+2@u$Xm=bej4Z9*Qc~DQ7tY|aQl)!2cya^g83gSg{rM{*yMqT!BL%^>q*Nv8>%?a z7{9_Ez-beWrf`8FdwD$Qs!a*MQsaLmV1~T0F`- zsJeDmbEVa?U(7Panq%cGlk8yruRomeBFa2aer1xy z4~nl$wd7ZrZj7hc!YD}R%DJkys1J-W)Bs}?HLQ+{lGU*aNHz*w*CFDznt40oM)gD@ zMWj3}6fkwl(^OAMykc$j;g!yi%>9>aYfa69vPG*+d$ zxiB`)Y0%(9fJRF8s!aKi=;?7}eWIjuC5rCunw}g;8kiSAsey-l&v0;60nIXeGdFAl zZeAd1LGcNKq{>(v3LK(%;3~#hC4BEc^sEA86uDwlUJ=f=ftsjq1-p_$ezb z?B#17ibPIt%mczuz6`y@2IU

rjcGS59>$as~S3JiG>L*rUhCGoheR*2<&ruzd9I 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

RG?M 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

    1JTq#RzbcAWS7LLGvE0AK?i+tK774Q)Hs1 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
    m2kr(x}u$-mwwl=S=0-E~NkC*BJ`KEy6}2C3Rn~ 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%0DkAab&m<-YpXTz8+PlDL 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

    uZGxq>R)248b1q8+zHy}_ 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%0A41-qXeYPH#S(SeRuvl9#pbgv;^S z`-bMZ<^2`dO%s9Lw1_bvi)M{EGRgI?ZPBd8Ad8x~tCa0OV= z#1Va|`$^KYUXnZawGbZ3tMEv6Z`^{~x{@?@828{vj2csFdt}|`rq}T)7~ldYPsD<` zGZ(b~mVY^ue*q5{t-Xj`p&stI(*e}$FE#2$We;$8@Q+Rn28ri8Y8*~1v(6=4xenIz zhOp)R<_<8Ok=9ViKt{GIXj-#eu@bRHF8i=(Ah&) zG#v+m>b!~Mqc4dnPAl9g##pWxJ!ky*$wvMgFfYluD2lYWd;`6)&Xj&2*Ik;RVE=U= zSn2F1&{`&3m5yF0fbcr{|8?jq2ynh{6(60t8++mZHvF|zOxMssHPcj%iusKA26gufhnlMM_)bnvSHk7eS5!vbcV}2%IGaZ}jG_(d^D(#zt zs-!mMt1$bB72KuHQAGd8X-bDTza z2XyD3i8!n@{&M!Iz58-^Y7=g;Z`CQd$5*^b$c&-#5ixyizJEwRZnu!SEhWh%IXhBv zGqAz2r@)$ANI$WC-)>+{5Q)f7m>znY2K-+_jzC@9$dS9~em05EkD;#D$W!$|Ted(a zgbW`PuLr8vdnKS8LWUkf$WQ<`MWInLy%n4v)ku^cY8xSaPQU~gv_f&cjaWHh#Z0az zsP^Th|E+w6s;W;p1{6Y2{8SSZZ-%O>4^&kQ0;sp_nA{v)?5<*j-nz=>1nmzoL^nuG z8o{TSG!mrAbcTLztiFBIhoeAF;3_tcTNJJq)bYoMm21 zKfV3n9>WdTnn0}OTi&AGT80?_fWv$X&ZLn|eXJhv6Ymza2-T6LRpR!cE;jH(*tG$c zN-c@0!nVPR1i_+($LZ*j)Z#p2PHI+0dKMc77g_ObG+w?;%8M_6>L2>ZCtUGm_PTjZ zx^-?dhdV!WPAQQEJ+!I4cx(GjLtx=@ji=JBGbrONsNiFdD zj=D`IJA{#-1GT-6p?Cqokf1e=T{mXMxP=p`%TmEVJ{? z_<2#v+{`#qux1B29Td=b*_W;@(8!%Gt zozku$ywoyjA^y?v9#pp;f3F8IFGv0c4rB&-Off0SO;H`ek5sxe<8>PQROr-(Tr_Fp zp+NW$%Ho>yII45N!P1qHzRL&B9g6uQ{@ul5C zek^B_&U~AEpsr8xWSfR0Vjv0=NJGOXu3jpplFov6ER#%$o1Qk?ZOHD+Gs}=MQ+s#P ziXCmD;s7UN;jcjbW@P}Yt7ApnS9`QBfHlM+slstvFivoTJ7`nK&udf1^R`L6obY05 z)t)eCB_9z0MA8@b=z88!+LdWTcuL#HR*zrBWCZU4oqd!qS zJoee~)4ynQ1MC+OvELRwG%^FX*Y?{M+J1WwI-IAxu>`s!r^qj2pTr}M* zoR8fW;-sj=sH9EFMit6;m^Y|h81d-Yt8JwD0*T3__UPrkJWNdIi4w=61^nrqDD*{X zgoqlJnZ*f*MdlM;Jpdsjw6B=>ej($;&K()svjr?7nvDYGIz==6|H*2A>?)=*H%eL9 zbJVv&wTl8OE=WzbdtJ@Rl#k3wZpkfv(u)w~74E5H>MDMW4fe)8g($GP zbWdyjgbUL3B;oJgB&5Z{kY;43ADSZq*$=uIt$1L6F&r;I&pb9UkKI39HK@(NE#K|(~u#OvwQ(@0)5@aEHl(QOjxLWHR1&O$|*x+WnG3V2NIhvSJ8 zC$Il*iu+@*3ZZNKHHfWis^g!{?JzRb1&Hi`G1Mi7>;uosk_YVL;TW`QfpWcF+PQPg zE*;R_ubBP(K3{YDh5RcNy1bKCjgFkWIKnt_z_*hJEC)>kOMCpz&AXc=IJR>}I%_ehv`i%&oj=tIu_Dxv6mzL6+4n+QY+6>a3CeGA04o%qWgkKU3 zxklWcTL&>~j7rD9XlNx9b1~?(#bDsv{G^S!*%qq>v@wD@yG{rkeFS{chdPWPsAz-U zd-_b1>4G8Nxy;Is(R$!Zr z#60;;(I2?=&4iOhMOTd*H^FPX={GoPwFwJ#5)Z~4*Vta`J4c2^3^XnbpEG^tV(;Ib zlMdq>XPZPj;~Tvr2F)2bb;{UC?6o%%P8IFFW>B^xx-epFx|iA$7m<7b-e^B6A45@x zI<6&rcl$uFuxsZKUdSE_PSP&j`UUg9pYPfad8;E-N^z`hTyAtet>uRk=GwYBH_k)% zL8#7;?I_;9XV3Nn2IVdEvxKlH3yfN^ok4B4Lu9y37+vH5Oy@?6*4zri+VpdAVRA3b zaH%g;rFojFv@ITb3sq^JP?c7be+2aB!$1GQuJa>)kEs!VTLFDrEuvUU%=Kk_=3#d! zISV&F(z%%uw}oF%dQHmJxw1k_`H4#?tBv4hL68Sl*QDbkA;;bi!R}17ro1p^?~~yL zl}F%|qEp}p#60)9)b=aVEbJR zU9KF5&vn&9_tbRA?&{(lo3@c3P<+tUBv=A>kkk4#FmRB{E|5?M!P(MJr=;@9een}D zp)2i!Sh?+-Z^m?U;Z`hU9Cchu3YpclZ}zp_>c;f?MvbV$Hu9Dg=$SKLD}T+63qc%n z;=>4Q|T6Hy_8i7@-w73$*T8EF2rzHQY4axC<`5 zUleePW4NKHl&}4hdhEss(3*>}mL%vDBc#><>iaUeF?G6twCCkWYOw)t(qSf)Q194! zhG=0wb$y3lGl_Z(AjcHjJF0Do;z>Pzf-Hmem)a{>m#F=}pbEpBz;SLZA*Kz$bcP=q zwBf5TPN)Im070_s7>){R4c0LnTBnh$<6c&S)!-fX@{#U*l^|Kt%nKJ7ttMI4o*Nd% zYtI!VOKKd4JerbT=%GJHBxiE%sDYFDXYbfcK~7#!wUtOw+i5LpsSmz^6LZ ziJhRf8KgM=@If)oaNMf#|MxhargPvbG%}z@WS8BnbQh_*6iF)IH@8`UMD~-zT}2 zH!Ctv<3-H71sb_VkmO5bB_CWp*WZ!7I-tdd_PGl>v%Ntt;|Va#xh=$1QdXEiuWv6#m$=js#Tf@`iF%xaWS&8qd0{uJRu(tWDJq|K4xU^yQGSPf zqaL^T6_gsCA5mUoHEXUed8y+CvGR`!c57#9hiz2;Nm)l7=aQDxZ5e5ZO$+uFdJ6R| zi>n7F3>`XZLig^Yb{{!%VE0utQ*c@O4CS`mmib`5^g40`5_ntQ=7_+nZn5C?xFPq_ zMP}HJK7DC=akIlLjBM_ZAxLA;(}25*4p>4FK1;013{ zx4j2lWFiRx_DdjKApW(M)YC+X1x&c1WQIxPHM@+IQ)aehS1T&oT@n1)kRFX2-|xDH(@RKIcnpJ6#|`v7Eqr(F~33Y^PMsW-4PQJ zbCI@C8NYzqS`h`4*^mx#hfYld1pHQG=HRZhw79XSFKQN;blIm%mvQIVXY8}Wv-pFs zuJ=M1HBzCln03S}xc_XPBap7Ro6K(lB-kx#U^)>uyi}GpZ_4d|@>XYv_QpkOv79Kk z*QqLpt0#Ca0QL+wuu-1(ETtoZKCmMF!<3RwjF^OR-u6up;V^itDf>f5)-- zOQ2zBtVx4z?bcNpE7A>DCiN@|9*d<0FSrmd*bZ(1hXTTZEu->pLLc3STB2kpo9x&~ z^Bj(W9yb0MaExf!aVBu`?^t~GT+6T2&xJgGXb>CRLQTY?6{u`b5E@cLO`x_k60$l1 zzvqRrly$+E;lfZ`upi6=@Y)v$Y}=DH(J@%9uVlpkcSw8cGy#xe>UKh7vwo-+!0pro zaJ_{94xfIDqofJopw)hb=`oNcs6OxBvKsjGNu`R??^8ab?P=Zm{@)E-J#Kl&d4tD7 z-C55$`asmt4W|ufp7I54pXk>2`)=6UagnX2_vEMOk^ffd~H)qF5G6t+84f zBD(l5YbIu57(S%!`N2ISHa$KiL2+$XJrko0XJ`YueE}FtP>!(#BGoG}P17~HC#(6) zL8N;iBZ0!Z=5akgzN|gKNKi>Q;SMo5lDVN0_a@mX+o>az7t|7ol$9)*R-td$loEdw zwvrGPM)Bq)Xqd1z@%fY>#iSOQD=VZC zY&lyl1yRq|AZk)83(}IiKh-Q&s>HnIXpQ@ahKRrO)vG`~^%E7pYg)yx@7It!)tcbe zT>molR>_fagOUKYh5_wBH4BXalpEGl*U|V(^eE_PFkop-#>(_%sfLRq{VAr`O&HZP zz$H9kLMGr3`$0AO%$3Se^vgl0=k$85v~R`(^lE+HQDkwo9f;b1_0a$MSXg1p^z-@# zE^mmmn9V$Ux6QF$60P|yV*%kQ#dn~plYLBg|nv!oqO1}{8gk;e} zT_#t}6)n^fYBh&QDT2BsCR7OO)*=_l6r#)%(e~UI%5v&90AiLGhzNgSYx#G9$mH2! zelkQs7YNCF7?SrB)T%Wu)Vl~>x=B%) z!nyl^X9wNTt(H&>cEH{;Z;()iQ_q?tu{cNCv_mN;QXFi25_^B2V^~5vwzUt>K)t~^ zgQyoV4F{^){-i`Kh^B^WlyLEUo}8bs1MHe6iR&guPMJH!IDWu@@c!U4K5o%(Q8idc7jv>T5skvLTa##ybp?byRg0#HstX!zo0P*~{+_u$j>VZPH zS6cp-9n|V5xFw^)#~K5Ixo#+}6-16gV)Im)OPyd(OWT~j3693G5BS)Z4Vv?DL2R6E zesJJG6h@Jz{ukyJ!kpDI+g`Vzlqb9a(JYnPEXOUQi|F9{Ew3f8MQ9c#mt+>E?8p>Y zTq?CA{0ar%xD)el#Qk}<08u~yDHFeDs~0>f%gGNhNzqiwA|b;CSy%jqv&ly@cP4L7 z%gR8#?>WPJ`AghA6yomPe~Y{CG4!28gAWA(bv?8VC5K{?fP)O({_^P{i6(#~I=)}Op5vP}>$&I5nag`X64je6814hT`Y$yYSHl0zdZ(7qm0%Dm z++aV4u+5$MCNZ(K3%SXb-Q~+}vdv}uXZ17o2h_u&Wj~a^52bd4(H~9HvGeGUzGNV7 zFBe0`;X*(kfKB2rLfQA7_;*+}WdtL&9dEORxA?+a?EAZ5r*iiGuHMF|9LLRB<1BfM z*G^;;MYqY^K$4G^_dVEoe^8N;oz&mhbY=7T7{hb@*Q>j&?uOx29Yt+;U7IHB>$EWz zM3SJG5fkQ|0}5i!5#3d{daNGKdsXA^Iq&yA&yVkqGBZ6hJsqm*zV0gkUqaL&E1S%! znCq>zpUf-I;}y8h#H&Q|^3lAESy_%|f7_*_M+dtNADnP#&z{sHX}cq4?YB63(h9%e z?g5jM+MUADyidz?1gRWFG&R8ZJMyM5k;ab`O-lp#@ebg}R@5#XXQYtrRi~pm1!{AJmPRrqYvP5hD8Ht#2sn)|v_Jhf zG}uSWn`-Tc7eF?M-nnMisy#-Ic~cA9?t@O{ZPo6X;+dW7epE#0{XME4gUpWpH8dUV}UEyr9YxQmncKW6g-zqG_sDwUeKA;_>Y*N=N zzi+xiIGGiQ;|0c4AE=i#ty1HFEHfzFj7?jKI8oUF5T6rR>g32F^@NT}PV+dBWF` zCp=oq6Anh6@EF#^+8*%t1m&j43<=z$WridmGbBo6hJ^Q+(tqS|qhBMg@6YX*Lc)J{ z)$L8U(yphT+kX_+FVysv@PX{A>Pe)KPMyb4*YD&+r-QZvl*q&tMb*qTkX(Nx6Y~+cfO#`IpE3f=y^VL%a9~+^J@wh6Qa;-O=MpNz< z)uE?2dd$q4%-MDGxtQxK?nR^@?n$VABDvjt`62V!)WvW0?}7ybznV-WMGV=VEPl@wlDO##`( zA%-*&#=Vs_<6f9-W#pi`siTfTHJOC!rY`ofEY^48?|S%2FNFRKWy5IlTGO9R*7Rq# zp@c=kx|h1;ky^_PFKhYoR)`^x+IHt9CUN@}m>zGgyb*hK%hiN)I}Ywu%7Pr{ie(YF z6R3Ah@a8!nqQMG8G#DON#bYfQOuUXQv*6wOPjnan0uddSp=~gn#NtD0f<030AyT0B z)6y&8XeSy3`pP0wU^1Rcd`JKrqMO+&us7y!YVSkP zNR1avp`fW_M)WZC%p6YL{~}Xvy`BfdUoKY`(VyP7z8V z8bb%TsHxP7FBG@P#!hgS68cUNw<-$!MItAJFAC5=AZ8#bg5AKPaJBsE#($NHv2$Kd z=t@i|dH$}!`m=VbI0Y4A3GeVpY5hYXkL5X|2QKVJOHU&=PDXFqW6?Gqi~6ZQ>qYH* z;v*k6XBZJ@&z&=K-f$8XyJp?$bw)?Ni@N-a*vdVj6+WR@Z^qo$Q4^2`xVWPqHk_P_ zJiK|&&ZKP#+cqVMXacYU|K`<#X9r&Gte?Ev(HgH7xpuW{y=lPTXo<&f z&h9I5Hvx^tA1ur}6F3yef5mU`&>C`9-8JQ9}k6(Cw55 z0=IeMsg6K`iZ&$j27oa1FR&ro;+0O_y~&I92{GH&Y^QEXKznrI<7ZBq@cXck9@Byr zh_?KuqbX?{lj0M$V8Qx9>_{{>?8(KB*x4uSUl0B5Hxd#t8Y;2jty=WJFK?p18Fg`M zPI~&5lx^D(lAsS=GJWyPMTQ@qg#G$@L((nFO+@^iLd4&`pzY?FQPbB>TZ1(w^v^)7 z)EsHAaEFn3Ra`0MW)gU>A-Q`d)Va)6ZSd9#H)Hh07vmpwsKjK|t}#pMtLGN}3wVCd zU?6yT{h36mD4(#NxYBIs)oR>N@kFR#dpd*d=}dK)Cu~UGu$IoZP2zh%H>qVOsoM~z znsq?i~BaC?tcPm?~5-GdT>NT3h#+BNyIjZ zI-VhV>NFbkBKT9Z7ycCO#WwA=ZSZz1V=A@=0~i~ChH>tvl2JzvGU z5E*D_+gTmQcQ;Px5i*{VIwByd74zMADE3Gsf&(hlfYH+Xy5Kl{Vqb-OcPc_{{6u>l zX1){oQ|bg!kMaR*{!@9}7I2D>pl&G4U`#Ut=4D8Nhlwx$O3g1xYIM5Md&_9dObwg! z`YVvi%_^>B=IobG6&l^34qkbt`zYanu zwrwr&3?j*2)Ql3|w^DLDr z`#&Dyk72439!O2#1&*~wqx9te(mM1?NpQalC1r^Kb>jt7pZncr?{Q4>^$`<>1CSk~ z$?Ts%a$P9c7YdJk=p-4zG2c{%ZuPMPz`f- z4CZVEUo{ZHSC0jlv04OQ{Vh=LQ^>lo(ikgIWl_CY6dTT?{Wb&h>Dg24AnQ*Z{YWqH zSOov^&FDI<+oG_g zGZ+1CV1vKNs`QdQqcn*mZQSg3aMhqu7T7$n=lb}6#jT1pABx$!CBbcPc53vXg)h^X~b;v>;4)gncvJs=<-tyO%*N!1$G}fYsU!-JL=h4pEjIS3j&&$24$;v!Db!gu<%c_O;JvU?zzU;;vp28FoAkjUe zIuxboCLTgJaWJ*xxGJd}f%(QTN67Q5yPm!@CdD2zTQp{XPk}5Z2+P#T?9V(ZV`zrg z89Gg)wT#8laK{=AcP#4Ig(yd148$A%<*VAEJ87rokAdT452>@gm`-BYFu_`n?Zl&D zRQ(kcKAlojp7lJHtCoZ#W=~}3Ip*p))P}H{?CC3J&}d*ZpTJRSgYO^D{=BDs|0r5+ z6DBuIk^Rw)g>spey$6d;)(L)FA2oAH*ngmRUzhL38AVtN($A=ThP1~KA4@5={enPq zL`8B$MG7ZZeV!id^g;4tKB%$I5#>UfpltogMm?Yv9KhJBslFOzJQ4 zTYb!`=vC2?23mFwoZ0G!PYBX@mHpsqnE`jk6C7@4eomjf;M_@dGq!S zM`Fyh6o8UCRX6W8gMCt(nr@5p4rPy!`nU?Mj{zFbKI%94u&Ly13)#!x*5iLL_^`SN zId-)wLjD=ZtKI&wlT4C*cr`d8py%wwJHJwTDffXf&V_Is*sG?cr*;TL9S_=&ErSRZ zZ59-=S%0f&**Bq(EiV+ZMZL%k>e>K96+$ci|3d4MdVoZ4UrpupByeK)UI@+DK^l+l z+#yV;y4M{~&lJu8`yiTZBN>X9q5qqis3d3nqv8{h2RLBA(u&tdqw;EkzXl+B_sI}3e}&aEm@%PN9U*Gbg>_AKchPXhY4Ctr0$J=Pd{AZu%xPoT!gjRFZq4x8LbPG)b(OO16y3!7Fhe2=@)@d9C>Ub3`ZTurO zQ!C>rDL&9s9gg3Zn!YVL6>A9|)r8d@k3I{1OAbaKi9Aj#`XY%=kKX7cTHc4WrREx# zG6Pwy4ZEZFM;W>vCDH{s9kECNFbdkQ)5$d;p$G2Kq^?4QGhuYc>)TBAKqAHB6hYQ z^YFDNCR)mcKn31Wet6^fmoL|$;B42odiA!)q2c^TzkFKgmwRaX<#C#R8J`!1&x@z_ zfOaU-lTSjZ9Fu$ChKV{nCGGAG6}ibhk(4o4`oy(wKt1t)cc?qc-TS&C1+IXcy zcj4ydz8*&Nkr~wGBR)%dEeyt}!)5VzH6pYhuu&WekDvc84p>PdMD2C>V_GH={o5z3 zwBlHxhteZ(HF2z5beDMYM!b#Ax|8rzEJ)6~eE9Rns{;c9+7I;h`0a3>S)AsZ@{8)P zYOA4d7~s*Rgf+62fKwd2h$og8|3UK%rd1!LeKU9Li~)N0#Q@AB*di5?Wks6^B(c=x z7*V%r&#tESqM&lQ0*yB-i?Zdk_Vf-p@XcVvd;7dObpLMcBciEXdq7LG;$D7ykLfjP zbWcc6Ka=p`!|CbcalH8-pEo4LZd;RR^p0CFW*T*OAx4;a{xX>xRzRqF^F~bkHOrMP zXOfTXLb0Jou>m6#L&m_Dw?mat+-?P0JlC(SOSopak$65cI~(5fRYhg8 zF+#ZaPBeCIRb?`_2cUmPyNR#FpGnKw4^vSW*OVt*`MxokRw#?noG2$?A3g#OSfcR&6VV@LyIKYU^*TyuSWw;WkYub{{%#IzQ@A>ooI@)^#@WlE7T*%$b0&`-!6m zcQJLz9DI8M1a?k(;v2J&dj&P9vCv3M1MIw&LLJ7C0mi52>yL1B5^p7o zSCa6`6!FUMc)RQd?_Sjrqi}t00Q^`5lMkRPNUkuN)NIZ7-}d2$sJlYcGIuc=?r#pL z)tj*85`52LiIa+jv%{Zpg5mW_cj;(U+)jiFgmZV`$%jb$Zc7*SvCvYPu))zSU9oie z(iMgRXe-LVKCj{rf<~cSqjScQV;6RPpk*r)ivkh7;E@koFnZPm;d3!e^SQ{{cpxn; zAvq}_4Ky1#@83r9NZIun(V3BZjJ9e%!d(QQ#{uCkB46<8Y&(dW63L#&5W@5Tz~v0m zc|t#Qa-^Xb4BKu+vMjnQG=Lxs4#FclNlM<5io_NtSKA8Qum6D%1gL`w6k$`i6dbzP1`9oXgmF57%9H z_>kAq1D;RaK~8+oOw0IM3bjfF)`RK-34e>d=pRPiP?p#5;x+h*rtGU;z>%1|E|Pt_ z)^6B=94uy*MGIH7a*@Yf8?-^k95ZM@r?K!N z#5i(E%SnV0&j?stt%0!;PeJY+Qbb~iGMM+1)okXdWaBcWjwWIqOZZ~Dwu5&crN$=2 zV)X$KX&;5vKeBumOyI@+j{CU4Xfjsz8IKV z4)5IU_Api!$#@6OUTC$SyI6R6yS789`!15T{>D`#-lda);q9>)WvOhEstaU0f_N&H z*2eA#nnr9r-}OoPg+IUo-))94n*d{vR%`=)C72X#1e3dwKm^+e7K?22C(?f1k6&3l_1>835o3> z(0O8gS`Nendk|m0*?qp!r%|I0eLOtc=RA3GHRm%J+JDO+DCrJJDj15jQf094T!2)b zk6g-w$0bO)pvRViKPE8q^@yI=Qb_H&%P8M=Bh2-_trzwNCw~T$dTYU?_u|eSr0!^H zSZ^wY;5K`z%?r^<(_?b=YDOzq@jKkskQ!7s2!n@M_}iGD`W(gABWiS8m zs?-&z&M)X&Vl1V)=dkkc+FaAPpVn4PJ0<0FuKGEbx;qftK-H02P|U#rqO;6DJoRYE z-!&KR8L)|R&x=2KG~T_TX03oiJBaOG^5gJ%x%9>Raj1>Z7#OE$p}ba&l!*CT-Wg9+Ee#+W3 z1mKn~pnbn}d!h~?B8Qevg=+Ds2nM0%odEwq>2+-^%24xh;s`A)1LW432xTx>T3JyW z_K84K>d>1^#^wH>Ak%yVnNmlr&8?B_CdfBIkQ8N6ryE2K1<8$lg@)im?3NQ2>Ufms za@9!ql2%5~2FtcVp40@(Rs7x#!n+c1%Sy=e!33xFuW`OaBnx$cv+jGl{|;mk0WCOl z4j`({eyz;b^E7oD%7V$%ZX52CvsVDej1+LpZ-50tq}B17I_xRRB;ysU1B33~o^-G| z@DUgXOHg|wz6cd#MX?(&1lqn`s)H^IC#dz2FCl@EatK}1^evLLwE8d9Cqre_dCrqS z@7@B7Sd{q|Qb$(5n%yOm!5vZ57ZO z`r$;1H4|<_AA2>XE|^MDZmY3=N`o$%IYqr@ij&ATb{z{ZEO5T+GZ$K}1-kf$$Mi~W zOH2Jq9-Pa(kYVAe=!_Y1a3yK>ziK*Z3@;pi0QiH*pG7EQoONv=!VdjQOz3!=P_F3inf9xe-`#-3yhjdOk=sQ3GyG>hzif z=~{h2_V50c*~X#>RPZp2yCAd9o@#s{Tk=oa`x4sT!?m_|C$zms6t}&9z}zyEPqJZ+ z{lD1E;ZQK20$$^BO}M=I!Nd^BRB0s0iz0Ss$F`)DE$LYPzacrUw zP#i1EE=uJxRihtb(h>yKM zjew-VzH$efqmY(9Pdur%b{ls>K@8!>udNz2nQr9t^~Rkz*LcFQLEV}QjP>=8*5>Uyc@=SKC0!q{ zxwrS^HP%uPKST&d(^zO#0Swp1656Lr4Y-*lC#7x8WE4Q14MF!Zq&O8BRU->pv{{Z)9 zq!6$zK}`qu2MIR~xLLInT-s=i{rLqfXIk|OdSVT$Ru}w$KdU2IRB^NWc!QcB5^t}z z=ik4-asCsAPBY@17^X;E=CuQ<+#Cuq78)qp5U%PRk$w>Ls4jnrK$(|XpiC^_jUb3X zC~d=P#u_o>4b6xFXGT_lKq zd=RX)Lny+G?AM2UU(*7}P-W)GhxjvHPq+gFQu-Z-BI98EojV7@#*G~|t5wTkn|F$G z7Ha{pk=n8YIMOcG-Y|5y?$M6V2~sZVpk1oWq+&PkLxu;mG>ZTEv|=6+zkiN8umywf z2g+&C{tlLD(VwDO^K9fVT{D$AgmEyF#Q8ze+{7faAZ3eA(kS^(K*Td9>lL1FiA*^(t^LnJ?odhWq)k62lSej@xs8 zK>;tZpD(lUW_H}K(WZ=yCtA?WliB0OHKJyiMpo!UBC0iSSbr8SM9GS7Px#k-@>E~ex<_&ZCI;~VeN?+)~ebZXr*fKhit$H2L~Q zW9yfm1BcC=Im{fsWbVqPQH$0^uaAl{TsxO~AlLMV?^Q3)y6vmANF8>yt2t^>^!!EP zOBc;u5x&L{KYZBMfo`6y>w0_Kto=Rr;_=K3OXz^Gdd*D>Viw1&FfYwaUb)ll{J&PL z-erkd8M8LVbZ^Fs8Ar^c(=YYSb^Ctv4HnXC4n~TF@x7;fa>Fya6&;uLSv)MF<;>nA z$2DQKT-Rnto>+OoaONowYxqRB;zNf0K3=e<1*e!NPNk_YUkc&_#2 z0s5*isT8vDfI|CI`&?WluappLEj%q@jSqrOO*IrFOJ6{5Xljpqr-b;x6tY4Z ziHS$|p~lAJ=PqXRaf<*k|rspxQgrWL!2)T-+;o1M#NUuP@x@EJBr zFNs2DF?tZsTCk;U;IKH3eaW>3k=yWCyv3*AVoP)RGtMd9M_8o?Dkx0e#aRHhL)s7R zO$}g4$xIeD!`ZMIb~R!74@~_DHF%LXN=9wHtv##h!#_<;Nz^^uyRA3sR-yu6svoN*@NLCcMG)dbMnHJ z8*Ud5Z_dcD?AQ@^@Dwnob8XI<+npYlz0b5OZdckabMsyH!-h{E(AU&+SJ#`J%vZba z9yH1{W#P;@bIfz*Oj|g~ZN$(m`-WJQmBI4!(<49ico+1}7|`cttsL(R52LypXT061 z_ANX4cW-38-|^)0a|M^~8y%_Bc>;c?YcatS{7%;^$L)pj$7&dV@Lz=U$NL!S_?|47 z8a89{%zu18nhD1#sv2FjV01a250deD6%w|CU z)Ll=qGJyU6;+po5e}5CVH8x>wB1lbfMau#7!ds-&C!!RVXHAh5_ZRwNP0<%CiN4qr z))aMIQ-565>ZV)X{FHSdJB8|H6AzX1l}-Ly1LLjk`Ue5fI6(fs^Pv;hdON_N-MTr_U6BQ z)T>b~r8BdB^(#oGelvMHXZr#+$gvjmx!sK!c&59lhh zN`LZ7+6QQV6#t$gO8b-4HR-F;jrdtOYo(G2v!haiSn=+_8i23G@4F}J0klaeEbyqa z;JkEW$Ee{1e*R;;N%ng)l=(8>HwO#yYGn&2+FFAG%!+6Eu{~x`_hDq~&Yfqre*SoF z##l28lBQ3YI5T9Pbt74e5qM23K*lgpb*zNPO`+1>lgg3!{H{38YN$$;P@UHk8Ct+; zY_Cq*7rvWTOaLF-t=E7BvxZsxMi2gvA|&h4XzF&8Y(4-nE$|r(oKaCG3^;k|XHF(# z;M5OYJZjzq^W+YLMs*kV1&3E2jN6lDxO)a2_R=PHXqhajs|hAhWW;6>=~|SIy8a4V znl^$OuwSdXs)?RwYmfq$|VR@L#IW~ZUm*0Kt zII9hYvNaG;e1WGQZ`nd=gQ_V?EU1F7d$!~4f|MaB;wy@-)-tWDwX6koUx~9@`UmDG z)Y zQJTs1U=aY))fCKknZli_sHdQX;A?Lqd+V_`O3|8FPu<7MH6E(9nzANPpg%{~;CWpL z&%dlox@eK|Z11ob0cFc|qrj(8oJ21h5;0`fP}^9NwlygwA%oSWWjjIKln&K&;G?3E zq$z0sx+Qq#{(b)Nk!KU$mK2qPmWr!L6T)=H0@>zZz7f+|(S5#M$1Xt($C#BfEk?2x z9}GWxM_Tp;iQ5;OwdN?kacM7r+abpBLGZv^3WR$rzLYytsU2#g=B&*6^r&5ty8(hP z85A*U-W22L_PvMygVOI1D19n*1#@qZfaM1jLO}vpUXZp^X&KDMy5L}{mk2tm-temn z$BsuMCh$uji)|0Cz*s7m!evmZBwREAxrsm|uVeT4HtK+B^Nqlo*iK+m{`iBEHo_a* z2zY`Tju9LjZ2m7a0pGS{tGe@l@qX;{UC{8P%2bc<^_RfADZ2sf&t+sEQka_r`P^(k zD+n;oy*cS@Gx1^8HMzp(r4x7zuhu8s_{m=U-`d6^u9Dfi-M3>s&}ziFK2OlP8BCo% zfOHC8z731a`P}6-8g0IMwI;XceSsVPjb4tU1~^x6)J@TB17@W#A?O=zZ9szgT@B4> z!dsz*5d>wg;Fz_?y@f91Kq@uEMSD?HTf)&pd)LTfC%qtehG_zalQF;}7to5o0kiRs z0IKLfz88xjpahzQuA+Ck;DSDnM!TbswDpIUXm+s@h`JN9le!zowyg$y!)APghiNu1+hSepIK2Pw*> zWgn1>Y!Rjr1jytfK;|8@LVzQfjg$FXT5cdgRI7+Kac8h9a0F}e3cmF<@afmO*N`?q zI>qbYvNFNf52TUkU@AQ(*V%&Ge8Dvqoy$M*Z;asssbL+GQy~cY!oKk@nqguyK1d{| zLg#^1kV_f^T zLFkLga9Sui0_9Q35wv^+*@xn&z zh0U5cc|=&hMQn_4?-2em;4ELodIUwNAWwrg3zx~OaM5qj*ynK*XoJgLC%50V7Tjp< zKiK>=saxx11CE}|ugLb68{knBJd#i#(y{=q$HKOHRBiR>8xVmU_{KNNSv~(ljihB) ziF>-8#-W8d49aX!Y!)MlMQ~^fAyu5-RMQsiLW>A}#htj;Zz>3QHsg<6tG&h6`4BI!CLpS?`j{5p)#U{kYYRk&R?;uR ze#*`ychzlLNhUWX8PUCne+NCG7m;EWV0zYGxUeKWgA$4AH^H{PFK7jw*tc6e?l_ju zo$6d*)1{pv=IRx0T8PHL)K9acE+IGbK_U7B zO99_Twfx>TrSubNpc#E^(2PEk{>$hCnk_qw*8doN_;MKzA+?a{7A-<2aaGl!&M(O< zU;;u&U@jICoYaH_=AS}>lR`)U`cmncB)^6~bwL@*_Z64<4I8z_Jwn)@Xq$PqF4U_n za6bVkN6-H{G}C};*3dF<#Akcs!vu@=tYFbXprEm6&uUH}c&)PbTDEu%bQSHjZ1I{X zr(jJX3}xW&6$gVDI6T7ms}YR9sLKSx4&x5UhRLH_Z^CD?EDyC5)jbv0#^2o0A1*{= zlcEu_9LaW)TYde_>#4&$p}lQEF!T*3mjJ4Z6tp!1vXW zed%Y71(o1=ZO<&R2i9h-QXG40@+MJ`NA;WxVVZA6mX1xw7H#-t;pD=Fa~` z_1keuou9$u%+MBp87~vH@gQo4&LOo6`)Q}7#t3gPQ~`_0mzixZRTdyOGu*nzq*!?2 z?$A(fu>_cc&DOG4GL%WNO_c^vCJ8)7DW?nUD&X>7g4-n9j@ zPFhaPN}f92H17AQy=R$c^$K1P;1&=ZvspNuZ~lFIhDll#zcPM{iR$giv9x`Mwx7eg zHt^*z5T||K902v=5U3Y*>JHYZ7i0U*uI|x0K0W1wRnf5lPxrdU z)2(o>n5TPP@N|{+R*3zBuX?tpE?@>UlbK%nuDf`2?fTsob`co6H~f`ZOFS$5HT$45 zRUV&}uOBk2ZMe@e{FM9uAXgYk;?%iK6_ZXA1Q12?ZFB$7v|Q z9RWsUJ%;nD-}wLBpu5(;yuJ)(wF7y4CqME&Gh*+UD_Z)TBb_XCb!P z{H=8n($lE(Ct?fZ53LLC+AJ6ktyQVZe1cjI?hzqG@nD{^uR0sP0GToH$e18JGMWjG zjOy~)!y8ieSg1=sL_pioiV8V$FddyJTT`MWpy^Ii5LQC z0235Cjj0`YlIX!Wr651Sep6P=k({52Q&_c3`A_0h{I+fJN$?V4V_@8o0Bcf72~jr4 ziX$(T`hb7^8n-<=x9tIoXSL~geXyqtThZmqkPa54T=>Hz^CjZ)HN z=$U>^&gY*$uG<>DEpi(zmrvMp-J(fhQzy=7)ti>NNG``ylY*=5p6y+8Hlc~=NVmdr zsL>M1#LiSXZo?qR8ClzjrcD?90AaG#*gwcT((`()g%&>jpdS!6o6DBBkMt@IILc4-+z3c%KNfl~%MOconUN zP;)c}Z#u_3(qND)iUnh$3~ zXqirAulQB-?4av$-6|}Swm|S^VXng6%ykC0SR7&0n1SZ)IPdE2^@M7}AJ&19d|}gK zBSGyEbxk2CiG$GhZ$b5GsD27)>GgO@Z3ThZ=vUM*95Z?}yM)i__+vEArw9m~2%LE^ z+MW{$th61e`wOxz@dQFo9c&$m^f5AT-60`_lD~nCOM=LAW~o6--$wt9*OmWdma2O7 zoZ1m2IB@CxwfvYepO9gW{FtH_#MYmhgYY#kmBV$Rn<+Pi#M!2!@Y}6GGt`Dx(X2@7 zz=|Yw6};B!J;JqZx0@s)?+~{Kbv_D5AzB*qFWZT_5>^vcXt~tlu(WqIeQ0r58n_g_ zsqu``We$ae3Q0#W2%m_M3#Di+O zhvGrS#;l%>{i6EVf7E?deC(N{?yL3y(s?|pr&F&zmiM!I`*}Tklua+>j%er<-3L?*|sGtU5?*B%VjjX0zi(B66rFY62pE}&~%tu{-H0qkCDFKL@ zDC7A=z518BlIr0!qNK93Abr3nb2ujCZs^oh!0I}$p;{WLPd0Fmais)!=#?s;We@6p z0}d=c>JV`gKSSum2;8j?aVLw+Ly@8AjN7qx9U%%h4?2w-AU*jpdxr7@(HX*LoBnu> zr+mT2EK>=G(i_?Ia6#t`b{H*i%bC&r0>Co?>xHeNC&ZJHi^sem*P}9CqI#2fDi+dR z4{#&zVh5!nR|xzd1Q&A>SQT;sC4+%9Dv4w!2|V-^o=Fu@}xi5o;)zH+lu6wQX<)90d-Ht z_%CMK2||xs|A}WK-ZD_2TWn;mT9Y{_Sa(CAxQ+G2?P}q}-zfur=KT6dd)86cWJorP z)959ZN7f>sF^{m$r*b8%a>WV`tZi{heKfR6FkM)v&e{-rc$by}e?x(pYQv8}j;Veh zCMR@x(AJ?2nkGZi&zmr8QExZRbgc{4B`RWI^k*>9eS8T-#0xM8ze=S6cmvc7Djfo> z_W#i@OuzCx0!n4}>+{%z%N9-K(AG{9E@(Oia7R7XlvMcMH>D-vCb}8ln1l7$M&~Z^SH~-(FHuksl-#B&K z4pZ9pZO1m6Hy*zneb4Rw<%M&OS&q%wK5e3D!qjQ~=9nEPbfe|Akfg+IDO*sj@=C54 zl-sa+n~uaDUwzz&CP_J-R~J144;}>G#J$9R|80+Hwp~vM*xWbilD% zvYnj(ISx@g@A4};mItytoBPvY;R&oVo?GXFZQm2O@9!jE{;XtpfbnmtMh@OGJ@C$g zJl4y5NV7J%LzyE|Vct>uFT_UzVWkwNby(75(|;^!LSRXg{kJ8Jq|e`SC?nhSqbwP8 zXk7kGv-E`RCyhj52uR@<*2WhGMc|qj8y3OU@Ut>rwiz#hY&A@ftvZ5iHB4lCT>|b8 z>htoBlDR`xK?rp`Lckowv_FBsy3wZ#t&mA1i>iZ&3UPSLsPmt=rX^sM5{3yC(?nWp z>Qo(aT7MQL?iI&DSja;;3M4SBPzeJBfxjXOl?W6s&#?q|KS-v+G^9Lpvz9KfO_KP8 z*4B5o_3Cb^#s*gazQbpZltgJt-N7E_&kraN^1RyqB5y(o#@&km z4Qp9pl{N2?M-x6bP{A2+fFgpA=eoK~$9EShPxUA)PRM?*`a|62_3CIrf$vdq)P4K= znU(V8$My-WQKL`d&Yd}lA3o%Sjx|@}tK_wCV3~-cX-$STuKW%O@ah0m*}Z)$3*Bb5 zDKY}nsf_V(uqIuH#4HXI^jxpHf;L%O&?f6s2OKx_J<`$l7*7ptv)Vvl^_N+9(BkJ&2`0kxUuL%W% z%UL45+R@S}KejiOkx#FD*@4Y+$g!!bc@zf2UL|Ul32)G-#KbovAI6-vp8BObbC%q2V@{8^WgoZf+m&?evgywjXIsXb zSL^eVvoGE-ou7PYSgLu~;7%KBy0vYyXu&WG>%43p>d?ywN>Mu+H)y)At@b{r;uy%1IrDV`D_(tK96nF8Ve);$up-EoB6QYxwiQ&*j+4whNG^b1Pj!m*13S3 zkw%gYWq)~pq6YK!@_iUhSI8o;FRDmO=i!`2vrLpBqpAK7E@w zj+R2}$aWbB$a!kF1(4i5!p89{Eit2FnLJE0K1wHNH2ki&zie=Vl5@j`%vzAb7{KclatuiYvL2gOFmefzQ1x4)#eW*PqA{@q)d>2l1z52jT^{ zr5cnb(vO#9*%(S6ljePkoyc?24rAWxcgZ(9)gOR`qhgLtfWCH&q> zK*}f!T<#L&WMfBNYtRbS2zNbe`wkggSGb6~!bO}J)m4oZA1Xh9LL289=ssFNstAW83~EWD*wIjcCcp47M&1MzJZM|i#fNngsZdFkt(YH;B* z5o-@iQ_*Z2##sxtxf71*FzR-fND&yJ^)veT(6aS0UAFR6XB4t2z?#@OZJ@&JY9+V^ zfDyLD!V59jynYi_Ul$>?^h3iGQ0&1_5^EG^000Lh-F2;evwqGl?2KZQr*?vd0zaQbqc!%D#C6aAwN}i zgS<^keI|!}W#OJf^^M4o*=-}>rh}dW_@sKFu_)Dntf1yG_&I)vp`s=z1`LhysDe@# zYgVy0TC^w&Cg%YQTRvi6%I6ZEp!TN*l#F?t)S+Z{}Ew2-{S(b{DiEX8z>&J8c#{$TGl0h9jqmgBlC7V}y9fY%9n{HtO08 z{IhF9UNM(veq=@bvCgp>yC^c`McB$PuC`!XJMnlvOmWNQIXZR)y9>F{hEMDrFU03O zDt1+%rMw6$fn?uPXe?0s3dJ)o1Q(;kUbzu8$Cptl7>DKKH=amD=$D=#&Jdr4m5Lo{ z7uILgX!GdNL##R2rZ%hj@V>e=@CEotM#TPv$w=?4sik+y7$1!cLKPSI2uu5s=_u?N zu2NSg(m{f%G+HXkBQ__g-W)Wtuq&m~0RR2~Xz;xW3rDY8Wan1E(fmf#bXG=5*V%$K z3x@r|t_+Na9moTsD5M~5=MBWEog+@|L~&|C;I?B;Xa#rtr1B*Q-)SB5z-Eu4wQK`o z8%s?UK_8&fH)M`fI83BXhDX#6Zd=k8LoRi40+FM3XI{;ZRqLw#i^hCc>JHDTUpp56 zhkXlI1Zg3YmPZ!~cAIC3<82i!CSOi8CkhE(R#S!P^>jbn&Uf$ehxi%dUb8s_STS5! z*PvVSQ5m5;B2pVep>82_sQiLg+hBOqw6UI7o9Eq<{|ajU;|{D|h?%G9Yi#Uve!&BS zmoA!D_*RG2m}6-4@UfnGu4DEOn6pWprTi*iJdyP#*32XH9%+L!E}7Ugbt#+&^-MS6 z=$JO9w*Pmm;1wKj{`HTTjUXNZcD(SwHmw=U*UcCiGOp)TTDm_ulnGRo03&$VoVw?c zh^b-Iepg}$jELfmj!%_6diB8^L6c;lOTxqfJkIeGLuL+U4auc7$K&_y+#DAdw|*0A zT*VcJM*&~g?TFg7`T)9vMm>QC%6m_&X5oe_ETIKUy5zbyu)V*QQ_wc}@_?u!UBbLfBK?xZ2!r2=`bDCM2%SOT>n{5oUIkg)7|P4ohj7 zZ3J=#2}V@vIP|d{M2LcB1uk?52xdIx)e~{#k}s>C|3FP?_JUXU_LFke`ZttnY_z(# zg#v|g@Xz`#fW@>!yKW*i8Hp4~4Lt=Bw$k53*h(P6vKz(CO%cE<2J`~>+mwDJyp!*3nH|1=`W|4%&q=}l?A$jd zzM0pOJ%Z1{o8#Q)!fTys)e7$9iNYRc@@%eVM)*{xl!3|6-w)6?$QG7Rzfort?AF)p z-!gD@+t&@SdIH&uU8gjXuot?Km3TlmUS%mtWab7Vsspd?8Pw{i^tyw-IS*6L7?_)P zp{85NEGt|OOIbjMpheY(G*I}OyDh!z*^(NtXqDB;JefieD$wwKK*RTG`U~Mg$#)bg zVx0^TdUZ{NK2M0yaeUuU1BQzqzmiKV1zzQ1gVM@UofiyE&ae=%QA?Cxd@0<={=7@e zY$um+te>Idh(uPj*iI2!GZdo8f};i#@#RjkIIXxJ0;r)Xh>eF0XCL#h#!nC_FN;{{ zl%%aW8z5nBPLzckS(eE0OZ>lc{6O_y&07hzD0OLvlX8*?E!+aV~cNC^Gxin?JM|nJl%FLHe_S^w*A-JuDjGPw|&`e;#vv8m;`IN8qy)g|0+fIkh+@|9ShcLo*0G)dTy)J596W%p<2@-w z=bJiSAOcvF3(oDkkzoOhQTnYCQ>zZIt2;ZcM+O{WLkYVBaio!#5y5NlF-lpUv^3F- zMI2jeZO(ScoA^2VzjQ;a!|Zt_9qP*53H7El4r^{)s+*ZN?a`!Xyd=Bl%B$%5+lJYH z)oo@c)_z4c^s3j!NZr=@$u%>)|Kbl^pXgv(^mNzzw6{r5jjMFE*78zoYM34QB`CyM z?H}E6SN=?M@S?^*qN~KQmvQHfe6VvdiEQdWmM`)`s%oQ^#I;vg}I^r+RBS?So?P9%A;r| zVGXV&;<+`Uq&X1=mV_Mw?ID8jzF!o(eAVu=;#mMM*AA2n!>K8EkDUIYO%$+>-$e@0 zvh|t|fm)eM@SzV+od!|uApfKqZUcrao!2=Y94Ut!ITef&=ouB8}JKq zKCKW&!0kxSSM_RFDr3IJLD}^`me;+fc|otU!tjKRg@1pggri5lC$Po^R~LupSdN7! zg@u}?P6_K54mi%ayMjZ}TV32Uhu*)feLI*`0a)1ZIn&c?y;S+A1j*($0$ty}h z)Vo`wAK-0jK1&i{4ZP>5I-|J)a;l7fb<#ROyIA?K!MSP`=7M}_H4M3+y(H0`)B!KE zRmiiJxMM4E&+2r~Hbuo8QK}EcbbW2j$+UeZ4bt9}EyAlad*+^zDP{?|S8}>$4-X)# z*dHFt_mcz_sH7O-s7=dy}B(-&<|}k+njTe636!CJ-U(2uE$f zKWkk@Kdg0}eHy&eNjrs4wfGX4(%Fm>Z-&-cBOmF3Z9aVJ@^FlQft8RC{5*7O3^Lr;FUjiekPZ7@Cy8#^p9ygKnEJ`PD?op zTK^KT0-quXt~+S`{izcY4}wqKnZIfAUtNKC<#mkH1+-Bz=5ZcRu@?>8^hcj1OG``UeJ|8}t#E zI&W?(gs}cl5k3y z3tGvgxU^#yHCouEgrFB~AZM>;2)h(s1P%0m$M^;mhg_Rw$s36vA3^i{ry6Cm#I%V3 z^TkonV7S z-K+vk|5~q(;W{hctWgc$N$j|iB14O3IlK1QmaLt|v~5YLV7xY=l>(u*nlr$JdXhh@d2sOd?sXIxNQ2K z_l0jH?~MCwnhs_wABy1ai^95uJAmV^WH1tItI@Le$xS#}o=z-0aOF`fvonZ9o4{Ee zCib3(BV>L@YS40HNM+=@r%>m~FrL!>qK)xlrSfDxx9irj%6#LG3u5C%1lLq`+?fDH zwn2CGzynGNG<-q&wzWrRqfA9?CEp-?fjSXc?;}`?W+Y* zbhNd{QTK!A7^<^guav&NNH4Wx4QZ+G_zbZM9!tw3^a871N?+q1Kum}LKb<;bsmWZ5 zcHwlh!#}QytAvLZJDUNP_u_VMebty(hz_z7N%JNo`>|>=6S{pP>H_$cTkUR&!M&xY zI;jwD7C74nxF3=VrVGNjtDBG?SJ;Y%=m#ygjh4ELz1NK2PvPcmdjdlTg!SqoY%LR~%>}M10>*|K{iT1pP?!O*@y{XfM@S*k`WKDy%!AtFRR^z`P z;4^f(Jq(+b;ZR)H(Ei3Ij$kZ~3m;BPUS14drq`gFIV!n8hC9Ay|?en;>gLd92uCvfJ8EwmAW z?Iv;u9?+h9A{K#~7LbE49%;FDaDMn8d~|}|^K#Y*aWXEFrGn-YN73=J?-Aa6dVlla z8h*jBII6gaY(KMqU)ru+$%wv{VUpDBq{zx>y?#&h0V)G`M59HIHRcH-dZ<*u0-=b6 zf5URA+?zC{F4)@_RG&!dft<${6JIssl^4v0pmln!WYhtr4bv5l#bZy^3v?M);f;_G zYA%t**~lhTg+H^A5ed~yi-htiWKTsR6fNsVL})VlI~TIEZi6v|QUM}~GuYE8_*{u5 z3rHrNxjSGz*f4-K18(PQ3CSbab6WlmKtVnhYozDk5n#$|!E}vlw}0c0{S%9%$Fe^j zHRg}mbeNUilV4t~t7To|e?6En6Xox#o~%2(#qfZ=Abe9(HWcOO+xrMNV|T0AVhN(U zp4c7(!^$PfI1wWSApEz#n;F*KS z#m%RZ5AIYfNN08AHCQ`VSqm$yjDA&(X41!tp(93g3ibBxl(=u-#YB)2L{=cngAIs? zEyVgJLacA31?Hyu>uXM=?ZvXeiguJMDHOvwH8_yRv{VK`?ZpTRBwr%eh(kYV=*;29 z32g@s>^Ga6n9g<6zSu)+vTJT|r4{dy;URwAduv1_7z%7UkeS)M`|+ z5Mg-HyE^MB4QU#m$V*U9cZ_>L)06dfE#}J^5s1y~C-~K`*+G5i?5*DtLnm|syyB_b z@MNrNSa)*CxeL^?gG}v+JmcDv}lOL0=JMpU&i(4D_ojwHwAUFLqtummD81PoaR!OJ&{ z6O=$dB?33c6SWu~6+rfCZrq*4)4ngJ)^||1=J3HXzxM-U{#^tT+40o{3&B_b6flrv zt6_xyj<7CpbUv$@%8yn;00eLE%2P)-vNakrU{H5U_w9qOjz$^L8C~BJ@i0il=>G=+ zN(Tte%16FbLl8KhTtf}5jIDQ~#s#<qur z6S~5Nw?@95dZQ4rztdUKJmJVROqL79<~yZlrtM1J4Re4wh5U(utvYpYhe(c>rj`tEccUy&JViY&1*2SIZA=+PWHsC!1I>FKPm0MM)-AmQT{IGad~V3 zRdOJa*KhKVqSh^!Una*si~pLRoMUu}D9;^U=MTot7>3-yN%=OEaQ52h`%rR?U`BT2 z?#2Zxl2)#?WX#<#YaP~5@YmN`{Hd_8;8$wziqX7^bh2L?G{Q?RBM*Psaejx5Z(ufR z0S7hirkLA_^`+<~<0KqX&-(P}eBt3VVJ=)vvZg28I*hF##Gp?Y)C zoT=kT7`6O?k|2K%DuB%h8@tDH^N%1Z%kvj3E2$9;cIpDUN+H+)G%SKz=Miw*R*N&Y zTzP8!N+RB1jc)uEmkh5#X}nm#!}D>3xUcZQN=QDkSKOtFGW~&Zj3`s!@rMi52P6{V zF{-B{RA3*Yz7@{bF|enhbE_VV$#l0eMwD(+Cn_P9u*!_X%$%AzYHpy(*I{RtWL zo4WjYRQ`Khs?KbdTI?ZMNQJ{%2qP?u zBm?KAz{qY=m!{$w!7Nf&Tig(8i^#v#7B_UYg%`fv5&jnBl>0cF)9|7!>ahqDB5-L6 zVJFrEg=uREAdCE~T>dHiAsdwtDG-&5qUaWuIMlO@kk31809lPX<>8f1qlxy8AxaQa ztd4tfm9Y0XH4E|1yTw_0{!%4cYJ}&?V+ewXBv`jCTE16gLkU-=AzlBK36))#3H9z0 zGNGFGsSwr#nNXK^zZKU>4Z=gAWf8hchHiLs7)u(pr4v-($}Lq;4xKfFf@H&?JU@Z0 zsRN*V7_|Ze26DC>$l1hvAg+Rl8;I7W^I38eHW-OH%%Fp?HFc<&;2Aq#( z#;E0*BUKT!ZsF6{VbCBmH3s5ul%$i_=Z?H&&hVhut7QwSWhY>It!T+u@+mx+y5Gc# zupDzNsD~GeELud)Ba0S&c%erKB5G~%m2~&eKvXvL5&^>o3%vYiY8gck?f*z$pSDRS z+9RceLq-xb8ytH^0qXC0iKuafI_x2K2aNI8^GmUQKW4&_OmZZe6wkIbkyoWrKW~Dx zJLl@6tEE@V8)>QS@Lrwoo!rUtZLmjKvI1mU%u4`6N@QbaS$+n46ZQGsl_ySS zK6-^-Z$T~#) z)2mP6#msZ1X{^ZPoQb&|*e|9g(og)xgi4cYPY*KBk*0r~eSgY}p6muLKoE2uPAHEIHeVh3yPQ+xISnKgT%!97_Cse6jLe-B(3dIxpRDlA7}o zSY_pZBp}K{DIdf4=Y(so*t;ETJxb#<0;%dp598@8;xs(|uuU zef~5Chbs%Ic?g-)!}f+PG9nOWywZkSCQ_eY$?~&jsasdl23#Ox9#J1?u`h{OlR`}3 zY`-9=KTdvM{#2b|veAhLD?zoXT%Mpsd7^W{9kko)kb(IE_N4@ZRJxz|@N-^NDK5^+ zc7*@MYOUY1V*lcUh{Wp8RY*gHFH$CocL} zHJBl?a>EyK7_!956r|h50=_Say7~X`?zkKp1!DCGUIYWn39$^Xqc6kZv6S~rG;{)= ziI2jZiH1%dKFY>&96nx8jE!xO7(#vO5GaCn5cL!vt+yz_M=R|3xrhG)S(Ffvg((q! zK)tHgoZ=H{Je<5|<+d%37k}CI_IKEs2o#_sEXJwpZy=Y9hOd8OlpcP@mz~0c;aFMl zWk=K+*iBEx+Ttt5Q5O*aiMh8Rn`j+HQgM6Hh@XslV!_`&Jo|JC={st2Az`61_b14{ z4aRr4!Q@~qoI)j*3r-Ka!A;^k-AmTWtUNWMRL7`>s!q5l6ca8A=q2vOIt4BY%>DP3 z8RuX^)5wnGy;wJp zf#jX>XS9S}NH2w7&@+oh06wR3Te5s378rY|=?EFu!-kGB1MZ8rmVl%qt~R_LPrMn< z56Jn3dUiuxzCkvLNJ;A31&R@l4o+|lZO8p!ej26N3i61nv8d7hj2BmQ4vR;m9CfXT zrBr@0a+5IymnC|(Rc4y<0^T}aFL0b>L^0NS4+z1=TTu6=qz_kx+F34W1&KCH_Iydz z&*)r2x5w%>_88v5apfV6vkvYz$^4IHi8Jc$Z9;DE<%Iab?$)&Bed)pzc z8riz{Y2LDC^!2Ky>)9vIZQtQ|;?%xPTdbRocZ|de_(k))(imzs3^TMm|+4xI)xAWWTs3K|bjZ z2~Qw_Yt9*AQrapHF-jCQkGR3VqrP@-LbP%X6?Uh*R;Dne`Hr4)FK0{v}G(IAN>z|U842?yB+Mj zSmi-bb>3F|7!MnMIX_Nx-VA)w3w2gyYHCWviyBa8tZxOKZ!mwk9-Rg1B&Jnx1|^pS zHorEt))IL>jTK%Mu?oc@u`dpjv#R_E>J3&^1RErM zg8|eh3LB!_;R9-8sCU&f@Te7qGeYoOq)6n_4&aTTG?kgJwxF6|!QB80E)u4V!7aE? zU;M3_5$bIad#KlI!WvPdC{7$vBs~#QY$^kKKEPN1H|Y)qUZ zAV?<$YG3o%73zcq%TDTf1Ut7d>7^vAhtu-9K62b*iFHBEJtou?brjVgF5^=S<{$FMvJYUL9p)?02RIDRH^43*)MB~`L0{d3!0k75rp-9$ z^7p^}UVwOX0if7L%B!ZR=@^WYSbu>D*WpRBRXC-Af#xn$6UE=FBSK|k?y3uicHfZm zGxDct*U4)ZpVNTV{D(DCvoVD9;nWC9-8ooBgI8S>NHBH->i*K1_OId`s$c}=v+Dn( ze4=gUKIBWtyZh_1f6SIQQT#6a0m)n66M`EGfU_^&}I4d$vYf&>S zL2IGqI~SG#?}*w!D|eSLoRleiA|mzpH^~K;(MxeT8NYE}5ep+pHL*El@@QIO9gz=A z*)wvx&(*}Jz0}l@^y%ENnx)&)-s=bWG&=mGH)4s;97|gb8yYNorUIeI)uhCH>d4Bo z@}ExRP-_qo-Z*`l46hKPk253mPrijAKAwL z=mJ}cd%7+V(#~^*($2Gm($1$s+G$kXabVEkpe2Wp|FkzEWJ#+FQ)wqiYcbuuMNRZp z9ZlWx@$MMVvfiq{hhZ#pW^KZ>{YY!LU}lovg|is)-Inf26-u|B&@XMJzJoyplH@n_ zsOwI0LHP`J%lxJ|F5TJt`#e>UT~eAL(iU#DJBWxdF2K<`UQ>}Pz{0?Rv=cuh*;Evp!i`dDbon{;SfwS`Qy(S0)gN6loYREC z<}l-(RmV?ndxK)yGXc=rCv`875I&DO?I+qz-WH)^g43#fC2SY=6O$G$O`b{7(Z|%1AQvPs^*kb=xP~7R;DGW0u85ov(0T--hJ^?sj0|qin3y*uz7Avb3+?r;>lWBS&WXl#>D$ z!9XR{%1W~m*IDsbO@HClH`uuEnm${PSq@#?@#M+1ew~tiev>}UDt(LlT3vd#YSxE( zbtCIHuqr{+GLj%5yQvO3%D2&r%OSVff`|Mqf`Pv3>C8#6_j#AV78XYGxE?0g*~Ghi z;x)GLA%6#-#c%qv=7L`S8q;6`u98tyo&>*lyw$_Pw{p?niW;!y93uX9>t7#JwD4nS zi6|)PG55jOs2PE(tupt29IBhK7saE|&>Daa>)cTFa01mt%s zh^OOP+72V-cp%r21UXIA85j2-RJjjq*(}_I%b~h`%D(3E6e+(6t3g&JuUfE%x^*Uj zOx3xP& zi9J5=r{;8s9jJVc{O?5s^+qd6i28a0b4a?NP&yCJ4bIC3N#C3-NiH^!=E0u1{o`3s@Q{$^8~5z{b>l}&UMi=a5js#pJxUY%IKCx+22RF* zI2KNy1LY~8@ITNxV<_{W=+43|uF0q5r3;rV1fc??AASr?2V`x2H_Bb9>ktfd_Qv>; zn#PLzUlk!lC(X&gC>N$Oxvc5bW$wcy!=f$8+qPStQ{Pk)e@mKMX-NH+LxWzJ(zYgV z-)Xs##Z%&6OY?&I)~-DoOwE6ijOoP_mg5i+aa)BzI)_lU36CXCur z$<;;Y5g2%2%dTCU_B$duy##u1k-S@;Iwz3#zyT6uxw@DxA+Pq}K9S6aqrwtwxl%C5 z-9@Cy^YGt?Z;l4tuxG`}UAZzB8*uAN`lerO%;DtCFAJETBh0DPQbZj8p@F=!5l7ao zM%DXBr|VY$sL*I{#_#20k!WG@1p-_SZpbUtR0Hnu@{+cRM~e!qs~$<+9Buio>@R3u zC3OUIrSAL4KlmJ;7$Yof2f?@#FrN5($sgboTqAH*FYqJbyv!k@WYmjD=MGlx5HV?3 zJzM=@{kpfdwBFhM#xS2@H(yUG6b_}s!|O)I&I9Kx=lUI}pW%Zrz0T0k`emFu_h$wy z$}9gltaWR@VZ5@jU(74M?_4 zpEQ!$ZgY#ihmrvwFa9OP(Te(rW5YPf9Tjn>UOj*RU2gR{p^j`(f zh`p-td>jop_g(@UTL-9w6(Je@k#!*t6Bb(=Sw%nLwzX;FhD`|5a5TwTmsfy}L>=B@ zAO4N`QYY+C>iUpqW_CiUk_U%0pGy#pR{|~Q7Im0OP$6$ocrjiIBq{Js+v&a#g(fc9 z*u5cs{Mer&Gtz5Kp%=|D;YE{n{7Ooe_2K1N(@s!Yg^aWGDLamb%SluM?mq|n0#w1T zaEr#CFN0Jhen)v?e;+CDqAp;&{27NuJe7J8)*0WgJ|-FhZzwP74b&V&t&dddh8LEM zC&QYToyJT24GlUp>$HOUH6+WaUn4S+`ZXXEnxU8mf4hVgEdo3#s1h4%SD>~u*kJ&=d=KbSo;P7U zx{7#eD)q&}WzjC`=S-&HEb$;vbrpNU_e5q(v$@BR%C&m=qLH$AZ_0tBBeY~!GMn2d z?Sb?88xMZ5>ethIo}vQgWv`tBnW52=V=1STP!bn;&NHh#kmm4^p`~jkmSts3Y5HFr zv#8}HdA91psa=l+HddT_J)@Sdpd!IOo+Svp5wl1wUf!4*WdL^Pz{^Q9ajSgPXSJq; z^!9!VAR!&(3f4icPdc9V3E-EHR?X|twId%tUhNVa+o(%ONW&wKFuAazoIYRs>v6=U z;xoLioWl~S^5Weo`zUEixciXGwR`z74^!HnlmpZ)5#P>dU|7UJSZ6+7d;aLI+sG7E znD@6kd6~A-(odtB_KCCl*S`08icRe+Em%H(MY;ugbTpgM@QLA0ATCyiK_Y&$7$2<7 zJ}8<&%3FH-?llaeBL>|ZE>ebMsd z6=s)09fKBxCZHn$HNW$?xM{rD9O?*c$N!VAO{d;HNjdIPk(#%Vc%W$usrMEf7i!sp zIkzG$8A;B*`Ut^MRntBp_=)^m@Dr&Eer8hdRGfqcfW5oqh>!}E-bs9HCBTa5)D>$T z>XKA=MgKSSpidr4)Y(ZrLp}W`kl47lScS&w8VLg0uNP?N)v*$VR#L7^3or9to$=dQ6~ju3;Nk{6Mi(* zWuNG0M*vE>#XH8bB5@Kg(UE%ik{e*)f=a_DWh%Q)t-6Zlgv&Bgu1`Ys={`}k)E=_) zl%pDO6+LWe@s5<;`z_1?WREOFR488p0;qKpKKAbw{zu*lq4HR}^aj|;dZB^Le|o15 zt$-L#p=~w@tJc$7Kxne>LpJbvs*J}Z5=qq7ur>e)Qb%aH+X`QTE}xH3pEJ-?C@cp; zq+f%Yi*x6`G;Q+a$rGj){4R(@8xCZuw6qB)j{ODV(h-<$cIlg)AFJ5gBM4!qan{<6 zb2nSxj!x--`;*M2_RZI{p9uJzW1T4S2doc5Cq7YN#h%Z!P#DlE}G_?SHXa*3%j8x{vtlYOaZrEx2 zF0t5dybLaY9#%e!*VQqIy1*c2;mjW)v9|$~vy;;8bmhI+dSa&ud=lUJ2x7lY)z3}B+vT`YW;*ff_dPDnl zYi((@v-{1VK0|N4nFv?TEC=fS1_+_UbYaJR`o>pQ3X8wjY8!>hj%4+g<=Yl*HwUin zi=-4^iUD+{If{Dbl3zZ&0@>`pPGqh>;9$ZGAQzkmRh7Y*`HebX6uW)N%O&^spZ?X1 zdd5K=PMDiCQdXalGBT= z7Uv9%QL+HZv&M^=|2ZaE(D|r-mU_)1Z9qvw{$gv^c)Cx#=0r;YJ6xm`x(o`xL2$*p zkY{Yb=f_c=xaXFbZ-auWxpAgeNRSLKGfpEhDdBZFQ!}z zXjq<{dFGR!rX3QxG`|&ls3#&=%Eb&ba~Ni<*t_&VGP0Htgki19i-aQR!}ugMOC(@` zz+rltl6Cw{HoX2znOvBsTBL`9l!)f=NwBintT!g63NQ@q0E?Yav|jpy4iLiH*%rN0 z=1II%EVd+&1>MDS{aM*NFtPIG;qjOVd?2O~!FpxyE+Mr`7a*NTzxV%{zaySuMe*<> zmYVAk{!QWEeov)dV_^i9&F@_-*NoqfV~?bWHr#&*t`EQ+WteSC_6wT|#=F6VwFi(u zO=&1y$AR&KwRgbsO$ZLnGzV@N0A*)nRXv8iY!dT7_38_f5v!TNDf-Hs{`L?G#+3k` zLp@%3uDK%hIY$n?daO!1iAE7=?FOW^x1e+r+3^4g?CzXwe!~Cwj3mYlsToLWN6ulu ziY?1B7w^C|)rW`hN|mU`3BvD3vm9yKFqo*1E_k5dy(UeaFloa0NgQ=GO2$;`6bAeW zwie~EI9Mv~@qEd}iva?70RU$R8wG0qC{Xix{fLZHr(S1J_eNw``}PsTczv5oG<8nI z*QG9QcsmQcAh;Y!o+;2~!2$BM3`Ua>?~ zkwlb9`0zLCq;LdMd9vzZ+R(QW_q#+LrsAsnO8(oC{%@Ds2g#NQb$=TmBT$z!#2>^3>Rc38OH~yGL=j%}x!Qpm05Jgv)238bX%8c>!9y$Z>GOOl8rgBy z0qwhawh5Yx5`g_zfrmqO97!&`{KEd?@umaM!2*t0wJm+e;$3jfH-W+S{V)bM&)VeL zWggGsmK|7pbm2*}c9Q=rmRPU`3?&Uja4K~GcjE-_DTEDrHiGACU<=ed79LYIS@6=G zi}s1>chSs_Q+pzXTp35UZ``zH-3}IvpaUe4Ba;*-|1ksXuGt`#Z8&jn>$S%gh=rB! z=uA}MiZ2Qugn;_8@Lk)Nq^i#70W^)o} z_L(ve@7203rQ?Xu2KW`eK`P$h$^U$VcdQ;-7Q(Zw3p-}uP7)u)vke_;3~3Z)LAsCP zEBe1o`3_UwYTV;H5AQo*>a;OF*;-vN>}utF{dzZ7X!7pHl=ZI_BNTZ`{wDA&NUszV znvf8kR&7RQurILu8IOr&C3TJ@a(!WWf8z~)Iq;4@UgM<2NM26)7#PBS8`dL3>xflRNwFgN^X~gE?|z}a*U;0x{S8J%tU~!u+*-O}^KQdYL*F+} zXdXKw*jfpC^-O3UlZo`l<3%ejfU)BOevkDuPI|+0k|5{6her^5k)gaDvklxTuD(&P ziWIa9Sc{&C0CNO=RAD6l6YAAH{8c2IDygAZlYeG=s2fV5RqK{#EZz2y2bfNz@7uU_ z*V>IMx25lX#e+?^56N$rQil(O%@5->5@dE6TJBHq7C#Ha;O@eP?lU{0`9upz8(3#- zU@(u1qS9*;{|Ro9C-3oO7PbtLnG5#Awc@F^tQs32$>YhU_3O95|0odtM^MU8*T>*{ z$Fgp48@*pBV#0n473c^x4JQH`!Ey?=I0MC32H=zkeJF5i7{0iGi3?$k`%Cf=aFA#K zvzTnH81O%=PNC*0#uTNZ4054yF5wmBd>3I&Kk0^leQL#O7Q5rPHoUs(R#kJuPt4WI zMfg|n;08R!2T@DT9f5ks%4!)>D<2Vm|C30@@P|L{Yk%C&FOqHV4rS(mY!T&}!2E-K z`GxPnng!V_RDMh@2rmE_Q%;H>+R!|z{m{OBN8#%&!~*3L|w%j?(}a z@>H}s<;UEA8}Ez%{(}I>!5W&n9>Wv8_aoR@fzTh25V%DvFf~!;xcg z^3B72J9bL!Q%}TW%K4<89WkF^QVAo?dn->K+n)U#fm_#)qLWdalV8sQTJu{bhf=2r zXq4P}sMSrl#Zzk~u>LwJvlZ-OU9G%>42FdaRM1D({vsNbbexT{C&sDv8X6Z`x$n@* z!EhmDvRId+^LtbH__JEUfJ<3hsOs2$@qlqSRU8TLC*OWEi3#trH|a76s2)~QTOLDQ zR^TPasY`i$Pp3Jgviz<*)M2HNI0R=8p9tf-Rkx2HlXc(!VBtkg4f7EPPF*Skw)mSq zYL!{hTwO20iajnQkzyBoGs@4jgH;&}tI)G-ha3gDZKw!Q0Qw2|it#HdjNx4lp^s=o zACa0blfp``@F&8$YGNrla7vG9?PpP|>))ggn}(gDz~O&A^+?3Xvc59WHhd74eI5CJ zBx3S$@71(W-kK{?(vta0mRdwj{czX03tO@r`5C#OJ`6`tALGhdk*5y8$2wjTk$u1x zd*gGdX+Pn=1}Q0vlNTi~28>g|bXnv|v08=|=NDhQYbn3bz}vLsX6n|OJVNdLh-ejI zyM%E~ml{xa&!irH7y4l72S(z@Z(M+F4R0=2d zrfiUMhPh^-oC{>G!`hbB+Z;e%U#`Q^}%#Kf*cs9y!bUP<9Scu*^>o??wqu9P|S z;F%33jU~5c!TU#AygYS93YPr^ZwZWiBKdXzg*OPeOWN+2)N=}XsqPlhF6v*=+F!Bi zUxl2m?r3&&SJ+s->$6&v=SVK-U-6enPjf@VO*AWb2^gmGoKNajqh02|Qtx1bJS!yr zHAWePVQB=oZNmL&5tQkOO)6ATf&PDs@N`-#9&du{Roejj9;4QTH&xI$aTj!G?(#-W z3lHZ0x!hijt*I|{oZMB<3Wg0$5dzgPvV#9Sas9(0=IO|<%j^%ewy5n~Mv( z%INxr3Cs6Q-DJIe`yeZJsn@BFhipA}&se?LvUT<5T`SXPOqn0k7#gKW#$3WI8Sqm7eBXx$9oq?4OZ9eHW}^KL@f(sko_ac*dQfYv1;-w{Eh)Dff*X)e!g#Yb_& zK*wO%6|Z^l@gSUp%JZ$J+@rjwS}g5h%JZa;W~gc)T|F$@jl_QF|MJ5ULL)&BlY3x^ z`;Dk&upg!Sq;f0n)tk4nLN)iDY(D$ShT|K}E&xcFI%U#S6;xE=_)E54zsA7AgyS!@ zf(Zz>Uk55#Npo%a;WD%40t26DzK0zSz1Q? zTOJY^&xT=;hxUy`FtFtWF)EL}(8kBArfQlgj{25FIJ1n%qMFq02L8DH;6_B_4M#NI z2t?y;Kr|j4?OH2*;%)yrd_ryA(GIhmu)svK^)F$kA*?)ED2CYHgyo92|D?Zt;D6tq z`PO=gGuGiZe87&2Yu~-SIJ$rTW~0L@G+T=g2zqE*oRP9=!4^uNlULFV8J(<*Ty(Y_ z*`6mLXpe^pr|>{R0|;D%3s4%f7P{tk6f4C{SmJ34}7DB_(nPYG5`5S!d4nSw~K|#&VfP`4Uap3&Hx!e!M%OK4r-VI#0o2H zG?q>iz+|*UEa7|QRT?M~wNxNaj8e~wBxE^gh#3TOzzm$t@&pnC{<(v6=7LbeuzQI0 zqb@7)7vHXctKkhJexX_!3HpSj&4z}KI;CT>{<~*ik6$Q|C?d(aOfC1}VNZ_Z$GQ%hG_zuf@1g6M6 zczJIhWKV_$1XyUK=%?U-kH#KKqt0k#vLvE@0`DwboBVgjV?;z1;m%tMRp0`qONObF zpV$@{Uey9PR}9rLrkExlsN^K}luURJoirW_ZJ@^nv{9bIwa6vM$Sd)h$;1VmGY~iH z7hsJN)TH1r*{B4A2Yok}TDB8rC=KS^D@;nx2goBM$Zivq!V5-RI-r?)rji|a{<|7@ zaeZF5rrQ1X28!zq9taJK? zjYpSVymWN(@DZISHN|q^Gc%r`o{+3}lJcE6ay#v5y-}ARN)xa$V z7fAo6ap$_cNbJvMA^U@J=1}rc5Jv#8MFM)G-wA?9PXhV~Kn^HSkke;!h00HX%Sfri z!VJy2bj#wc3p1&uAG*+$s&JpNXb3_Y_4(Ydj~ux-GUX*i5qx zcO%~u4~~k@R~pzo@!(uM$b1VhLW^bXDE?m7yjdm&HorK+Gvr+95%UDt+Mj4i2dNZ| z11kDlTlE>Q7(Ye5(LOi9ewn)W1nA7`S1W|d+Obz5mH6?OA&3%fi~c;UAuk}LAVdTS z>m-dvpVUT1yEort2T4p&qqU^t)Oi#(qgvhYTa|FlS}X)%a+Pqe8t!@hMQ*&I1ScAG zTTM#$SHjDqqJbA$$1#ypg+>b-reTJ`Tt=P!#oJU0e_08-7x6aPN+sN@hI@FM=Wn2b z8R(_|a^ORhTyfn#3WiS0mKr^vo{{Uz>b4=BE zaaw9B$vzJBEC7jpPgAl_o_WNgxv%Nh+W_CnrSD#{AIo?bC8!N88AbsAZzrz{kPUh= zsDu3=T43z40v=QpBE!2e{Ko(808yg=Ds<=FcoYDIt{DEOsI4%jAJuJ{BOs@tKA#8= zX4Qfqq;DZCeppep4=8}t+8Qn5QhXDrGlBsnX{}_mO^k?QN&%cYWkC0t9jrarR#r)H z3+n3J0$p@51ulX`7|_o4;t)fH(Mz`#Y)(s9@PHAv!(4TyJ|kCbDDe8a~&h z{TsF(I+ zLG8u#2rkfS4A#4-_X6@<;Y!_p&05~-%diJ-Qs1$p-cGIvDo)HmLB+{jmXn1ZMJDMt zB_2aHCaad8&r>IiLEDr@U5;G7eB|)etA`VtG)e5z$fl0f4gd{&`WUU6qSYRAiIzM{ zo;nmh@5t3FN4hj=(xppd;AT$!prGV=$b@Gmz$2Ss`5w4oN|)h1diOUcG~^C_sdA6p zT6TTi?G2Z9A3Lgg0xp3w({W-y&XepbF`lo5J{<|CfD~F$+EzCtM9$Sjj!xT6VMr*P z2wQTEx)dSQ>!mIn#VrSnQI{{c;()UXt)@HJ4eA*L?O_~f zn5VW61Q=IaqAnm^fl_=`VT}T{>3M7@l~4##_xS<|T!Q!cLd3ybLcKo|OwETdhJC|S zi)6*WI{x=ku0S-Uh&3 zL~vlmQW2I(6|r-W1X*VJZYr|1oeSU5mpQE5v*dt4PSI1aU`Nb{1I7wc*wunG0=NJF znp$`Uw5=Fn>**V4)>{+@Q;wKJ{x!n>r$2$P?vtk<{Vi!l9+g%$RxK*kY0f?S^Lo^| z9(IXgFr=4g68X z9L;V^Q^!mkJ9>N_#AXaHf0g@Kb-{}pcl%lyfM@BCH-B4a6Yxq`L?PK(73$bp%;;+n zmu633>uU2g{AZOu6jaY%5NGmBB;++#us6x;pa|;z5aZQ;jPXCjH*;=|v&`)Qv5y4x z!F-1Z)~P*F!U83U%>bCiXMbk72zo;g#Kv4y<$*R5!q&-RUOxllNaW?pc5@aCz=zuh z!_={+9Vh1tf!6ng*Us0KBIEPx_yMx{Q5nQWIj~Yo5NS+3o)E-%W2i0>L*#G}3-54y zBwM4qcT^Ya)sh3D)P)rj>MOLjF7JydIgnn_#rGE}B(G_t=^6 zTNun%7Y=5!@|9P9zUtcLgCETxgvZ=EgW;>kipz^{CuN&MQs(iR-FaYaJ97{VSamh+ zLDCaEIG49;$EyVnG=~}=ue$Qf!54x(kwcDMvS_Gh#yGsY(jVhT{|eOYJA^-KFA=%p z!HZ;M^WWYtTT7k0i{OvxKaU+gWOS|eB5vo>s?!^(Z#kkiF+H4v2sLoJ36bBV>Bl2D%xey2j%dr0d=UAhtZn&tKW ztS7g9u4QFye`MXhdEVSiTk;zN-^WwN_2Z*$$>o`4Eel=E0+*Rv3~Jl0TMNgo%|_I( zX9?a_{Z<>Fj+Y+~&qJFQ9haVYk~R?&D6E1bPTWUzTxIDtu|zYoq0h9FRoNtICLEW0 zCMI@hKB)Rs$BM?A!g2ZV=H0tDAH<>oe!&)bSm0QC%Jx(PayKOpyG$ zfI6=LGxIcAincJz9>a5Yl?X{(ToVzO(&H z=ju)6Hh}!1PTk`hS&U&lwHSz;Weko7XDLg_EtUKbD&nvf;KDb8_9n~1+C;Ypz}_uE z)KXqDuSh-a;a%piifmpk|0F}_pq7XqfFA#&H5k2YOp?!QU{0=$W+FM`_7z1PfVn1SsEy3t2N(vV{v-o$+0`kOkwra3PDM z?pZ65v7$LTwoFa837@xJ!{utwZh(i*ohl@}>s6th zRP&kY0yfrE$N$Z&pyu`D|FSV41L~{jd`O*+Ev81fPH^;aGxzy(#U3mQ z4w*xjPXQsZEcJFJ*+QXOl|o z1j~E`o5fDL%_5A^u&AoQeLgLHc9KNpgPZ#fo`Nfh7u! z&rc%uhnla6BiDkJSiUW72i8uQocya-tvt@mZ7-?sFal2;N?l0y!LwJO+$&~!p7Q9> znd__(E9a9a2J{FgNx^eRK>64DT_iRRT z&)QvsTS7GM08Uns^30{OqYEv00NW8^&m{#Nh`l7+jN`tEy~))>ZO;X?2EzqTS3E3) zd-1A+F?2B3m3fygKX>FMwdMjsqt>OwK1Qui@{_WS+5%Qa6tZRbLa<)?Q6~_ltFdD| zC=ZmRFdp<7zj{11+8c;*-V>J=pmgZGgf?cF(8k==+cvOkaAuvuw7qXxDuipx-m1sY zy?n%;Q`ZV;&$UDZfqPM4Pk8cjlm<;JmK`m45{r(l*`FzQAt#p~Temku^$#)0`uS(= z1mBIw9KIZ3=X9HXl2aqXG5-TtKIUw9wRsGjrS za4hB55!80x6PBjkBDB4)v28^t{V0Z!7NiN-*qrcVj0n{?_}EZ=Tkyp#M)a#)=oD0DznI!oj;)OQ2eP}sjHn!+%J=p+xVEH^m2+J>OA}c;L-%k z=2}bvKJ+7wz<(=|diTOhHfOAX=QVXlVdpJktZtCg*3-uqrW{1A?F5PcK%w9PWN4|# zEc|1h$jx1fm>)>qW&|VLY=Q)j@d#z9L_MyP95~*>y%deDTG9H;s_{C;x5F!3hU@vi z9R^tG_t!tKwb4>dP;As8|CkMkPc)PJvX(^hn~e>D6VrT!*Fbdq_Qksv?nQL`+@90= zjPGwA(6CjvX47Gvc_R7n%KclmuFKf?cX&J)OVfDIJa&L1JRS#WbX$>RZkz&uf?;XW z^*$}Jo7CVy8v5##1L_LxnJ4T;2I&LjN-Q*&t0_uI6@K7(c>(R;B=6aQP!wGe%O>-p zEt-~{jF$5*?BoA9t+>*XZAoA1g?*_9-1YmN8lK^{!+QcZ%`(cjfU?xO77r+KP(p|& z52DU9ae&b8{=q&{DGSm`m_L=W%6vHfTjd)0C7anjWHem^xP#1p#ISTpUbSdd@)|Sh z&T2$`&F+FVg0y)-b}l016u6@^pPd-mVw9Z6;^wWSwO|F*)k1jC8(3k;%XLAOkw4?v zKX6=+QrG%KYooT-Z`Q+2>hLqZ*h0ACd{QR{OWGlRj+XF-aXq(#B-j#W%%dq8fvpCW zL^NqWX+5a(ANV{gp0suXbraMD({xg%5Dv8c4F{GzN{vMTi?TUTq+*6M;IyPQFnS?6 ztL6vZ`<>cf*!56nEX5*t6S08{#0GBHH?W@AK-|Oz*3&mo_`5>VBO-s_i&Nype}^qvzs{&g*Z~RlE^y;*Gi%e$!ZWl2Z8j6~x9!{1H3?#a1u~ zNiVzhDu40#>Q~fh z1o^J6_7yJd5Z**;tHlav5Zh`WBz=m5-y(N{;i8M`eIGI)ULQcQ0B6bm?(@d>~c$5lZ~=bhn4#t=q0q@*UoUv}7kd z-yVLe9JP0|$oS&xkq#gxi)8@6?FzEtbn#Rxx zn8U|>W>@$JNm$D{<&Xk9c&FkIGpOlz0^AUoX&R5k8g?zKVOV!&>93bTPXT-rf)$!a z7m|15@&{y>X&Als0~OgsHl$=M*lcE{b2RT57A{TV#TzuJJQ2w%>=TNJFDk}6Q(eLj zJwW*cjJEvsMG_JR)7Bib-8GJBS7Dl<%73fHW;Vb`2=rFq0$Nc%t6&orK((29#epS9 z7NX_1cy7n3UB-5`_a|GaVis7TJC*B;5Y-~MS`t`i>X@Prg*qi6u#CVoEmksuI=0Yv zDQY_G(u3$v8hG46>RF9+!w4X;ICOB(-GlR5AhmoX{1Wx(Lvj>QQgOd5?z2_WDRHdJ z>c{#lTI~O3wY#zEZGx=YdtX$r%`tl4PT?!G)dk- zjgyd9g9bY&JV^NkaYNoH;%5r<_!$w6vS=mnk{YI~m(gWPOoMU>95bQgsR|`9*!lP) ze)Fnj>U8KhxUihArNff()YVO#y9?oo84Hz{9T=S*u?(UKW7;9+WN(b{ARTVdeFs|T zw}kJ26=jIn&gmTxJ-0Y7S33~>iLVHVW+=J3AjSHZ%`yuje)5kLq7{>^=xU6@vm^Wp zRX1UPWj7bfX0WC`zj`C&7TgIjRy_Ytu%`5gP&DRlV&3USW_G6@SX)sul6aCa3cz(& zM_CRd6X-92vYbMJaf7-MF^0~=7w0`WCn2f=-=W#|h`Iv-`=O?E%uVCiMb00R2|EIKJncLUK+ZcGn~786x%ymau}>=WftV^(SB@1zSfS{KD~D zta(SH-7Ui$*(pstnV_1(jx2*S_%X4=AbGyTj^rZDP?m)DZk!eNTj-^qS$HIUA2M%D zB69{aU>IR#WR$02@H%day7mld#8YMdXAQQZ0Z*3&3kO$HstmWI5L{*lKpqsB>=(To z*c;QaXBM)=uowN|jqGofpV$XPA|Ocq$BI&#H*Vbgu~=uK)#$bFuFPiVFU041#uB77 z34%5-Fwj^KIU(Cce7gC2F3&`ilrK6h*vF#A$A{j>&=WURhV4xMX7RG#c-sKi@+ras zUmo3llFuZpN;3o!bq~f3Un`R;T8HNX=WSSkCc}T`3&d~1G^l#vjNuH19agpfL0YFF zWv;>fvlhB$J8|qB@G!1w=Cpsq8kSWOra} zW-N#KivZr&yToVlnuYkDqK!tF~!&9M?emma)YIOy)5+HMZ8+`8<$uU=^>|v1JVPA zRGlW5*^Smlf8H3plz=)M=*}|2rCmplsxCYTumjd9_0PegiM3n?1Gc0iW;XD- zcCZR~vQv3%t$7ycCH30SGm6sQ^*VEwti12xuldq)}nf)ho_| zkz#I2*8Z~>Swv~mqIh(2lk7sGDxUe*PK7H`wqYYC#+xwR<8@&sJA3Dd6)eedA#bv z;oX>IL_yV2FQ_u9qZpLjP6NWO2Ow%xtGFovn7znOm~I(?0bo=g43@x|H0nAIcN2;F zo~5DIrf$8E?RG_ZV(c@%x2)E72nFDs zso}z;ygldZTacn}!3nViDf$+O6)~(SfSnA}5Qnn}WUa;5v^a&pxc~Y9iOOA@{*h{=<5v3i7<2mv8BRn2DtV-RV z3tx8i7f91;ryWW;o^+O)nq!X+Dqp+1KMYkZ%TSNIgyOT~`UO=Sgyz(fwHJ=>%9f!F zvA5;Fp??G?cmAE*)QhMboBgqPZR+~ujhY`B8`!v0G<8@_5SSLsZyZJU)hC0jPtGt? zLkzJ4y~!a*2|PP!B`nP&;M>{}RecXu?F6N-$qC-W#xn%Lw1gm-mJkF}2xfmqQVJGQ zxK8lCHfdz7Ht3kKek6Hm^0I}?%-ZC8)T_U~9ck-QH!j>{W`49}E*aMILsT1z054AuR%*tx{zzCL99AtoXp^Y+Egb8>X1j? z?Kyi>)UHjwuh_O^yMQ{=r-dX$RUHem+|!krOLzX`x$X?6-$0^5XbFG0YT1FsUZeCyWpWbj~Z8BwaTX3ubSSLT&p7+s$7t<}CsGThpJ zPdF=Qq;56`u9RnYo!oPDUjW0H1&U+pC`008EscOr=Ikt{l0YEOT5)oo&sUgNknpfM zjyYj=q4Ecw(>^>)QD?A=+6?Iq&^ez5%AW8Za+n$^a5#)nLQVgrYzzy8fXr?$;K_)*6o4yt)J=K4c>-TNX~dj_Vj=PQDFW*s=fm(ie&9t zcbOijCc^;3lmkYR0YM}Qn8mDX&N;hA#GGBzDk6xYh$05eIp>@MD3~zk1je;`tRC-w zs&ViAzsKi+nQ^A+?&+?2>%1p`88D1(g<`1=1WRfj?GrI z8y9U^xQ*(($)9!N2T{)-7~HmDaQkKKCdQ8w#mWgipMfdZ3%JeiDoPe=R~dm;wv)u2 zXZ!{MA~k_e0r!YG0#+Ol%A-5+N^@;N+&3q&3Ok=)vxV9(j_TXuqhhFA%x+Pe0z5G= z7zDz(G=}{Kmz7G-;ne7YGT9KJ*hhSPq&Pg%bBoYaoVjP68pGa5 zyyX_8m0sL7=N`9wT)ukgn$)#MvCedujLEuurEj>(BP*5zE?oX|IYFEI^o^A_s|`Iq zUBB|_ZHO8#I&eNeuLI z$2+0}O|`!EakT$Rn%R&}gSFi_&mYdD81d^EpqY8A2IIR**S;p|$Y6_sIdh0V%8|bz zJ%Z=cg8KY_riM>t?$)7ZZDBsTKWX=hts8Bxp4s^Zs0ysj1n+e&Zep+qtHO7eQJFur z0vrGlMGUt98N#8dcZ|SS;m8SWe&K)v)%RqjJxtm5TZe~PWC?G1Rl<`=$JzkSH}Rx4 zn~4As>g|bzAFqluL27gnf5>2QjkLPPSX}w<#q6_SoD7PtF$~ivW&upQ?C(O5q}lvJ z^qDQ|#S5Dyc3<3}{lM(lrQM(}#SNN|8}x(N-x@G8sG(Qe!TifcOjOSaE5~6jg)7|f zNQcG6=Soj#+W%(;G@Ip<(uSdlpokB{fh!+AwzKO)`quA= zGWm*7B#8&|ZMu09N|9~iDeH@3Z7Bbbj^S}-wjcFBSiTK<173Av4SH)F;QD(3{y6da zd&N;MutC5N&ANP<(JWRL|7c>fW}GJSvL#<~7x3|280`7+B_Bcfs0*)oM10AaC1nOa zXSY$D)?xUR-7s-(;I>pbWd`rn77X6sXP{0fO1^%1-+LC!qrI+P<*hJUVAieKiP}-j zul53q>eve`v*F|kmej(7zh*}&d5Q?s+iWOxT0WfkiRI?yC$Fa5Gu^v7Yw`)7latpc4)Y#1GO@jE_<bY}@TLDItSCwaaJ^Cp!lmr?ff;l47jrP)C?Y4b128KEgz)PO42`0u1>uULl=)9auXgL z$ATMbKV{aiTG4BEQv7HnN2%qI8O&78&6&-iPQwTQUwPq9>a-JM{2L`+peGd$-j-9d zlCr5g21Yoy?OL&Uz3s*0n{nI{y6xyc zvK=sHWT6%0?R!popB%WS0csq0U`p(e%=O_=7^%BKy`tW`iNE}S8oH7;Ky8%G+*RF- z<|TL%lkdq4=4)Pn#j5MoDzFP=D|p3&H+dGTw3K@ECR4a`bzl|a05e@rIWKf}>$Y!M zzXLUn9pKWnY9~d&S`U9QbnYt35@zfMX)G##+ zxBMsAEm7}Q#OHxcK*Iy~@8=#U`j88g@rFGD0p)J50bd*#g*B<6W9~_j^LKD?@d%2ssmNMC#(CAXR9{Mn@X?5 z{Q*OrdF(WGn*EEL>W2$<=Y7=yKw?vB?uc(Dnjql#pX#bDn8%8rVr!@_o`O3CBCW^O(yzPaX$gk@;#t*DBs$%-fD7t%zm9hnYWc9yT0)G%|nWMRDO9npO7boPqC5L>+3G!7T zP!EgB*t+#W2Gsvy4<-&C95s=L`8bN@R~!CG9Yri*B$~=$Xw3n+drR%#!5>H6j4WVR z*2OxeuEo8L)fE&=*Hy%zsBEycM;+y716AciETamnE+7h6sB=4FoyOl-<{_<@8d^gw zfhzDXsyjgD>G@cQ;USt3X)nH7+RFiv_OdahguwV%Jr*t!Uw-T)r>LPRMnQZ@X9zId z{(gL)$b>TRgAl@dq!NBcaRYxfl@h#7SihW>H!AIL*8Z+Vo$*ciQJEW*-sksTR;teL*TS};j+5j<_7q=t9f{%A6M(KK?q`6o(be>hEn{g}F^H$499y)b zN;*{ib6WGiv=(+rR1Y6ftTfhJ(|8jR*u$PEe^OH|k}4uG7Oe)U=sxc!Or3nq1leMV z;W4ea(1((~onobqo?Cg23aF5J_az#} zVJ9$5SMr4ocnHvbY5=rnohtCZHL7hZw7*;$Ljx&L)v7S#kXcAowH}PG!ML?}PhF4Bn@-!8=F{-amk^)KK-JX$Y(|-ym`qXBWeO8n!7g{GLdi zK(O%V4bdbDr_Q1aQb5UJq{sYbC5BPkTC9812xvtVx^v5wc{Do$$&k(qfcyGeL6Ki zgGfQCaz|aPnyLK^BICv@CHn_b*V1IHpg?pAsG+T6{d2kM0;~v@{=!`$Wf1e;i zT~=a@*Nbw;1!}m@V!{7HEcgrjk4g@$ODg^PK`w}7Zy(J0F& zcMWnv!r)%sJ+pC_!gviulkYWhXlFhW<^BN`QZ`_5@>MUNT6{EP|9Uw)D|0PQ({nL9 zxR=OJC9ppV4G;R02CQKKZj8pzAq31%{<5ijjBROC&Z(;(2@-Q3llBN2n zBh>lAXvq`v1B{la3)aeiYPnKgM*s}_!3W|LOJ!Y3qNR8tb%08nd#vTRYhX=U29Nh8OO9M)ej zlG+nK1V%d_m?Oad_ZW-;8c-O~)ewnq2L++_zkF3XPteVbbuelz0N@J`U22$2+5}A& zz95~xDK__2n=gw019d*wHX`qwZBY^pw5&VXb&I!uy*M*DbHOSwX7BNcmsP6ss2CP4 z&8Xj^Q+Z1(ajyfZSkfA8pB~iVE~)+m)CzolYhcCmafh)Wi9AB$cO(Zq=sE2DRs?qQ+DznoqhPzyG+r4n0%=PXm64FI6eya zeF+vv?MGvE3Qfv+b_fzGSZzg<`9)nm91?B6Iut72X65X~H#bBA~=v)FdkGm;&aU@n=jg>%>;-+8~h z2t<-`XbZgdtH!59uyGPP?#U4By^m$d6?rmW!s;TPXAf?^k<{rczH^(8a3hB!3|0gv z#z3}f&+OlU$@wYY(vZmMRKEl*envhoU31z;wnZqy2Ykr4EYa%CBeA04J#cr!b!IfM zHKR8fy<8CHewai$z1vSRR_2Kj;w}?Y6WaakNC7S`!$a%aNSSTB#ka`_>pqzxt4KlG zi(+9E0d1yA8g-aWX15&Ev2U*)om&lqlqOW4n{r|G@h$t;@7N|fy}S<@%aK%Q{74u{ ze}D1(6AY=|ejqP5B!2J3^uI|h_XDf=$<)wI^d@vzol-sgsAj|TJQH~iE+}`X{u!B5 zXH2uc9ecKEJ-GHXG?a5w&aXMXW8cQ@JJ%nu#R6S`aPiTz1Qi$Wmt0xgFJ)Cs?4Agxp>E673-$8O`S$EIywyd`P7k&Sx7M}PGz&l791 zv7q{t4-Md^L>wJ+OfSB2?yb1BzWtMyxn%WX6r$%JSjPzWylJDxj~SJS4lI2CY)mzk zJ-}#BZ`{8N9)2!f+5)02|Fi+kl5by^t-?pw7};6vqmQJi5O<9li;q?q!F8ta5`6b` z&c2=aEaFHp)}|1Q>Ybmnem-1L3k4Nf49ugg6Nu4oRe#{SArU-mo)OaqUBJqmc==L6 zcr8Auy1KhihSj4G}gtTnihNnBAwe?2A5* zYyg}I2f&#SoJ!x$u%wVJKEl6Hwg3R9zAy_IMeR3&`ir;-4>mXTV)D%e4>g(4fN|Wt zLkFZq)JVIMd}qOPV`$P`zGx&j))Gyuf|W;)i?j%!uCSCxZOb-_fcnPVaP%5fOujP7 zII!f{DQ}@*DBGwK*Nrkq>(8VfUA=en`c-SPSFN{&CB_KRh6NXa8so5#EW(NhEfY%h zuR-U!PejYsWf~r?W$C#8yN|0sBVvy23;o*_*RQ_yW~D=NIhBlp*6 zC8`F1-3L(Q5Q_@+L2dR*nw~H|ag?%zq+~40G&=I!Xm(4QkvMT|;&|IX8kHY{)U|Ei0E|A$vAyc-aHRrwlK2{=OZowt_edaIPaVb9tmujUY)TA) zZLDw>=v*F1>}bm_0@o(YMFrGl1h~i*`71F=-@+tak2+#WTtM|Xcs&xY z`-|iRNv%})-@F7Kboe%3$ttIEG2;7Wm1I-*G7t@{pRa zXdm+pJn;;5QIt}p0!BW(Qpn7P8~ggTZ{MpgEY^0PJb7Rj+M&FKk}E94)0=}E-jgZ$ zJX4bWV2!($sIuIECAEk7&mZhl9xROHq?JZC95Eev@cygArgnwzd%F_Fhs-*#TR{>0 z$fF>B3u!YT^ZkW+lu6Wc0uuh_eBQx+18c+G!X z$vwrE9tT0X{~`!$+4iX7&V#n7$0UTA5F9|+5YWhqvR@>6>$ctIGrpu{Enb6>RQGSX zFs$lfo-OLm?Lg@R z3URoDb&g83R^c#*u@Y3&fJ+RLY^u-8r(p)0og{+-*LnHxBhJ zZ*S_cLGC6kNc}q{)mtv)V+GZ1LbSZ-ppXee_S{pU@`6iC&twC#VB;h6I|Oc-5$ehLpk5p;;HEx^|1Q`?tl1tuDxHg!p-az_%7HNDs90sV&> z<67|FhH%|{P!sYO5HD1WENP_UCL~ zy^beCL~86vklf58m`!!?xjrb4 z2xp7nX9VN}HyxC79-T1MQX>cyHx*01YRR+c?pg<^HkJ{>+Q#CdS<_-^W3W`umAZMgYv#0pg)vd&dwwM9qSw1Q3a7SY?MoaQznX$+B_E3rUTuR%zd#Hv$@fmo;gtf+Zb=S(sLqDyp=l?_yT zD>EduELeUasPRMeGD6B%WO%Dj$YB`MXG3}oG?v={j%7B$W0?&AS#Bc`*~myBvJW#v zEBzr5*+}*Rva-x+ofCQu9AK?Y9JH6Uwl%dk1 z`5f;*!Xri)E9oIE{=yv2!K`)=f8q7$6kn}W)@8g~@(;6vy>_5bl(_;l9IEN5hEgd3 zk8#fo759vT6Y*e!!DxY@;CccuOV0;Wj}N$S79im8Edrk!VXhcPZ3_re4O=32r8tED zgze=|>~Rf_F-ZrDJsoZwgjOn-LA2(vMIrnf`^3KC9kG0~!0a6*?hEgSO+4hs4#HXx zWj6p*9`Zc|_uvb~5pN9Pr@zpwONB(frOwGm>}+>Vc<#qEnbNv z>gg8}WS?xV&6|sZJ9KO@7)jP!kDs`-6-m~Je?+%m#}l3@qiWDH$wbabrOrSzC29nC zsMi#zRBr&Uf&ihE7iUt3mKY_2lyM?uuJ3DQST$M(11rR@XBGLnDxXoj^VA7YY0Z)} z>1wY(cm?h*q^oaM<{mrzM25EE{iQ+OyEh*cM2*8>_+V*DKCUS^dALx}u@M2jvxFV4 z_7ORbe~G_}W$;Cf+Z|WJ?Y6TtGVmFXDn?MRwKzt{MF>=q1iC4x?**E%o9p9+$ zl6nLlwmlxI%Ocre6dre|TL6(8&#Gmr)i@H&t2_}p;x?wXGMYLg z{rD-_X!WmxMXLOrx;Ozg{c@lGtR?5&Q(ML4%GE=7?29lt&-%6j1a)ty%Vbn5-zCK# z-~ik!aVMaI*G$y8u2|>b&>9FM^4cse{os}N_o-)XTz?iJW!Vo4ts^j|{0hIJ_nNT*sNg&>m<3AwNQ8ma=Mh)0pyBo4ncc*YKU7<9E8NbKu$>k2Gz{K#+nBG014<@ok^~&}Gyb!9td3|a26`yPC z&Tl_>2>4r|m$ob3897U}U9nP9t{fbq6-IuOk+l|IE*Y$1QIKJ;C zrZbC*R^r-5aU1+M(szG5TL0k8aB1mI17Sm>Nu4!^#4LYKod5~AXLT~u%15m z%)2<`3YODyji&xJuC{(R$=roEj$@tliaWOJ@(;1j2YTxI2~V7^67~_7M<%KC3W@jn zQDRX0hk0deScXO|5SeM+sL4v|H7Y-dmlj1w?t<$}uVi0cdv^PQ1B#?^;W2;G73-Jg zq--?$XHDyt(0AZqW4%V@epM;C3$87@l6`I6*&PQDDmJK69F@ri9;CvTSZSk!du@Q) z3J+W9d?nUh&DG(S3RIe~Ahn5j*j>rRHN$)YK+dib&B6Y1Lj%Kytu_R3pCU{sAKs?? zgcN%&aCLHw|` z%03>b?h`L1;H3oZrJZ$tbN4#-U-13O>L&%?UYqvQcT^C#MGe`@Ww z9OP={h|LVaOGC7m)Pw)Svk}UfbJ}z zxM8QMlbgVpK3Q+DF zFQ?frX%9ffheWs`kD_+3#AJMntU0~(!WFTCY&E@oVrOG-zvy_V=4Zhwd+)BCE!)<^ zavNNrp41tARzb#xr8AF$8V2T3?nJb7v9i-& zzykAO`N+2MB1!Q9B4v%ivQCs|vf&B0{{;3{F(6G5 z7pKQfMID-fc?S5hG++sl*ky^7f53X-8%DxFOZi9E**w>>=#kiK*RaQ?J3QA6`u1@dJJt3_(aJPF+&IiuP9v%L3|W5x1dxGX3H1a;jZM79C!S&p@??Yrp3LRK ziEYjL%#ASRq+T*_-N5oTPeWp!3Kh6NM)QwEdFp{L?jTu`eI6Bsvr6X3n{V+skCtYp zWJ2PltP;eJz+$Dgo^PK-?KWV0kBB-$^fK6*A7!!OMsV=|2!z$E4a%igemvph z!w1w39p#!3Xks;wH5spTxB$%ve=IMzP&Xs!VeU1maNlvF|KPN&`0Tl-w!l=y>gUj} z)z5ZH(9pF(q<|S0UYY&m1$&@HT096rnPWE;C&Ozlna?YasnEV>6!Y*}ay0qOg3HwN zZ-_GD6Ux>e28b*-XTq(JF-Td5nxo`T6uK; zX4q60J|SP=h%N$zUE7%N~fz%q0xFY>UO=?`#9+mcB5*0*BY}0M6%H zl#=*fkk`?J1z;_>7-jyCR^%wm4gU==vTfU#m;TdN0dNPt^im8J)BGjAf*P9YvJ^t*Y$(lw#-b?yrj4N#g~x$CFu0LsdL$osk) zmm!GliYp6(o%PaJ61+*R?hg!dB7Ea9qCjLb4lh=v4o?Ba35Jh77Km6%1_9(Bh#-yo zX$Mx>-eb>k9ImkhMAdxxcpf~M!gX0EmYz8;*j3eewX(>zGE;*Jg?0b9)}5(@%e!(- ze*Q^iUML5Kt6Lri@Y}dvB0xin5TlR2mhfP3sv7yGXH|6n6cTjXz;_~5Pb!WzDBEPr zZsYMMjZ+DKgn9YxUF%!vJnELZ&-`of#&U2d@9`YpgIqa+pMO*t3rS(@HeU{o;XUpJ z^DD9-8bcveQU3N&y&m}u!Durv%wq!$SrwS1xQ{0ua`jYAqKiL&3-%~u@qN|Uew#B{ zwT}=SCLUi;=_$b^#x(~kZR&wxL(7+bR|#c3;nv!bnk_P#X%DMnKN zU>@F)SC|7k1!hVTyoy}g>!^LQ2x3TG+mL?(zRE1$&9yM?CeOM}{KS zG2lUgy1LGD9uR~rml28psK*0%H0BaaTQP8yK?G|3WxG=MEZF})r^4wxI2eqk3W;cX z3SH#Y3q^o@e`ap%^lJkfw-_zHmt%G-_Bj}8C1)UMt-?2mR3lN)d(l#Mn)-fO6 zx4x|<*C5t+IQYN77*V1gtC`vznDuK+OVfHEhyW5T%nMWo_+y6i72fac_Y5?nntnBK zFwP%^ZE4uYXUy5G*77L4dbFtMO6Tb4rkw)I$Z4#c(S1 zgb^QuXIdwmj!w8&d5fUx@1lhqG=6OA&06V^sV2k2>w)CQ2OV? z8~%zKSdCr8Y~B!Dk;g3NE|r@SK9*Gr=YLYS^W-tg#Bfn23Wts-)YJ}vI&=#``jT5R zsR{FM9FTj(7ve-z41xWL;d7{l<3DExvs&BZ$@ODJMb|pjtl79zKtTMlCpZyEjsNY^ z*Dw6{OTc5x@!y+QD32xyE9b+O*u1;cuS5Ih{VE5w*md&6#a$wC8x=#!s>Q1ptr2nO zLCw2GTgB)*z8V}IrtxJVyc4f5Qbb_5ulQ1Q9)r+$L}1*yg426z+4K>9C1~#sMkGsL< z-QmxHgcjZ5si;Chowy*)nmKdkj9G(6^h|6&$#znQcC*@2<85+g<&kx}wN|jZZ$#l5+VQPSgR_ACqX*(2+i2=-X2&;t%9Mr0oQ>@7qnp(C&cNB)iK5bMoswaB~P zdSJR$f`3Kc9b#ROXFtb>Gqo{rku^e%ZTM7Tt)quS9GdZeY1TSNSx3kb7Wk-r)J#fb z!h6BlzP zD^{}R!6+$>+_$MHF)yId}WP zi*VC&ZE1A|d1_7p0Ml~Ra2XrqxF!}HvMm$>+s}Y%y;o4f4>CzM+-0D^N>rLo1O=vv zMpo?#vMMm44~B=_{)WG{Hti@pC$7R}3;zWUem$hAA4cFgUbO{dyA;k$L~wl zp7H_1_$}AJ#dm95OKzirHF%I@-~b9BR)eJ@8IL-~69;7wD~2#CH6YdD92Oy*!*=iX z4p=O!6$DcsE7aadXaVW2JeBtgibc7gnqsaA$0fIpR4~E!H4XFQr#fs&FkkY2d|z3R zev)s~X5rI*JQoH;LSOBBAGbQU>tdU;duH?|bKvCpwAts8RVlZPVeg;O5QUn_x<#ymZ4$;L;g!4jwWavmD4_?YoQgrnYEU z|C^IMjbHy?^#j`zS$}%b!StP3w$$K64kzsFy1~4mYxCuCrnu&lM^NA8WJE&$uHIn} z+B4^AW*Nk$goJTFPLt)}NUkMofumF;m3d%{#i>5^HoyuKDRJsVvGPB2$2v8Ry_G6; z;sJw8q_&imU7rV>)wQhXcfMGC9JlQD3Mz)V0?F_%2I-whIu%S|OxW)(Tf>b?4ZoyPpK|cR;+};r+V-WfUp91N4siCyNXBoy}u`pi(|v{P4i( zTPSy3F`e+}3y6F}Ai^3;0Njxc=UH?svH2ah0{8{|*$ddr4kVC0R(1$Ce}lTcAb_92 zf1C-B)a{6?zN>7H)jJBW{00K{3>9AaqU^m&-s-7zh6KaR=@r<2jx4D)UjVt6UKG@Q0|~G?L|Yt$YAPIo@q&k6TOdR{ zTHGH7HU~4-^Z#d%ML!8V1JVi3WG3I1% zbQamkI0Ji%nDnR8ix}Z{+nZO#MCx*mFpm|VzMp0BY#cxAb^k2i%)YF+zvRV&BBNvf zHZ9>3*o$PXVKoD(_ZYHf9hOU_#3Vh34c7LjDL80 z6{$OK!ab|-`1!U~^|(bH;RJ=2?junSpA!=ounM$qY9^~u*bsTExpBTK)sfc zP~IYnwFoO#B4E#sYIh)_7J}5W)FEA)Sxy+9a%7(cst-S~7^W9bOnOjH3@eCa4P~|l zkVALqirwx)7~n{Rd6u$6uKpbk9ow~z#8r-Y;75J+M=j+? zZ7qwf_5rX-a0)jF%9W$g zSeUSILd(hyNCU~|J0v-_;#lA>Fn-O1kp@@gUf;(I|9W@d^Fe{Izj##@!2z5#f^~fahy&rAFZ91Pv zVdzYUDIU6$=d{?PbB0j40rj#Fz*YcXEUwKptvwnwU{ZRD++?3>qR}9SP!l87#1CyL z*AYuOY~+TvksH_u)vGYQMIX^+aFfQ|WiSuG#RV6eR%rjWh9HOjLHxuI5J_8EJz^{# z^@`aZxe$;m%A0J0oh7(DhBG*8K=Al|B z{lfJ5D~|2kk|zhXq`n`>g{|*p#gxa73&8~MrG;_~Wc}EV!PB`1ddVJubl}GDj!NLW)s(}6dF-p| z{4Lz7smFZ540rgnbT#Op4JbmT<>f!BV(cGX zJ8+F8fTJ!~2?MuUmJ64{MF8*5gCQ;y)9Ch#!NQP4stMm+z86%n1eL<>EC7yZyVw}E zOOp3a+mX1{e5Gd;wY^LR^lTFD-FxYPtik4{`|ne89N8^a(z`+EgIl>{3k`f3E5MiL zTChxAU_zmo3^CpjVKeN~gurC@oG=--yns+(>uvs>`qm(umT#pVlVH}wo55b@FC%i# zDxzV1`t565HC$FYDE^|MGlk86#f#J$?1Q8PzB2GMypr?^g3cO@Nyq)*VGk4V@QC0? z)H$EvS2(VHgnZq6RbPaBX}rWxOV|UN@dcAktmW5dB_h@9SqJd^&W+ z^%8$**{9>bOZ<^_pAJpjLe^QQ7$pAbje!L#o`|~gM7!_Vudv&Jid0EO{}GeW9&NE! z%#76I7?3pKuf`Wzras2JX38XLk@YaKtO}D@0Y4#VOktogZLq8gk<IyDVGipLAS0H@U z3PZsCddW_L{u9c_!+RtYCD7IzKFn6nO2ypa)y*~ZPmlJG@$uC+%I;7w!CYrTLWf4) zzWSKX{lm=AXy`};WItZ@$wdfkyYtXT`ao*x4#|_c9C<+5t4McEUXl))c zU(n!9purz}{sg;R-fPDL+)(BhBqw#V(a{=U04EvYnJuBaZD z-itQVCUW|}IePMa7%@TOAlwGPNJ2_S5p{Wn>&FNe*6Y*`O9H%BjQn1IwRSNU_V!}Q zVGFx6V=j@ase@ljjKTy+RO~owa?)n#6CU%?pZzNG#Bi3VO@lqD%M&8M*>&pr^_|o= zg7j|}AK&lP8-ahZW7N%;@Ml7|&2@7?fz4ldb4A{U+zsb;9+h8T7}}$I%c0e(wcK*x zz=h3%5(T)>I#_h=FzDKoGpUzvVzpe%?x>S%QX>|MO!UwAP?1E&96kz~gM8vT$|2vy znov*Rvc?UhCKgQYdIB>v)xnCs81;3;xj}-Zcokqd%C-2Hf^M1wy6N0N{yP$IC3SNM zwKIunDDdOePoMm*;TsC{Yh0<)$0jV$hb;wzYe1W}E&7AOwe$3uOFOW;Zlmc!ax|SbS9;&-IwGy5Z|f!O2_>$>NS}*9*P(%-k_?i}}jnX1iideFx1L z|EEvO0R!Wsy?dt)SUJ?(bnE55cTJ+S7?08-lez)1H`IC64K3j+uMZXES33-?W7XiU zbcc)K)K*wCdbV4CWOFQhjM6@7$2NK6o=uYI-Kha&9 zEhpdZcpx<&Au>4mx@F>Q!iepMX6HzClL6Yah7~Rh2NFr;vY7Imp1}wB4tc}Q z!&ac7Je@im#DS_6KvRSZ5A}^Ca_Y}BVh?x1>l6JXz9*LLk>vT2lk1Owb4i(9Fo@{d zY)-5xR_2WxDcx_#ywqIV+IqPK`sI2Pe$5cSthppaZb3c0u!X2yk1*jrtZrN~#f#|8DOwn!Hfj8MYO0CT7Q+<(ov{;2wV`B@9Dv^VucVu$#pxudI={;HYmlYf-5%s_XnH*!NZF2=>zfqH@~ zCvpHAw+NkRWUe@OF@a4!MDRBl!dNzYV~D`h82*MjCy=*S(S@)j9{3GpE;6Rdy)Z-q zu8`Pebb-R~G?JsxeMzppZLDVlJ;X0@0rtclyPw*lv4)8E2BccbOkTE0g=(M^v?1A9 zS!*+L&}cS6*v9{%Zhu2g8bv*!Rrfvm@-;X%RlJZ7QHrFmSxW7Tk=5$PgBtLdd04q% zsa0{`vljv^HS6GClu4Q)(xD8ruD;s~flnB?%ZA6?@;zfM=scKW3|xT^o|s_#c#SX~ zI!`!JK$m4c@$#)=i_lzXXJX*lId$yB@na|3c8?EAL?dJowjotS3F^41KaZ%!>k2}0C06m|n>QkwygK&Duv3Hxju!-qYQ=2oF9Joi zA^=N*K%oUm&zw39LDIHu(3lwKi$8ZKmpPO3nMbmBY{FK47f{20nCJ3!5W0Yqlsy!05pDaJ0;LY%K%isE|cRV|B%wK!&`nFZKP7TVMfOjBDX9>VTUg z(ZK5Px>v8jYPOed#pRTO$670YW*dORhJog)`fr)HFCP4CEB~mkG%z5C3R=_0KrbHa zK%|7Oqdy)$W&0tQ-^sg`WlwQ8;4H_VxrJVID;Q#=YlawbH>~vkxf_1Wzw*Tv&6_-t z_~Z>2Hiu|_lP{AusZYi5xPZ4ge*??pUb=NRmfyaQmhU{?Rm@nSnmeML@%Gk5?ekgW zjFI}zAlAQ00t(4tuqVlTaFnY z3NC)N1-41z)Gc=cuqt&L2|Tkv*-{7L>1a1;y9YeAp6t(C@pf2o%Q%I0Ld!QpX!$1A zQEo`=7GNUCp8VBE#mEChXL~R7xnQdb-VhSkc-Ra0#5^T@oJN2YyB1o9m$?Gv4=cm6 z(K#sdQO`F6t`SI8E{-Sk`^Z`t-bFf=Ihf6hfKM4Q((f5e$Td&^TzMnqb z+kNX+%I05@0Mq!WiJ+OOg;x=7RGYOao;8tE=AiO9*xv9864KysOD2iuwWvB3E(eOeD-K_ z^|udsg2u zVQ`PB<~I7fD-KiNdfHde8ec(v#kv~L8#UM?b!?2{9-zA8CrHez$Z3`WBH2vpf~(4( z!0JE_W}~FJJTDZ+i9y3{1N3rOwV8s%ggkJdx@e(;of`;0&R5tgPw4$0Q}YE>NDYZF zmQXp`QL}}4I0)QR3oAxz=Hd9mH`TGRihC8+9X}-j^{mGQ&_otK3zduBQSU5#rACmu znkKE7Jy`3gBpwN_*L_jogC;hX{ebZTSg>a$IUhogI26ed0L@Mi zRxJ{-30RDCa@9gn1HT~?qf9bus;307(rx{J6Q+#_U-0;e{f8M{b!d`0%U2(J|5_`{ zJo<46e*v`jg^aaNB(G6NUbZP!a7qX8N?HRX8ORsYg{q#^p{(Y@A`!_~yA6k;8Dbe= zh@_@RxWZeZfq!r z@vTdVL5F}=Fn%|Hv}zhKm1+1~0}kC-6X0k3p@APopYSNu4S3fdcvlSG)dKH|$GgTB zD=B!Fim~e`x_x*T8l~3#+`+(>^NJE*S&^C+BfNDXYzh0aN8W4#w_tB36U81^#W)NM zPYG)UV?mKS22*UlL1Qn8L0&jDC*gDj!VnMyaDh>Jp2GqUtJCY8Y8%1YFEO}f``Aq+ zdBviPq?JZ_=TkHERMlhR5SPbo^^JxPZUiaJjhw-ad^oI?O5clP)xk8k-AmvDA=o2|%ctHS=34TtoIKITh5#t6@gZF?NTvSW&j17Wk+#D!> zfyEJ{)TkJXa~-QAPqh36SiU+)(PSujMU5@NY3mLSqTy`7A7B>B`m9A+i!)PgujK5+ z-Bl69H?|oU%XnV%_)R_=iJKvCf+}Kp=-rg8*Nzn{$FP2mVO5sxOxc%o(5RV8r57vd z!o28$WdOT?zD>3ak%s5;olEv6?T1LleHckPh|5h5;E&PSc`RB!786Hd=la$*&G7*?0EET4{Ql?@F1j*snm&#V4)}6^?$K=W(At~ z0F1iuq#OJJf2u^7i4q)M>9Vk419Qn`r3R0dg~LQ=FhOG;@=O_Qi!KafJw{FSxD3Uo z2PVf_th&5u)rPg%GK?fnY?T>eRL;uWAq>{z$dLye_U-|dr)fd*@W5h%NGXEkEz^}@ zpw+ChCPZ0Wh16^&PDB|XJlfAc#O-Z(B+8Q^Xz>R=Py?ByL_bn9)se~u{1*}*{~OWx zNI$A=z!Wjxi1(Ibo7LG7(47Mq)lOsmS4w?7-=xNBX^2n6?G*r_LWCrj>k!hI|LzSVmfyozqn8gipSWti*jUF?EE5fPPIZruiS6az9gAVF zuB6@cuH*Wc$MqdPrk}95hb3Xg<{aCLXEwk7idFV!a3VPpd}?8*gY=WP?)q!5>Hf)` z1vx&ePozC&w%*SsT^YK^ylYsGRjo`3qvp@S6#!vNRRDa*<_0GzkTng!uhxQ!B%3VL ze_fTwixjUv?{eam+XZIU!J7VnUet&w;SU6+xEc2wLEB;z(TE8hHbB)ig zEgSb9^8UX>vFf}uwY`9mvkE_{l$YdM$k7(><7Oi zb~cA4s!|-=6vuOTqEhi5zX%wZ{R!q1rT-!PzIe}C)?bB>_xdIr?QW%P0j6+#(Kx6C zo?XPg^4sD~t3aQ!A{)FBMDoLwl5FrEVu!XAp;;@OqS$8EL$#yQY&at75K#~oL!Hr& z459J_1aMYo9Y9)WkLwTv&!$!D)@5yGQJ{xo#7V|UdRLb%ZjCvLH#R0R^lqrsBEGl{)wkG#&0x6VN`ve|vZxM8Inxd^PR@{@W1{zJ#SocVTIA8kQ#A zG)t48L4=Kwf0_XJqH?A7t3f6$2vlo*c+B*Vx&8xYaQ7=Pq_jCmqFJn*yw(`Fd}MhZ z-JF`55)8j(Hjq5(jz!p`T_H+uP@V<6@79>`KL4vS94FuaZQCNsTtm4&NB=}$ zh)Q!r-2o))9Tqa&E8h!xq>a?WK+xqw4pLl|2+{iKgOMBySln4k2Zk)01?(hS_!_N~ zaqJ^pnqG_e*pn>zHUENFERsBT_En#Ks%&_wpI*D(>;|UhJr<>o@)?mfX?2eG+C|w* z)|hK0>EwOWcA+UN6s?@paO$^OCttdt3%_kH#1{YiWtk!!=cXzbYG69!GO z9o4M%)S9L!{oTADwaD=m`!jcBD<)XnG-R{8q8;B%(4Y=ekH=`{vZ6e6(y@ez{hYdP zaZb`^K|lLL5R_gg=WRK7k=5`MpVMl`rtC*9b^3=KX49|p>4#ZLF8{z!uZO~rakwdPsu?pTMYr7a1lMaG2v(e39XTsNwjl~vqt zt7G^9Wh(0B>2;|ggMjkYcSzS6wot9g$DT1;T%XTMGyB)9>T5uWvhUCAE;5KtXs=U20FYVeY8L1bakb1FH?H0{Aa(&T1rJg$>h=~`i0b1q^xy~jQ z@QK&ig1ab)EAR$IY`L&LU}fJf%|3$W-xEOfH3LyQuNDFd^zG{45*_x!F9fRrxCnzq zCg)Mw0QW|uWzIunuE?5Uj{7Ki>5)apje%)0RMBchaH-gl%Bq79gp_`mmIbO6?})B` zn<@}T7r=ku|IzgxU{PH0yKs!Mi{~g<7-V-33m6p;Q9%@xW^XZ~F&ewZ9$PFJYZQBl z6}#9g_TIb35_=cL8Y>nw#^lU+W|Qyz4axuB`#twQc_QqxJ3Bjb%CEd77r8Qy+&Yn3 zq3sf3xgcGXBWy@p_v32!fewkQBV27djvv)ED0x7;)*6LqaBG1 z;6CUX@%KQz9T%!@%8H??58x~2)^}L+z}Cn^mrb(VkdapYBnp8+2w|RqLi1+-SGhS+ z$i}K#FR?V~B=S+D5LtlFToLXg;3`)jvj|TE`BVecFwR_$FvIbdbx2qj;c5qsk!F!&CP_C z6+G{$R|G>$>J<$}9{}fSorv)F!kOQya2~qIf6b zg~%iN83OJUelzdZo+B3>GEq_IsJ`@Fv~}+88GA`-#oVbOk12iM(?x_-VXD3eiD$+T zjHO|a9YBq`z6e&#Cu1G>wwoMbOS+>O1BC`uSP^6fqPj@)4**=<_c;ip6Lt4q&JXOKFI58SQxlD`4@oZ${FCCn7=R5BB||6; zf|oOleQifAH$V2SDQ-~yprfszl<_Hn%Vw<8L9grF?)e)Fs_#^Ggb(W}ybq!4uEV9^ zckB#>eu0qAf6i7YoSENqN4NNIJHSpg#twayj9nWxu3EbeF*s}gix(`c(fhkATvb^D z*TTrR4CYgA+^GSU798L{=;IbpJ)h}qqY$MN6cyqA0Z8Ekkzhe(lQEa7Me=tSAO+sA zS7@1r8-F33Mg`zBLeMUY#3_wt>KiT}Kp*)-#!8rEM{pSJls$VHHPQsH4Cq)FoQK-M z6c`LaIzVWr7|+hzQRCwqv<7OU_*wRNK%fly~G?vQz_)f2s}TB*?jP zXe`^%gSH1@e8m2#y1)~)qH2Uj0f1BEnd#<-NLd(`zq0p3b9by|7FbQyzkF78kiERX zDPae&Em~$B^~tP*M^!5y11Z^|R?XrY4nLn338PE7xLE?X6)JnMK@&x>j=ntCqfOhC zUJ+PHCRn9PURjBI70j<*a9!M#*jT`S$+q|}_QB*#L@0`&3}}u*tp#O~s8RHc{IaY$ z77ASer+T4tTRub$swyqyeV#Toe?V;h(O~o6|L+$OynvF60L3BIo*sj$!6T;DnC&#nfywi=x^0=@lIeISjG2XKxddRp5Z(%W0aTGHq)$j5 z*067LN8jdMdjGwIE!!&HDl8!H`TBjEI{G&4(o+<;$TlwBCWBGt=jCQk>^Qo^@b-?L zbz5$yaA7_JR&J^AdC&O3VW_*AAnC18ZjEG^$!~X)ZE!@@r0DTrs@;d%`0)#v>|Oy6 zW@PU>eo59+Jiuqo;AQ>#4;kFQ|I)#0-1-{-wab>R`QM*IK^N)mI^p}0slw)Fl!JW( zJmX=oa2m!40iLPEnwhQ!zm>nL_lPWwe&GA|v-rLnuy$@hB;~gc3~qX-2A1zy;nx<# zcXJ;ObOB7{3xITIRp(BO68DRjYp#Ct$?qhU+KzflP_!C=$PFij2}oZ$6KQ`I>Rgl$ zECSf(9azD_s|Jl``*Vm^5ITg*f_e#@7`uSthFH%_lCw7bl#R24~WGMs`rdh}>X_w@|J@)>%^Gf)J!M2Yvcw2`%$ zjjYXtR|M)!dTkO{LR;x;i_aqh|76yku7ErJXlC}_W0z%Z5!4PxsW04>XayIup_fdF z5ZI)Y4aCy%`x5IYmgMorz({>8nX`?<<8kzYx|YjYU2<8Ib?Kw(S|0^vJz4giXJ9p1 zRy9yDc_GF)DD245cs!ck`L!rm9p@-G=wUd?@hFd3A6ZS7x$hZo?I_i(9c3YQltmKF zqzqL}WzbvmzVo-%cMhWO97Nw4fxHf*q@qFq!BLc+E=o_AgfzQ5g=Ifb8{P=SUt(t6KQ(;lpcd%eel1^LC1piTnbKcqci2ks1AnISx{d@vLxj~)C3l0* zctM%mMRp_zVGGpy_gE0ZI&w}66nWr)0ohbqy$V6?86z~s!#RjMXEA(51~iX=juEcY zthTxGnw*C6QdO8QN8aSnc3bI?CoRs&1H3=H<==a;;vvK-f)GbWf(Abb&o-uK<%@f2 zg3YLCLq1vk?4 zF*x-pqR>hj>DjoA1^D}jGO99Uunn*iC_YYoj))pu6*P3gRpEK!s?djl+aL5oUHB&Q zmheUQSeEVsrJ)|O^m=Z7p&29PF38(+nI$y91VK7jfQ48d5PTOd;R>6cr-)>^nJ>a$ zh%NsTRk9f?U^?MKLw>HXeZe9Yj#0?bia~q*8dr7yn!jPrmKi%7NE`>UzR>KaPQ!Jg zY}5)v9Dxs+{Q{-EkZcon!%;TA%JI7h_GgKgY{awx1oF$@urW44r~R%dh)NFVp8_X- z8LH+e-h;Oy{O;lLVBzS^_>%tab>AK6e`+*nQui#;nv@!P!JE)eOXSB@{k#X<`JXm5 zrHvsdPX7t;!(_xOlQ7)o2`2zFGV-BWE>_0ihLSv1i9RZpmvl83e%RnJVFH#OIw&DZ z3>`jH^au!P2M`igemEtpFDO|q+&p*tjGYcX(mM(GuQ`}Fd(aX>Ih`OvkTgL(^N{8OZiB6eRGFC`PY9jR$B5zWbso{e;UxfO2se0Z%RDRk<>Q zdx~5{FUMGo?N&pj-NBcUvnC3l%~d*o?3ATK-hhG^UlP7NrQIKGPfy*KpS?T(P2|^| z8M}@^dG^&J_N~53o6y;7!kk4Dmbs3s-Lz@lh-Im>gO<&izj%dn?T>3Z z4FlSl3hzd&rYL>`-_CCms}YAEpI9}c zFzNL7qJ+K_xdi-zB{9rggeXY35%T>^0Nit2@1xz1h_lBI>KL!`IhA$>m~H8O2Gl{B zufx46D^M&!nXsntLoS`AKZj+!2$l@6zAQNhQw_2F#Kv%HxFXlsS4@SoihI_^B?q=o z^?qgV_TvvdMg>i_P5i~Hk!>nB+l%657z7b9kM|P~S@qPUOW&+qNY6V4sSyQKkSGS+ zP7wYJ7}~Un5L+4PoHT_sUL(B)Bw}oGviS>0{LfxH~_TkGMPNYtQ}cV!6zF2p_xbHerX z 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%0D!z3o)C;CSkD0W zew$j6g%F=|l~4`gR7qJdAf21z>*!@TtR+1AsHW2yVP5`ZBFM%)fH3bP<5m@$SzX=w zKjbK|H`s3GH3OUH=x8b)GaDh=uLmarZdPD&Jlri1fz}p9+CYt{Q~-Bj+1pMlak1&F z4sTw=eaW_SMdqGeEBg2D-M@b~cf02Mv87*F8MNm5Qdx11oa(La*`}YKdhwwX@BI{x zx5|6MS(V9qeBL5=j{l;xc_T)QP8%^|t_ValOEvV~Xt`Atwr4CUN2bCx554ZWVB-LY zITzrxxzI+dX+tzx48tG)0%mC^F|JPaRnsX!s_N44W6Kw;TR6=-{Pk=D$PR!-E32S;Gef&hX4{nN}s=1?cM4asYPss zi~*0+q>oL_ln><)Io?Y_41c>ijngZ>oV`iV^h3(uJcKbcf{ZG!kx?ZqFxRMZmQm$# z!!Fwh$7ifLDynUap9pSu6S_4&dio?9yase@el*f7{y4Z_eLek?4c|H-fBj&LMdYIC z?{1jyuIehw)6Ohlbju=cnsyy;@9*i8WboQ}`v4=2?ClRg;Pp$-_jL{Lw)mhgji11D z*FszU&2V2f63CTm25KcJ+T`aKrTkIsJcu|YNfZmgW?!}%h~rfvqRGJ`k<6)$4Z_)t z7L(sl27IA6u|vu`M{jJ|jz*f*5&WsBC-!h+&*8VX_HgL$roIKCj;rWwds*0kQBqZ|LUK0~RM|#QkI~+Q z!$t)KFcQloK~U5>RLun0)-Jt2%mup@yXP#B;EJGhVt7{Z&9Nf2G{#)V1Q%{JG1`;x1L{O5V+Q>z zsas7rsLt1%LA0Jii*F*+K4IKjeCi?43UxJaJ7y@z>tGLwz(SzLb>wQS#b!Dvzp+?H zQ;-q~*E(=;f8!W8eG`pBH9REto{yl~H$hY*ZW4I|z=Bx>rXpk$4D&)2?IFZLwgoc? z# z`-#&457%Z%s8PY^Pr5V~tP4F$dIG9c)MZ^I0ya^#4uSYcwu9T!`VHwnV37CM_3-U2 zo%d4Mx5ncmppS(d4o!H>v^pLF14cYH%fl@SpO?5t6pv-Ntoesi$0`Fn(r0B6@bp8# zBm7q}bjt$Ho+0Tb9*~)(JQC+JeaW#1>^zkgB&qRJD1jd5KD`RVlOCQX_^S+50r37SQ56hZ6A$zP!+jcjeK z^%daBGL{H%q1a07W)w=Xx=)s!Lfv&Y)%e?-U<=e=5ub=i(z?L}NZ66?NIG9Kdnv+j z9;?Eup(2XpK2i4NQ(`S~Tj}+}ZhE+*+`>@`vBuRo=T@D-1i8$(r&o;j?J?c ztVej9mP~+hWs3&pkMG#yEDtFVHM|x@frxW0S;ZnF*c7O`RHIy5gcM;5_N+pOpDYU0 zh&uGb`Nw9Rn|d8~snuj8;>3Yfskf@)rqGo)ZB<1OD11<^kIT04dBpG5V^ z)i>BZ1GrW$N$t)m2iaTg5xXgO*Rb=FHdSFdP8;*XCBFoPgvkb!68rqa^x3w{q)Z9b z(lCUr{sg+5aI#D@l~zYb zdj0YV>WiD@&1$rM9TR~!*fGQFs;9fUX!L_V3@QMhU-x`|)$qCP=?5K_q1Z+N9D`(0 zuKlV)0Vf8q&lrjy!4wm_?!YUpi1PRHschs}2)}CRpDZ!PJSGl>aGqn=?LHCO&h;C1 z?(DOnbLZZ@J9pmDduNc(FK2hZ4nqI(HtMM(g?}p3uuI=G(FwI@dA>LEqiJII30Jws zB$K~u06-O0^}3%P7a4_Hp+(#5%cN=@{CIY?NdO8g+H40&`2!=0dKLo2mSi3lsY_VY8K=I%sk3(AlbFrg*e}l_J zvh2iS{8nD%GU>irO4JNUT`UNg)GLjf(Xe#q(?IFX&sA`o4Cbnqb`x(-0oDZVcbkgm z>TGos{>c{&v#~X#;<)E~5!?e^50svoad{%tEP)bc2pYetD*#8BbYPy(MLGdUW1dgi zm0lX6JqI|!SoctD3{u^4^tO>eO9sjEk=!<;=Cm61oE650j)@-aErIMAhWr<=Y9T}r zM#w$DE}?U7IY(wgGlLu8YW$7*1ZA-Qv;>*Ev}GL$P1~XvUjbL7DS{`k%ev1k^9QB$ zp%}uXl(*}-zRRvM%`G_E`Y0fR5mbDdgjLrpbwTG>O@2;y-Y|!&H~M(&0HOd&4q8>| ztGZffqp$4hk(x%K5fB?;*q~%j3Aaq>|MbrX)o*0)B4 z5v0!K=r1EhvAY!eI(Fjdzzx(Fg@II-sGeRwtg6VK85d{Yp8C*Aqsz+=pYS&=rO)ZC z+w0GqIkP?`IjK*R6dDZuAg~LCgm_Kgpu$KYf#Cm{AY;Bs)bwqt5P7ZBQ@ez_7DIe$ zDJS%jS^pEAM*U}_{)lYUV>Nvx%+_I}PU?vl>8YypR9N0q?ctN^TELXkTx9bZ=Pe3# zgk%DG3`C$NnZ<+ngo7B1CfW!Qp3f7E&n+rRR~!ym;{x*sTP|wv>&-`MJrb#^DkR{{ zRgg8p77F(U94T|f%5`f8t?c{5pwxaptVmrKzstP> z>&?2Y!uTywlxq@IetF6ngLh9@dEd0rcm+^m?c|coy8S^N)G~nPK**rrQwTT;9>W zMT;)o>ecJI?HHlV27MC+qUCRR3x016O_Kl@gq|?700XpE`$!)135lUul3WxC3;@lA z8{jEi+LZhDQqPpe^?M;r-Jt>?uP|bY8&d55;x}YPpgFj@h`8&hC_$xT{xzY1)p|6i zHlsOZ?>x#18e~=mf0ICZE8d4hh=V0zgMW9SXG%)Lo}pG{jzYL! zuBe5wE_C>h2Y8h%$wSQsd7v=B=q(4WCMptpxdaih&{7t|XG(vd zQ+hZ#;QqwAMj`BhaL>dYxuRczIz<@QGvpRcPuXfY>&#z{41+$d1&{b@^S*t*Zhp-> zcbwM2)uAI`7q^8Q87z8!pUqtX{~W^KJi{7L_$~a5u~(zu36-25g&TEb?Y|9HeX1ho z+t7d^xrAU#5vmaE$5b|4R!R2!j#btueg{v*JhG!ISxyDVV@WO>ZEk!@g$0{l8lrJk z<02p6o`fryYhcxZN-)p8Z|p!^VNW{HA*Parukoqk!cO%!4NZ z=__Uc6GVRow_ldPr@6paP!;1)UxjOc8AX2TA5r_p65*gCtsZ~{(x%qJd>cJCJ5Np} zd>jNcwhPxkZ1*koGu+&l?*+Qs8&QHW^qwd@n&Wb1({~=T_pm zzvJWzJhuYRLExvVUbxQNtHOPpsT2+R3Ahih=C3*!bV+bzw|~|l1#jV79CBgQE*Xxt z-UbWKgOrhy>rF2R$lX*00db4X(>ns{gN5&*Km%({<@9PNH~tE0^qpH?2M%oEugbyX zG7$29Hi#QFjV&_-)?pZLVj6f3kp2VcIS_ZsnGKy`ixBoR?FhB8Bb3bB5DHZ$ULR5B zEux=YX}5-rKy9uEY|nZOTjb>vnJC;&*j~&5rn?BxZSMPw*z|giCVP0iu(Eo|?_ZK7 z5Oj?~)ly>#0%hq%YA#-unhTt6%{8)^zJ^}$Wf`?v1eSp4yP8O(39PeUt9OtfAy&dN z1Vn?w(Z2N+CHygnRrDF-@acRR=Ky^C*Exj05dM?civ{4L;OFxNlrsKxf9^7PHIr@@ zH6> z!Y_gO$pjV4>A&j`{4&m*oV8>(7)4V>;1Jrb{l3PrUB6I2gB%iOt#gC}gJ|U3M?1-A zKsg}HWVg=UHDiw>0-^Lt_9fr9c+-xc%+-9}_Vhi|4>&Bs8#QoYG-@}C@w;Yv0@>po z#ZEEcTezr^o9{{MNGV)SCC5@aYD2y$ZT+Ct?n68xNx)#7S5W>#D1yT{T8{Rx3M7?D z@b6UXw-lS@Pc-t^%H>9m{)M(Oi&M*{A^i*G4!G*Q)#Jj^$RQ+b&~1C_x8>9LmlHtM zJun@YgsdE&5(1YbS9vAskpRk6^+PL&a$8;8UpE{A?h{69_;^ZH|3IpWeFtczAiiP7 zCP(=Nqd5Xf_4QqiAD#EhS+cyx-(fXQSA2mgx(%7=aCD*ZXr8KY5S(`5dWK~rS)WF7 z-9j^IAhd+~8PZ%BLfys}E1(L3%ub~Z8S;8Ax2N^)G_eO-GgC$k|9KdGih}#G+Es^( zQhWvO@r4B`P(0y^!nAos;`ek_me1Ro zzGFIA3S|TU2U+ji4Lko)moIr1#m3K`koX!W@ zXk?5Ex^J}~a55zdvdBmk^pr3V)Lm(e?h1J<=Oh`cZJx3GoL7u(TIXqPYdYVOnP~uE zNcdbB$=PLYgy+?3J&Guu95Z)_c#3;>la5s|KVXR6_jTio{X9mPD)?B8L!+_42e`l81y9I`Qk6d>;(sJuq!7~zkOzp*n~h%rkN{M9 zD8MLl7(WG!HP(H&5;v!PO2RX}J&Ag9l^hQkG^NLtK^6SBWW5H*N(MUijXnku7DOaa zA=I-O0&3M3x+-EHZi0IKZvK)v@U?f4x}jx%jadPxFa|||16UsF$O6zP+DaNl1Z-OM zOkah+J=0r6DJ>-WPpVS2lSf0%BG86~Le*0g@}DAYU&ou4RFMnen_kI@;vn&2cdy*A zWZeo(QaV8kJO{ceR1Z8%+plNx3*6jmG zseOP+@&P$5o*N0ECA`8}{7y|fqaBWT2aotv2c%AQ^1E^=BOcwyOyQJB6@2c( zKLGLTH5N)US3|Fps&r`(ERKUlhDxlAla|w)gQ6X}qz9H~O=e;_H-Z|1=PH7o3^+{@ zQitg+IJTK7E%5g#_`5827tl?x0H*GvSP~5nfBDVv8=L}|NR%l`qD;}lrhpVR#sRY> ztA}ChC@ZUn<44nYBZrr%cjV#2%SYb7yWBE1wqDCn!~jijB7Ba zUfP!_E$`SuR3RY0t->0PAWkahsDfOUM;L57nZX0MM#dr5xHQrDiBjH zVw?l=0gqLtDA61<7NAN2i&(x&gUI(fwMMS()LG_N`4JRHpOFjB?;9*d zeh=&e^R)1BfO|N=sJsJI!vRL|)}7X$IJs;6p~E}-H2bD=pH`@o4v?Ejf&x&-?kY}p z_W}jFPgkNqZ_mu!vAys5u1J9jPh{#kpElREXwKMCLw_7UEND`fnYLvRUt@d7h!jgD zGIJ5QipeKbt|k55BT)L+Zegu{3u8BcsoRCAjmA)$XAg&z6MqOXadKr`CIsXdRtHy= zNR35cGge(?BH_KMpU~ttmR<1?>w99ubgRpnKK-sq7&b^h3{}k#LBvD02{|_Nk{18(vWv@sZgF0-Cx#9^r zV6Y1wcF^#@j4Kl8`PNJJ05EKoiuZy#Lh#Kx0mn}txV-C*x17+CY>UZg1HFo!2r2m9 z=PQEF_BzpReEm0yD2A+NonCfqgK#9>p&(k2Nkm2a%{PFD&#N}uRfFrXeQ?;Y3cW;6a=9p*t z3a*M(f*F@81KmaFk)xBTqD65Vx!0o37Xvce%h2*_T!IJ*1>Gz2V$h|`&HK(c&wRhH zKB5oEjeaW%4rK?X?^(11qd`{r0AL6FGxL5SvQZq!MvucPt9nTw8xaz!B!bbBWz9}x zF3I)zWL?$ZHv|IpYtZVY7Gj^Qr53~-j0lj&5kJZnUkJZlm{5h@u!+juyF$g@lpm?& zaTBf*@7YC_vw2q>iineT&weTZ~f9 zhXJB!A)Jj4ciQ&qk|^E^G$Lpi-9`6vy)gnJFb;FnHQb{$`w3G~K}Xl}y&S6-M&f5# zoFa_6K>|WG!ziM0NMVMSj1u$RvWHbURjzES1U`TB zEa9@Y_wQoSSDLE)Q5dUXTe9tF#(tO8^MrgbACZW3`+dOs(e5$(@hSO!)1YO99mqd&(R-;FN*Y9A|vph*HEiPIv=f3 zH5o|1x3`HyNftd_@lELGefmahDdepqBp-slSGz~%{3@~+o~;*V4yB58Aq@WcOb2E0 zF3!{+Nu)}gg4Q1x$ECQ2VDXwIbvXe?>Q!x;grw+)ZRo25&koth0 zgw^Y4xVJ~D(>dkTJ08(^`>|tZx4q_ND+-R`T1WVnVZ2_4?MIL9-FBHb9ADj4z2U5R zJVljrp&u%EAN6_p-rmuelkOd?|8kD6N&d%tnRC_Tl@ph{`HuA)cI@c0p$pFzzQC!z zJm2-(7LB_`@KPxxK zD~iAj%vq(M#Lz2^pbCXZluPNyZiGuDhk$M3m?m3<(J!Yp*#z?_%uEB6H;KxV+CLOm zyk%w#_rAS2^TbM51`w^ne=^?qBLneNh~JT6MPphZtSr3+d4EK89lAK>0IB;mT4j>T zas0Vx;N<9+_t7B3y~Q{-0I^Txs)hni6Mb1?n$sp{AK>YWp+@jjaKE@ZK|bw>&bR{2 zX*GV_Ll5pAHVPDz-oh1d5r;lL0&_iA1W$(-R2*q-fAg>C_R!9)##qoK|j|8Dii=ja#u8@FgCo4kd@i>U82qlRQuI!i*ja>0SZ^3{j z6!V2*)?b-iM-`SZZ6&w_!M)iO71RbAfq9jf*`oL(oNLt&DO5Mv>Ye)l1w*7|OUX5v zoaOI$&`f{vX#UDm2(7$7%qA?0?N3qE7x$)w{v%aO5{RzNjVF37ZB)I;j z?0G`0Xh5uBAOL!Zs)=B`)^hVZ?Q$*Im7|bO{=|6k=@?kVz`##4S|SPpF>5Dq3HoQZ z)fyYm-n#e7BRK9%gOxyUZ2kosd+b(s{RoElXD$fE@$?llLD%3@$SF0LdtZH^7RPb< z_f56R##55?f>|l>xtDdl7NJ1w{6toG9f#K&jq7od9oTlA8$Iitj;lO0tK zj~}hPCLE^Pk8{%&RBe>zoy-qw}+E(F=S2hhohdpam(tR-h7WNMsZHDYWR0n`mA(PhMGxw zw)1VEv#aZbDNTtTQ_;m!J9qycE5z(Npfiw!IT$i#qHglOs!Wj2rp0I8$mo$0%GS;& zv-cv<819cQPtk{}muJCaOdh{Y3|PS)8oCrwcW%pkLDFu&%s0&1JZ+1mr9c$G;x5LU zo$j&wl=I4&Ls{;wp2`}pj9PUWwY4&AyBgXSbmF_6a=!iPymzx-%<^tBsT2PMi3TL` zDLRPL&ygd&`~NU%;9%#V`FV88uB|ZlUEOHz|5v4{ZlVP7H_&;Qibz)+=Vj&v zxynjbv_!pdgRg3l-T`m-W1H5_I_q1W>Fw@&^7%;qJ5;Po2EP${>nM4r+pF}U}cimstY2yDpnLr+hOhy9uHH=Ym8#&Dq6*UK=qR#*9Tvw zLMEe#DTb|yIE@&HQFmo79ihF==C8&re+xJG)RU(0LX!CpjDB0h-Gw|DA0w9FNoCJi zrgAarXAH5h)76aTLV5xFt92$Enyav4iPAJhlnotbd`_5H>i|)`sK7p4ZV0z~syfj$6j@fH}uXSJHJH zd!qU%ov=Fpjib6#mrY)drJh2SP%G(L&6#-oGfZla-60VYZXYXfjP9yyToqSSC9N^g zOgoPGZ{fJB2SXoBkv=CCHSs@AIaBCNW72rBS0KvY11y_AP!8X%4CJX}h>P?0ZC`&9m)Dh< zI~LE-STAnmmKH|K>ShF6-^<5M#=xSDDgg01Dd4#LhN=$e9x>j1$D*lb#Ta-E^iMJ z_e{Vo4++XOx9D2XRU!RxygitI*>e30YnwC(I{50I9@{$*4|h%ZaaIAlBLbtu@zTiK z;>hWKVz#?Hv?VQ(KQLN+#QX-{WCGqe`PvkGMLDmu-WYu9XK7%JsnAy3VJjpD21>WZ z?8R}G;wBH9WcaA9?*+qqpMJ1q14i3;TJjt&=fKmFIZy(MVP$BTDffJ%gljM=hf7nE zCtt;=64PnQrC9G^2MM0Q!rk;zXKYGD!M|z>i!|;$A$=%TowaTnc7UYbLrFIkn&ON& zxJP|ROFULzm4OCsjJ!lASjO~i_io3~wsi5i9}XOrL|ct#jnLF(H~E(`^0U(E>*3|3 zGnnr>kUt+K@tSfpJ{*w9NUg{cEFok}Da$mue=Y)|*sGWF4?ln9p zMqu_o#&GM(%%xbN5<8faO5y$%)Bs$1YrUpO{80Slip7{R2Su~95nEMpHU~S*ar0KA z%40F|J~;)QxOu)({ytctKt@}z>Lit;^=n?6o-GwaW?|i7qNrRbh;ur*=`d(jz6=l7 zpr9~p=Q9+Q>OZT8nM@r?lrj!(9DtOUo3JJ!$X43TJkMN|O`1?s|Dzx0k zucF#c+>H*?2M{mHVG%q@(MNo!Y|%-%&&8L@S{B{le!bpoH>N2X%I0Fkd0N88^}_g~ zE5W$oJ*niYF_75}aroG()#sgXxgGW=4A`)36fPl@&M0qehDt-|X}0_4Eqkio=O2t1 z{^4+pFz`g3v?r1iqLi6Wdix6UPLJgzJr3Tlp1d}g&%x<%3G-^JX}b)6czWid zoyaOYc`$no&a_9RBwVBP?Gt#L55rZ{ho(d z>f$L&CND)r4Z4ebT2fW4iFp*9jilz{7{-T3`O?)Zm#;?J=h~EjT@PdXzB!-^wr1wI zfVC3 zVs-RnThJa=ApT@Tr)KuGBuqPqf1M<;N7oTajN`D2*nv;2@7!;ueTTL}Z^RT( z@3!xCL5krudjsD}lc&6<^6DH;dSdbiuZkUB$g#xt!!#~Uq7Ki@T_5eA$Rm?)U_U{l zkiN5USiVpN0f=BK!1Vy*%+FbNaM^?cN zgW|nYxPgs^Wd*s^T)cxfdE-pxdq)25Tl8@A(i75O*LWu>500CQECMmWdD4~B_|$nH z%|pWAg8!jtcq(I4E#C9`K9Eme_z{iHHk`t)1F8GP5|!~(5iX=i9t9C%$~MC&p5kF2 zb@QD%ZMJn%5(f$^2i`JF`PH|)A-*vWlR9BK$>{g|*b$>J>pVVAxh7h~6_Z#Hp>pF_ z)fDs!nyg!XrhE|eqcHqxW0bbx5Z^VVlS zPUZ7QE?pI}eD>lMbHe6*%>7UM4QpMNo)-Ej&dNq}g^i#NMtZf{lz#+v4WBfw3${L^ zJsh_en`%Q41otsoUQBvD9{0^oZi+i2I+=_Yu>I$d)LN`PeeIM_@G=t)Cx=8BpX=W; zxPQxTRPWEyYuM*$jvEyc+uOR|7GI(5ZIA>vXbUZko(C>n9kP1WQvLxArgBZe9Dyic z%Se)hd%Zf=NJ^<^k@ztjLl~ISr$%zN`WR3c21~6=Vd|h(Rjn*Yv(+A^t#XKn&gy0Ro z2vat+Q#kyA)sO3CEi-QL4|*>vDWhvjc_R-$3sZ~Vw4mZ3M2 zhLT`3O`SL~25>&hSg8RxW&d{A~05GrrSD;r!14aWIb555|%D zX}o3%qRiCAzMUG|QBh8P63SN6J654-7IaV7PzEBJ~XF5MA}i=9Jo0>6vp zb)3ekgOm8(u&Pr|s#&zceM||Mf+rzi#o1En?I$sZKre}ig?~@Nl>}0GsY?_Ns^k8# zadiLKcx+S>3u5`-7jp}_(X^Tx;GRG}f0gn|JNG+2`RI%zi*QwH^4lj-M4&O=h^{ zWTbSCW*qX;j01Ym1+jlde4jR+;EcDQ_(~MtV@{yE9fou^b<^gq1>YsBqDeCq#v!KTXviyWK17!lL7V3;D_ zJtfWJ;_$=LaK3HSH<;tyuC$p4LynjGoY#DtUXvF;!0sC?lH5X@BPGU&iTuZzJ6CPs zVzXV+2`UzNc1@~J?V)rsUK~LJcQ#az=rp#=aNJXZ zrCmHsg7-c7^Bp=M(I}~k@aNvdBRfjxDVh%muI7hjoO777#{35^Vi+!&%>g^d3|`wk zwCj*A1K$OKpN-h)WJtk@lJ)a$m~w7FW7n6~t#Ox_k61a1ADwVC zEXpvs?!?*+u@)6e=Tv-(Dwj(p=M`I|yoM{;Tc+gY*G7rDP*I20{g@fgJ+8cc>&T#& zS~nOR!AncAv0^NwBmS{@#uW6bk$+~&)zA1Utw|_5OR;afpR^xy7z1%JKHUd_D;aa% zpS$R5tW08&wqALupj7Z!B-Uzi<(ps7j+4p)K3uTpELw{GDI6|_VG%JkE6}5KKYzq8 z9NKy3&Oxl$Hfn?Azm0@rReI)Ltpf5-@bF-=b!Jqb~|l5TZuY3D5AD>0DB2G z8tIzJE&fS!#CI`yN>?wM3Vdn&O)404Xd9n{_Yi0wwiMY}3a!>InD0Ea>h9e`1KYgx z{Gf2|FZCE3m~>stVZkzNF)_Y7olx3%kAJ*=|FMwmqrdFCHf)nJX+Ho{vgp3lMHC`& zw`Mr*)>IdA@J^U`#}wL$Zsw%DfVkx>hu9<%8~EB9SI|xdx-0^ZS6FaO;|1$pXUuxU zCG($C2H;#amd!ik(E?gAf3&Xv5(W%~?H+E{N7RSs?AvETyzl;>zu;_)0U z`a+=}8js)xEuI|IASI}Ja!~YboG>V>-la1fD~gz?=^B{apPoNPn_Ut@5OYhXsS=cv z%2yG~*HHdZEcY8DOn!wSbxy~o9*Cf~w6KRU5fAdvi(K@oBuBd()XDe~|3xaf8OzW; zrIKB+UGyxy6pwu}QisN2yU`|$_?iD|Lx7B3B=s@n#obckS?i1uUOU3Jvr^KJ+vw?| zffAZiKT}w5+SObu9PiE0lR+4jzDA=`>O_)nqaG-UuZz`Si{zEEO{xr zgPUX5)%lbmIE9Y^SV6iklQg{1tY}?O$XXgx)+sahxVqrQ8lr?_S$&jtI~*f2-Yl}U z6jV3LjCGFeI4Mv~oT^-ONjr;YEW^&?9;VQv#)a7Bx8=CBTnxpkx2fPpV=0;%K8&~c zu;UHyFJTA%XSfKUnA8H-!Sm7$x12e1cnc;f3lkG)zhk7T)}&Ic|PMGmHW`+xU$?GJUo24*%ww zG$QJf;R9LC?>HC2bIv6;ta+K)GLb=mn2EX+q`qQ zSTJbDmXCO8Q_inZWPF+yDJ=Rl!#Kzfg3k}VOR1CC_Co@A-`PxKTdHBR@$?AW(2b}xx08+RLu zogz~beidi)&jR58+5gUnEiLs zs&}hZ>vRv^Y*?vMO&4=?3}~1h7&&bWHV28J5AkXj7YjX<3PCFYl?^2t<2c-Vi#O{q zUTa)rIKAakgO)vT!$L{RbJ$&)122!{pf!a~Xozw572ZSONr{1C4eX-d8z{CYh4Nq2 zh&!ATX}>1c7xFbp$%93Jv$zP5SFyw?yAmQ_r!$FFu*5Xqz)#QrZpRlFc;fs6JHEVt z?H}*sc5IG&hfZ((h9BC7-JOkb`4b)L#o?p})0a%;`|O+}8f9z7geTg1Vo%{zVw z#^J|J>t-y%tsfh(A9qVIU*CRZ*sAt?9bWGV58`WAF5k5vjITZ;{Rv{&zp|S;bCC%=fj85HJ+xN0g?W zcfHa3s%1#3$ffJJ2NJilm&8nm)BqO|@)v8;yD%?eAXptGF2alpb%*2munE?*g))dL)?WKmuP7wrg&!3^mgolXxub@ z3p4)WbKeGH8eXu>rS)78Tii=B-qZ6UBis6S95rw#H!Pkr zW%fk#B)+6qL-R<#a_{p-8>+8v>c8rFzH-l^yLa~tAB5HLHJd)~x27BB!OL1Ui)ADD z=CJV-eZ`sRmz9o}ieBy%#ODuLzBXj-^5uL`%VFW+Ef=rkn*-aP$8OBN*faEN%3G1> zO;6b|X>(XroSYxO#$U`W=D5hqi%a%nBU!LwlSj;PfxjU7n#I{ZNBR1mSAvT4F42vj z7ev3SV(3NwnfXV*5j|Uu;icl6l`4Iz=}m6f_1l!0Vz8N;@ghSd-vBAc49Of8@ZQoD z6IO)=>^zW|_)QbO>Encxn+EW118ddnwu=9foKPMmag;RbrnsNa`D)|(1Gs9Y3U(++ z>=xGZuO%l$!M$Sywi2$k^hkQ6KgVKO7f6M&*iLnbDxlNo9TzYF)>79Dg3x%XI!2zPrvGx@z)N3#Km;<83Y#Y~1pSb{M z{iN$r;&nqntE9G;KHp&T?i;;cp3o5ksOkwCeTl6#l;0@F(U92w_^Pi&Dek&*e%)p z8;oJH2L&Wyqi{-I48P(ocL_Q#);%CL{Sx9{H|56k#97$r^8MGF4j=id+Y2wW>(-!Q z+fCnx@t=1k{PD+22{AD*)hu3oSIwVMCt5^EEu{V(rqjHhJ9iZv{w#HmT6s-v}} z1-owtO4H&Z!}tWlJHNkoa?IuK;$h7Eq=el`He5(C+)2*O#fA^Ah+((u{#1UUnTP+L z9P+!c|6y{DhkA}1Y;&AQ$#En(_!JlGi-oUXTRx9F#r--A9o%jB@JS!N5ymh2PH5Kn z{d%ENuSz6ERzQlZfD|!^ewexQmEwKz2K3)zviLX3PGIt@;=YtuamXa;{z=RIlS%Sv zbe%qwjM4|vChTw#143@}KNySkg(H{3D@jLV`NQCSN4~xBJsp-EgQ({m0 zntq@2?+;5|#kzRjy<@T7;RAw~mE(uR0(bBVNiP2N!6V;q>>P)zZ}O>cw-Ez-^NDjO z&k5T&eLnX)dCYguo>iaoQl%}Q{Em~#JpLQ0`-?UB)#QX|94Ql@#|EE)G&O>L$3Z@u zw(;Oa#ntAG!ZiFQCa4h*I?>rN z#ry%T5)Al>8eOz+QXJm=0UJ6j;vDtk`}55I0nO=1+!K?d@vR>)k?kiA;(otR`g!Iy zoQc0{dB0LpajYr@?n%~*ZLqPYx;Y>zIFMWN;6$@jf?M{X5#5Y4J$SF(as_%e*eB7@ z9x|fSZJtsD_KRut4$qj3hIs~HI$%Csg$;;=c>?q}_#FUqL6~EpBO<}*C?r>dl&K{Z z6XVKQdi=)YlT8g$LZp7lAD!ZN@NRa2t5Siak0Ej5#kCFavRJ>Q@KbnM%+T?*rCZG6 z8b9&p&pI^b;_BMGxwx6XHaLto?h}kPo!|M#8^W+btshTBe{BDvo&3(+E&QtQY<`2* zAbbz-^5=t4&T}G^Nj%A1n2&#ZJUSt5_`+{z@Iw;jRhrJ?CzE~o1XJm`xAUN0#d@84@MAK4p)cNsdDK?dHt#vA-JCQSoZ)!_}ggdqn9 z;pE;Ke#kHm*NLLGR*d0Nk2t2;e&hh z;G=OOwpF=u5C{$U1PngPVre=;+Q)lVtIz8SOh;d?<=J6dcF#c>E^v5y!4AJFq)6$r%tWoTg_YfbJ&3L z-HP9_10tH2lD^|7Eu~Rf8}nAubPNeEbFo(mK7YwVob31Ip+9}czgV#r7w&M(^~Li) zP$f&0Xu(@YqYG5{AfI?JnBPj$@w1jy;17Mg3YhtNp(;OtIEIv&iYrKBc*>wE{ICQ; zRH+VDJ%jkXPiCPgFX8>oP56>Ii@@uA9&-w9<`4P#x_#gA%H=NdUQL@L{-=4>@&0`M zwh%t3aS!Z`x{h?51pbPkgmvNx^Y$XG7xCkgg(u+v>hukhK|cm*I0JjM@%Ge3v|ag; z%Rit_vz~mxq=oP|na{3^Z7P^0vFtYR5x|QV$McoA)JZIVkGD6s2MrVOmjhSFfT&*6T! zr{UcX-sKm_Aw<1Y~^JQVnaEo?T+_lPi6Konu9(9H{PYK{j zTM>m7^Y~GS4>2-{lZS(AG_(FM)y8It96SiG8YU&;H2slUe8`aQyg`GLeAlXt5I)EGeOx5l!W^(- z#UkX}EzJ0y>l=gnvhbdRyZ2$yeLD~B&uV}MezL6K+RTE+ zUI!XNomwpmfg>xXK2`T&zJ0n6?#~K2`d8vZ@zXJbt~~zznI7?bUI>7>kP=2oM)n9< z-Y@?~ywFcRq4+Vgc<5#TsX$;+jC7!(V*?f6!SczM z$x1#gKS<-AC|`H>4If`x-Q}C`DKI~T>d!dKq2x{>aA1H9DSs#**yjLNPACDnmy7u# zeuO2k+(`N+olsm*PFHC_f1ZiQ7Ev1K_ z;wm8KzA%wX4wg@eKb0+iB^Ah?(tR@|$vk{DwT88RgFMukwBQLwP6Q82&HGN99%WEU4QokV=-kLjF`%nFvM{6Cccgt{vyrga4s#YR2=(^2_`yj$LGk74_kf6|x} ztUnht$YrquTd&y$#djcDvdPqAisPTIK$*? za$k8l%O-cD)I! z52I1$cc^tp{seYk$YaR{rt^U5Nb##m4ihD!wN3sG|HlD|@^RD=RbFnFKSH`5vQmcY zX25oEhBBM_GeR~TLd-;k64BaEQdr^pATal<^+hSs381|hCH8C8yOKWeML(p@cBDuS z>z88FS6&QzN{yXJi{0`MRyTPzO7!>g8hIUJz89{O01M=n@=AFpOrHZQN19py3)!Mj zq=db|gh9O->yO&>BCI4nN~7=MhgLq886z)8UPTGlu>!0p zl)#Fy;`j=O(z6m!KJZZzHl?8qtPGT&()aO)f9fYhL1kmnP)1e(inEGP*;ys19IP^w zfmMMDU@=fRSyiZ9tQu5qgdfZDfP>3S7kMS}3iFM;3T_MvRcgocAuK;or1m@zItP{P zPlKhyvlV_$$@j?( zsfNCc{80W2l<&abO|1{D8Cbso<9mdDoq80Co02k+N&ZSrMa+>lx8(Dn25GAOA>KRW zL-I%)**=wl+^wjme3PVM(u zeXm!1r!s=p?XaD13e_4mBs6|$OTv96WYu>9a395*T41U>slNB3yi(X{Ij1&J^?eEa zJxcpWoNrfJzAsfQjh;25I#iyw4N>2e&j-<3nk<$4UDIEa$ zR|J%cL4_!iIYen)@+p!zL}^Px6v-T_NM=Ei$vQlK;or^sXa+Kt&pJMH&Ypri~CglE#6G91c_@Z~;XE=TszcK}7=RQY3J0MFQthBye6u>V_!o zlR=TX`4H!6O6n|OUn3rndGa!OA{cACWoEy%uZ_}pPQLP}_kgm4GISfIL;xRt$O9UmcLaYvFlWcV8A`9Dkf5|7 z*3luQzrT{^)^_^w6gFy7m@BE8O-a>kN_u8fQZk#8lG&7W^HtK#prn|el1kZ`PUu9b zBn%anfwv&=`XTx@kK%8QUB>^A5vx&)KS6(M66DQ!j4Jmd9riu$lhTlWO21T_wlp^U z6ZP&Vs)M#4MjLC=+SuGwldT4VuDkfJ$rI&y$Wv;m0@3<$NX$!+xBJioRQQMNT#6WN z*K#560;h-3)7_5Lx(szypsXT~$)4s&vZM9PkG`07 zPRwdgshb12Spf2^Fv79U!G)#zqPz$|A0P;Q&?1T*&6tq9%!#}YMjy2(E7oIh=dSFG z!~bEgc4HTNIQZ{7ple_DOaIP&hq9ZF{s#>1)}P&T^gra){yo@V4*y^4GDKiQ9R3d+ zA{d6emi|AIj^-5UpJtG(vy~*3XhzDQq&1aSa-nugK&o)0RDH~r-V+Y!^64t;-qJ0B zTBqa#;R;AGn(3rDDj%9j1umIr9+gZwj6+_4PSj}jDgbT^bjt|{4|z}?C6VT2tr!9u z3VvwpQJ=M^Sz6G}gPbp-y9u6ivAnulik?q*N6`aye<(V&iaxsARyTxWU;(Gc?b|HrlAmkKs3Au$lLS7-C5Gdpq3J5_$ zun;1I3MQeT5GI&~LPBAoh)`50CKMOKg%UzZAwno6lorYeWrcD=q)=Xn5~76)LPepH zP+6!V#0XV|YC^0KCsY?|2=PKqp_Wja4HW7M^@RFD1EHbtobbHRNN6m)AT$wP6q*Xn zgyupEp{3ADXf3=Xv=Lqw+6wK2_QESd2ce_TN$4ze5xNT9*dU<}(t&cI6VjG?2$WCM z4Kdk`1LdsNmGVDVR1qbK7Ck>Fp|aS_Ol4xc2-V*ghlF$W0ZUh_B~h$KmlP9 zE39kEs=QCRnWI(t##i6mf(9ii_*WyS_^^r-p@h^ zM>iYxKLXkVHnR%4GpV`+x8GTLtXzcao3TdvdaQuYAn@{#<=2~_A7N2KcNXK*6mjX! zLWP^G7@(XmjK%AYfzC13OgCN8E9jOXPVc}E*{@*D1oYK}Z1P#erxDD}^nU_(DPVo7 zKi~;B@ZFnL6lSp?_^GQK!-DkRu~6MGmPa>=<=53?rG-h5*?+MX(2MA5vg$t3%wPB( zc$HaE-7J<@Ka#zq--7~ql7+#p7|MPZeRH-M`P5G5$6nXJBlrsQSXF%|riZza{vB2f zu$1k_tjBIvP-u(1Y72ds60Z`%CD6FUiVGHI0^}EZvLFRs2M)nd@H>=cr+fvpQgmzH zL?M5o^eB(I=UE{E<9y*D8==#)nm)mZQzDDjy~|1=|4o#(dViQFveMw?1HdT2I$c4O z!FO0W-3*i~g6u35acd38lM4NztIz~yf>Ei^9eNLdqC=7~KvD4W8iBroQg+{h`zwHV zbup{}^sb7T_-)Gkbk&(Jz6Swj+3P5)jR1{dKQ|SM>OW^j{b$SvJl6zl()qB505hO7 zpevvwU_Rgn!1sXVRBw>a)vPpx?7B8AShtns)DLEHu!{yzoIgng;$seAaw-giPEa=$ zUVv@}bON+Ug?`W-L36l804SU)faVCluyCIh6_Q!Fl1{~0DSbE~RoD5lt|-@Cb)hU4 z^|lJ)nHzO3Km3*g6jaLK9_9~oVL*_6k1!k19_Eh$n*b#N!(q2Uzeh)WBJM&3=zl_A z3IH#{JnJ{x4)e<}e+$?PSO(Y+*bVp*K=!+UGao?tkO-af3_80A$Oq^MSPW|63YY+h1*}We7eGfCgwNgvv;t5#ZvrT7S0XOeq3Z#IK{F>H z7(iho4hnpis_%h)Q^wsd;#v|Qr)&e2Yt2$uoZx~ z3V#FW`wajCP?-U3)(${)=KzKQD6U9nMW=5SMrh1KV5YbeECTcgP@0Seklz`A@qn2C zqP-EY0x%amOtDT`RGrL} zCX)g01KI$d2XsySCO7a2S!higN*{t30ZRa6{}Z4ypbuaTpcY^@zya@6{@4}7aV>!A z0pd&f$!-HC0lEQN0uBRyPsIy|nbL#eMR6Pe7zKC^Ky_s&+NmI2bJj$-&YI}v!;Ddc zt_2Iz?S}pfWHRPkbu9tYP|v!uINi4}H-x;rhPwMH%yj@QP$w(1oVqt5n*vyIT_4c7 z&Z2b5tPtvVIOsPJ9?GJwE(;eze)E(Vrw4q8l6pkal0HsW#T-txD_M{7_+XSke z{r4mLuWUGv>?m!i+&cjQ{siEq(aA0qocZ;LTW#>y956<>rpWczU|tQV4|oCa5}+Yq z9H1{C3_!BI5rE2~Jsy=)YJ*5-Z3d9MXp#C&a)9Vj`JVwGSw&@>%J)RT7(fjG$+A^| zCIG5K6b|vy1F#%G^@jK^3?Say11bZi09pger$U@wukbq*-&Fw=29^D00E*LF0HUkb zq1`Zl0jLR}dQ5aG0*KE<0Qr3tFdR@;|G6ydHZec+8w;WzmshtCeWjcz-{{Bc5}2R< z6v`yEwas8x4gDo+d~(6B7qn>*hW-J@_j>eSb@x$6$y|UH(YHoFpgG#`Nc5lMA!BNx ze_0vnSw;Sv$*iGpmPHGHvv{Ers|~s1ud5`>`uT8gg}!es*!N?(bX8z(CsW>0K6*iu z2J9-vFZEfV&mH=7;s9sQgxdZqduoW;6K<-pOI{>II%>!=;<4j}nN zeC`EY1-uQ21W?>bR+3C<1R$Cer)mI7x4r;MyTO120HxO~0HqOyOMJhU`b}mEep0i03| zlnzwBZUA}%z5sj-NB}GcP`(q8pM`)S0Q7AzcA-8A^*N|tat``B^aH400?_wj*>u6^ zSA5G}RDfjhd-7jO--P-s)Gyfto%$vH&=F#lc53%p)P!E6LVQ_BYBxx1jHlb+dK+Ue0y+kLNY>jPyrEojU`Wx`dU z{7~z(E4nJDo#|SdB*RF?WCV`rIr2~VnN6erlD`&62a@TIfXYLwECRJn8G)m4sNJKs z#~sKhEOK{+u1e>>l;2s2OE07w_2)7IM|tUPIa1T#nNDH3l9%a~A7^w`xAbVMZdpmo zf16+GLuQoksypR#BNrgOw%p#1@~x>GVDCS@Z9w8d**T-Db#sNL zivRym9^5GlG$%mwJ+1)Fb7cftdKrxcXpErJqj>;FV+Ln=77c&S++A^_w$WLipa$G& zPR(5)f7&O&y$L$)$Msw-BcR%O?=V3p9(6@ zv!+uzJ!?GK^Fwu@t{psQ_pQ2@g1yNFFasyl2@s7)0Iiid1A995yu0#U5n&Lxg6jw; zy?(JH-1O|pKdmD;0+K&eRw@Ikr2^Fh6=;54wI@8)Ozvc+Ie5w=nzN!gZ#BQPx;6}z zu1ZIxsoE1gEv=XEO>QJZ;!{COo93TXd&1MsUy(h1XT+l#h8m75^a+RPldkeid~5xZ zIlVmb+C6*eLVfdE0LoMQJ^|$`0lBMYRZq`Ob#tUsIiqr~0@X3qtm@9_YW)*lMsvF4 zuJxmaq1BzyA;16cWtQeYsGmmtJV*UCdwXiLN;rWs8aFe{VHtpy9<^cQ-x;VhRou+v zVL616*?AaO!lU+y`c%%qSzWNNW3iw`<<%KDqDSplMs+D8`dS*)#;JU`k{16q9O|oS z%eHzPXa|5?owlHHl%tt0$7TazSrSLQ?1 zc?D;>N~;@awsirV(IPi39Thh-Y4C6G(+lzK-~^~&t8KqCGDibHDg#hyQooh@B+eis zdL#!O`M3A`EaV5tb$9t7`A2PuBOv*qjsYF%#eh>X15oME8oaZ)4{|G#0jh>TL!2M*w0~R_1l#> zH5Esl+wz32()6_M3EteH;mZ7>BOG_a$q3g`7@4upC@fF8du5terg_VNw+y&j2Ar)w zxZ~z(+v6#DM|4~b(-U}}<;13da?mJc-j3@yiN4OT4%m4^Q&!3N2^##_Q&l ztKKq@aT%xtIYp3BTBV1h+NpX*H2zKQ6em~Wl=V_pQKUsmSj(4>Fv%*J4 zezoEJ6XrHZS5JVadG!QODh*HbW>4?mRM)+{W-R}`Y2;0#r%?vlLl%1yT7jOsU@zM; z`|WPH?&4>bugvYiz>e|N&o3a&OxPnomAPiFi+t$OJV*V`s| zx(rmn7{${xz4SbrrqTa!9=W=|#Z|nF?$mJPPUVR1B~;6k)~wpu>yB_7g^^i%HC%0Y zTC?izNGIHk@YCZ>rAKaLR&i8&Pv|ObEiE;i^mG+Z^{3TKgU2TcYS>=gR!_WX;Z2MG zr!qkIX=#D(jYv3L`vEK}KPD!kzB<^c26Y z(D^6xm&(qo+;7N~r4uT03WEXZR`|Rd+_`-{j^j&f0i5 z!&B2l)r%v|Jqa!p6O)GC&J;^dq3-ZAJemVQ~IIX+trnPg|O!AuUhb7(KtlHV@T70dWyJ5S6uhQ3s zsWq$aTHW5AzE#lTsb+WYn{$M((({z=D4eX=dx|$#=sd}~;-&4C#ojXT-!21L*(*^3 zGC!*j1{$7%tn%WDf0{e<6u+*}DTDAl1+IkW2^>%Hn-QIVIxqfBvQV8HdD8m7DNX*1 zysGbfJ?VT_>D#BFBYS&1_1hUfxe=bKtA75gy0f%MFV4>J)ihJ}@<>Ndfh%LkjBsjz zA5TF>VP)1m)`L8{64$JZG41`j5}rFa_Vk~`w>$h~7B{_m6k7>O5>&@S%Q3e{L z{m_D=cE}!wz6n>=Gy7(jBY&Qh-HyWWq&?k9=SiM3qGkW4S7yI63dddd%<|#LpS$5_ z1^;Q(KW~^`x&Lo01GLVgOXG zvn#aPB5s}lSHf}!#}hndM8h3^vVyDD6R)1W{P3oWH(k7CAnRqI17x`;!IeEQ&Tyi@ zkEg&{IG%Ki_8`x$#9iID-%Rtu30PS`5 zBse?cl0JpD9xC0*?M`&s)w!=i*wSOMLB7NTdY3KMcM;lbb8_1E>+JKw^cV&SRgX?KKcOI)j*mwWp6>PV#Qep)+trhWHs3!sD@CT!QtzyC)C?%)XQuK+bgsa+5v-9 zdq778maq@l6gHpLLHsF~>QP$bEB&(YSDLa=L*bS9rE)=KVIIoDJP(zHI>ZMcUg3wz zLLK_nsz+s^GL;BxS&)wjM!}!`CFDlIzk>hVLh2880t)^G*cgOtf-k$z9x_?rLJs7r zEa-%sY%xklTJ=lnw?$}bH3_YRZ^RwY!^mIgAbJLqMh@FkRj&F4Y|;TlB5HTtLDBmFGQX9fH#wy8Soj#_PCx}55E zS!-uAKf*gIC`$cys1HH?8iEw;Bt)Zzb%pB2Itx+Yu!0c9dOx!3DpbOECzRf04nsCyV9&D$>=kg_Ns(S{kQZIic5P;r*^4X)<)9lRaVSbpS4C>J zfNd*QQFx1e2dtG)R9jj@UJe9}g~;hR)W8LBs|o1}1zG()JB55N#lnI238;04jJ2SY zJcN&ntS#zVd$bmv**JC&rR8;$mzvaS65NN|E8wv;=yyg+w_%0Z zZL~x^AkV4BFJk4vNi8;m1%PHHlIubwX!=4nmsF&AclHb9Y8^I*eFZLBgM(&l09yyw zLP8Pt4O`3FF*7LcWuu{nvssWcUD1YJMJ|5{O8pVLciBOqHrkGk>^HUq7)2qgEJ_-v zvcv~pBt7(stxcA6Q@)!$vQ;HdS75)2cCb2XB(=$9SReeCg(U8#d@FWj4^;)VsKp~& zwFM`aD6JHHrp!%IBGOlB+lY+5Y;@{7phqRonX>w`(Xnym%-552OOF@lv1p3kq>XRY zlo5~hQAbqVw0cH9|9SWNPV-R9Pg+dp=|=vv7-{`#sXj~QW)5;q8xt+R%~%6FA6i${ zY{N;9zKZov=(g}}q1m{jl4`RjlMUZmiqpD2%`ewD(_%GpA*bwdwEk`N_-V#l4Ld!~ zR5z_|!?TZ@Ek5?SPX2A!HVRt0&r18(2y+E#m6l7Jneb}aVcPuJ@Klo)H*FXy#*^0V zLw!63#G?)CN%NC+`jyk|rAMQuYE@}NP;E=0XPkCaQpWCEbtOuUXb?56KYN;Cc0SY6 z$^2K0GG{~cHmZtd5sI?Xw3;JW3@i5tgD?rpicth^s$Z*~mO|!vd)hv0v9eH+ssC1; zY}}PCS~}#vS}H{{tIEB&+Ea*RbSsh%_17>R|LOTv z@l=25g;V~C)G_-I(`(I$<2a0hRjx=^W6=;ZfmVCf#-^8IMblB`mDy98K~+_G4c6m+ z?D4JGR@)LRR~l6Ua{wVwsve?z6IQ`Ac)1`GLLk#j(5*hKm^LhX%8&C^^idkvV(dv% zBh*B#N{@CUw8~nXYEF4lahs*_lOEkCVQ1?JspTkbD9tpzCPyVI{hn3&^wLuQC%#&z zsUfyHVzX~-he4dDX)CRwc1YP#mQ{Tv3D*=@8F~6P_*x(Fq5g zw6%-AB9!_?bu0vJu2m07V@tJ9^=GS3R-0n!_^{bosipN}qovZc>RLYRyCUqdHeMF$(-$z=hoE_GRJ>LzFZCc--TDfPAdMpxOauyjPmtyiSG*4Cxw$S zx0%IwQXIQWH?#aZ_vbDb?%_YnBPaJ_k~!@E_xNWn)x5sEDe&y2z|)kYnMn=j{ASfP zGaNl>KUs~_%O$*?9Au$rF5en#O-ScAieH{|Y@dOC4(Kh!4?_p~(K=gI5i$)$k0Z`HAG+XL&0$sJBzp{L?F=FdGBm7Y8L zlZcahT)Tp8+r#Wm-0XKNyAxM0Zq`yDM_=kLZddip@a`&YE1n}xJ!M}G zd*>n)aLgBBXjNunojE^g_tJYR&MF;koLn)x7Ke;Wq-%8kJ6P)8ecEMDO8q8NdQ?#Doa-uY>Bqv#zsfJ++Tvif zbxz&u`gBqtquIQt!`0)VX2fS^+#e6+>Dy!`95&I4b>+M<<{h^PG7XTPUuZ{*AGv zQ=F7@_PLif){ncoQX19z>(!rB3Zy-k>iFwPg`X9=j=A-OOU9i2bF&$qh)?=7GLEGe zI$u=iDTo` znaQ0p?OJU9OOnd97-t^KmHu{7+$TXdQ - #FFBB86FC - #FF6200EE - #FF3700B3 - #FF03DAC5 - #FF018786 #FF000000 #FFFFFFFF + + #10B981 + #FF6C6C + #F59E0B + + #444444 + #7C7C7C + #CCCCCC + #E9EAEC + + #1F1F5C + #333399 + #4C4CBB + #6666DD + #8080FF + #9999FF + #B3B3FF + #CCCCFF + #E6E6FF + + #17181B + #36393F + #FFFFFF \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index f8c6127..1af7af7 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,10 +1,28 @@ - #FFBB86FC - #FF6200EE - #FF3700B3 - #FF03DAC5 - #FF018786 #FF000000 #FFFFFFFF + + #10B981 + #FF6C6C + #F59E0B + + #444444 + #7C7C7C + #CCCCCC + #E9EAEC + + #1F1F5C + #333399 + #4C4CBB + #6666DD + #8080FF + #9999FF + #B3B3FF + #CCCCFF + #E6E6FF + + #F5F5F5 + #FFFFFF + #36393F \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8a5d69e..eee5e4d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2,6 +2,7 @@ 삼품관리 + 뒤로가기 대시보드 출고목록 장바구니 @@ -9,10 +10,32 @@ 로그인 - 이메일 - 비밀번호 + 이메일 + 비밀번호 + 이메일 입력 + 비밀번호 입력 로그인 로그인 중… + 계정이 없으신가요? + 회원가입 + 하기 + + + 회원가입 + 이름 + 지점 + 직급 + 이메일 + 비밀번호 + 비밀번호 확인 + 이름 입력 + 지점 선택 + 직급 선택 + 이메일 입력 + 비밀번호 입력 + 비밀번호 입력 확인 + 회원가입 + 회원 가입 중… 부품 목록 @@ -21,4 +44,15 @@ 오류가 발생했습니다 다시 시도 + + + 이메일을 입력해주세요 + 올바른 이메일 형식이 아닙니다 + 비밀번호를 입력해주세요 + 비밀번호는 최소 8자 이상이어야 합니다 + 비밀번호는 최대 30자까지 가능합니다 + 영문, 숫자, 특수문자를 각각 1개 이상 포함해야 합니다 + 비밀번호 확인을 입력해주세요 + 비밀번호가 일치하지 않습니다 + %s을(를) 입력해주세요 \ No newline at end of file From ddff298d961a8ec217e8089bce89974b54177902 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Wed, 15 Oct 2025 23:19:56 +0900 Subject: [PATCH 15/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EC=BD=94=EB=93=9C=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/AppNavHost.kt | 2 +- .../android/core/ui/component/CommonButton.kt | 3 ++ .../core/ui/component/CommonSnackBar.kt | 3 +- .../com/sampoom/android/core/ui/theme/Type.kt | 31 ++++++++++--------- app/src/main/res/values/strings.xml | 1 + 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 2008a79..d167d4b 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -73,7 +73,7 @@ fun AppNavHost() { SignUpScreen( onSuccess = { navController.navigate(ROUTE_HOME) { - popUpTo(ROUTE_SIGNUP) { inclusive = true } + popUpTo(ROUTE_LOGIN) { inclusive = true } } }, onNavigateBack = { diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt b/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt index 077e436..b055bcd 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt @@ -113,6 +113,7 @@ fun CommonButton( disabledContentColor = textSecondaryColor() ) ) { + if (leadingIcon != null) leadingIcon() content() } } @@ -129,6 +130,7 @@ fun CommonButton( disabledContentColor = textSecondaryColor() ) ) { + if (leadingIcon != null) leadingIcon() content() } } @@ -147,6 +149,7 @@ fun CommonButton( disabledContentColor = textSecondaryColor() ) ) { + if (leadingIcon != null) leadingIcon() content() } } diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/CommonSnackBar.kt b/app/src/main/java/com/sampoom/android/core/ui/component/CommonSnackBar.kt index eb1e478..34bfee0 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/CommonSnackBar.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/CommonSnackBar.kt @@ -31,6 +31,7 @@ import androidx.compose.ui.res.painterResource import com.sampoom.android.R import androidx.compose.material3.Text import androidx.compose.material3.TextButton +import androidx.compose.ui.res.stringResource @Composable fun rememberCommonSnackBarHostState(): SnackbarHostState = remember { SnackbarHostState() } @@ -98,7 +99,7 @@ fun TopSnackBarHost( IconButton(onClick = { data.dismiss() }) { Icon( painter = painterResource(id = R.drawable.outline_close), - contentDescription = null, + contentDescription = stringResource(R.string.common_close), tint = textColor() ) } diff --git a/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt b/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt index 0d4c3a4..1f6de4f 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt @@ -16,20 +16,21 @@ val GmarketSansFamily = FontFamily( ) // Set of Material typography styles to start with +private val baseTypography = Typography() val Typography = Typography( - displayLarge = TextStyle(fontFamily = GmarketSansFamily), - displayMedium = TextStyle(fontFamily = GmarketSansFamily), - displaySmall = TextStyle(fontFamily = GmarketSansFamily), - headlineLarge = TextStyle(fontFamily = GmarketSansFamily), - headlineMedium = TextStyle(fontFamily = GmarketSansFamily), - headlineSmall = TextStyle(fontFamily = GmarketSansFamily), - titleLarge = TextStyle(fontFamily = GmarketSansFamily), - titleMedium = TextStyle(fontFamily = GmarketSansFamily), - titleSmall = TextStyle(fontFamily = GmarketSansFamily), - bodyLarge = TextStyle(fontFamily = GmarketSansFamily), - bodyMedium = TextStyle(fontFamily = GmarketSansFamily), - bodySmall = TextStyle(fontFamily = GmarketSansFamily), - labelLarge = TextStyle(fontFamily = GmarketSansFamily), - labelMedium = TextStyle(fontFamily = GmarketSansFamily), - labelSmall = TextStyle(fontFamily = GmarketSansFamily) + displayLarge = baseTypography.displayLarge.copy(fontFamily = GmarketSansFamily), + displayMedium = baseTypography.displayMedium.copy(fontFamily = GmarketSansFamily), + displaySmall = baseTypography.displaySmall.copy(fontFamily = GmarketSansFamily), + headlineLarge = baseTypography.headlineLarge.copy(fontFamily = GmarketSansFamily), + headlineMedium = baseTypography.headlineMedium.copy(fontFamily = GmarketSansFamily), + headlineSmall = baseTypography.headlineSmall.copy(fontFamily = GmarketSansFamily), + titleLarge = baseTypography.titleLarge.copy(fontFamily = GmarketSansFamily), + titleMedium = baseTypography.titleMedium.copy(fontFamily = GmarketSansFamily), + titleSmall = baseTypography.titleSmall.copy(fontFamily = GmarketSansFamily), + bodyLarge = baseTypography.bodyLarge.copy(fontFamily = GmarketSansFamily), + bodyMedium = baseTypography.bodyMedium.copy(fontFamily = GmarketSansFamily), + bodySmall = baseTypography.bodySmall.copy(fontFamily = GmarketSansFamily), + labelLarge = baseTypography.labelLarge.copy(fontFamily = GmarketSansFamily), + labelMedium = baseTypography.labelMedium.copy(fontFamily = GmarketSansFamily), + labelSmall = baseTypography.labelSmall.copy(fontFamily = GmarketSansFamily) ) \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index eee5e4d..5de1348 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -44,6 +44,7 @@ 오류가 발생했습니다 다시 시도 + 닫기 이메일을 입력해주세요 From 4d0f07b807942270064471502e8b4cb57d812ee6 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Wed, 15 Oct 2025 23:28:50 +0900 Subject: [PATCH 16/88] =?UTF-8?q?[REFAC]=20SharedPreference=20->=20DataSto?= =?UTF-8?q?re=20=EA=B5=90=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 3 ++ .../android/core/network/NetworkModule.kt | 12 +++-- .../feature/auth/data/local/database/.gitkeep | 0 .../data/local/preferences/AuthPreferences.kt | 45 +++++++++++++------ .../data/repository/AuthRepositoryImpl.kt | 4 +- .../android/feature/auth/ui/LoginScreen.kt | 5 ++- .../android/feature/auth/ui/SignUpScreen.kt | 5 ++- app/src/main/res/drawable/outline_close.xml | 2 +- gradle/libs.versions.toml | 2 + 9 files changed, 56 insertions(+), 22 deletions(-) delete mode 100644 app/src/main/java/com/sampoom/android/feature/auth/data/local/database/.gitkeep diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9ccbfc2..657ad40 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -78,6 +78,9 @@ dependencies { implementation(libs.retrofit) implementation(libs.converter.gson) + // DataStore + implementation(libs.androidx.datastore.preferences) + implementation(libs.androidx.core.splashscreen) implementation(libs.androidx.material) implementation(libs.androidx.material.icons.core) diff --git a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt index 93cef46..1258593 100644 --- a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt +++ b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt @@ -8,6 +8,8 @@ import okhttp3.OkHttpClient import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import javax.inject.Singleton +import com.google.gson.GsonBuilder +import com.google.gson.FieldNamingPolicy @Module @InstallIn(SingletonComponent::class) @@ -15,10 +17,14 @@ object NetworkModule { @Provides @Singleton fun provideOkHttp(): OkHttpClient = OkHttpClient.Builder().build() @Provides @Singleton - fun provideRetrofit(client: OkHttpClient): Retrofit = - Retrofit.Builder() + fun provideRetrofit(client: OkHttpClient): Retrofit { + val gson = GsonBuilder() + .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .create() + return Retrofit.Builder() .baseUrl("https://sampoom.store/api/") .client(client) - .addConverterFactory(GsonConverterFactory.create()) + .addConverterFactory(GsonConverterFactory.create(gson)) .build() + } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/local/database/.gitkeep b/app/src/main/java/com/sampoom/android/feature/auth/data/local/database/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/local/preferences/AuthPreferences.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/local/preferences/AuthPreferences.kt index 9dc479f..789a143 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/local/preferences/AuthPreferences.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/local/preferences/AuthPreferences.kt @@ -1,31 +1,50 @@ package com.sampoom.android.feature.auth.data.local.preferences import android.content.Context -import androidx.core.content.edit +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.stringPreferencesKey +import androidx.datastore.preferences.preferencesDataStore import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.runBlocking + +// Per official guidance, DataStore instance should be single and at top-level. +private val Context.authDataStore by preferencesDataStore(name = "auth_prefs") @Singleton class AuthPreferences @Inject constructor( @param:ApplicationContext private val context: Context ){ - private val sharedPreferences = context.getSharedPreferences("auth", Context.MODE_PRIVATE) + private val dataStore = context.authDataStore + + private object Keys { + val ACCESS_TOKEN: Preferences.Key = stringPreferencesKey("access_token") + val REFRESH_TOKEN: Preferences.Key = stringPreferencesKey("refresh_token") + } - fun saveToken(accessToken: String, refreshToken: String) { - sharedPreferences.edit { - putString("access_token", accessToken) - putString("refresh_token", refreshToken) + // Suspend save to avoid blocking thread + suspend fun saveToken(accessToken: String, refreshToken: String) { + dataStore.edit { prefs -> + prefs[Keys.ACCESS_TOKEN] = accessToken + prefs[Keys.REFRESH_TOKEN] = refreshToken } } - fun getAccessToken(): String? = sharedPreferences.getString("access_token", null) - fun getRefreshToken(): String? = sharedPreferences.getString("refresh_token", null) + // Synchronous getters backed by runBlocking for minimal surface change + fun getAccessToken(): String? = runBlocking { + dataStore.data.first()[Keys.ACCESS_TOKEN] + } + + fun getRefreshToken(): String? = runBlocking { + dataStore.data.first()[Keys.REFRESH_TOKEN] + } - fun clear() { - sharedPreferences.edit { - clear().apply() - } + suspend fun clear() { + dataStore.edit { it.clear() } } - fun hasToken(): Boolean = !sharedPreferences.getString("access_token", null).isNullOrEmpty() + + fun hasToken(): Boolean = !getAccessToken().isNullOrEmpty() && !getRefreshToken().isNullOrEmpty() } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt index fedff45..673d57a 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt @@ -41,9 +41,7 @@ class AuthRepositoryImpl @Inject constructor( return dto.data.toModel() } - override suspend fun signOut() { - preferences.clear() - } + override suspend fun signOut() { preferences.clear() } override fun isSignedIn(): Boolean = preferences.hasToken() } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt index 96fa07a..36ed2a9 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt @@ -59,7 +59,10 @@ fun LoginScreen( val state by viewModel.state.collectAsState() - if (state.success) onSuccess() + LaunchedEffect(state.success) { + if (state.success) onSuccess() + } + val snackBarHostState = rememberCommonSnackBarHostState() ShowErrorSnackBar( errorMessage = state.error, diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt index 713ac4b..172037c 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt @@ -61,7 +61,10 @@ fun SignUpScreen( val state by viewModel.state.collectAsState() val labelTextSize = 16.sp - if (state.success) onSuccess() + LaunchedEffect(state.success) { + if (state.success) onSuccess() + } + val snackBarHostState = rememberCommonSnackBarHostState() ShowErrorSnackBar( errorMessage = state.error, diff --git a/app/src/main/res/drawable/outline_close.xml b/app/src/main/res/drawable/outline_close.xml index 4f9d73e..dc414f5 100644 --- a/app/src/main/res/drawable/outline_close.xml +++ b/app/src/main/res/drawable/outline_close.xml @@ -1,4 +1,4 @@ - + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3c44195..5b479e3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,7 @@ [versions] agp = "8.13.0" coreSplashscreen = "1.0.1" +datastorePreferences = "1.1.7" hiltAndroid = "2.57.2" hiltNavigationCompose = "1.3.0" kotlin = "2.2.20" @@ -19,6 +20,7 @@ retrofitVersion = "3.0.0" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-core-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "coreSplashscreen" } +androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" } androidx-hilt-lifecycle-viewmodel-compose = { module = "androidx.hilt:hilt-lifecycle-viewmodel-compose", version.ref = "hiltNavigationCompose" } androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hiltNavigationCompose" } androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" } From 2e2a64bd8461eb3be681976931bde1045a1b386f Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Wed, 15 Oct 2025 23:49:47 +0900 Subject: [PATCH 17/88] =?UTF-8?q?[FIX]=20OKHttp=20=EC=84=B8=ED=8C=85=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 4 ++++ .../android/core/network/NetworkModule.kt | 16 +++++++++++++++- .../android/core/ui/component/CommonButton.kt | 5 +---- .../com/sampoom/android/core/ui/theme/Type.kt | 3 --- gradle/libs.versions.toml | 2 ++ 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 657ad40..0ba8b70 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -54,6 +54,7 @@ android { } buildFeatures { compose = true + buildConfig = true } } @@ -78,6 +79,9 @@ dependencies { implementation(libs.retrofit) implementation(libs.converter.gson) + // OKHttp + implementation(libs.logging.interceptor) + // DataStore implementation(libs.androidx.datastore.preferences) diff --git a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt index 1258593..fb48025 100644 --- a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt +++ b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt @@ -10,11 +10,25 @@ import retrofit2.converter.gson.GsonConverterFactory import javax.inject.Singleton import com.google.gson.GsonBuilder import com.google.gson.FieldNamingPolicy +import com.sampoom.android.BuildConfig +import okhttp3.logging.HttpLoggingInterceptor +import java.util.concurrent.TimeUnit @Module @InstallIn(SingletonComponent::class) object NetworkModule { - @Provides @Singleton fun provideOkHttp(): OkHttpClient = OkHttpClient.Builder().build() + @Provides @Singleton fun provideOkHttp(): OkHttpClient = OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .writeTimeout(30, TimeUnit.SECONDS) + .addInterceptor(HttpLoggingInterceptor().apply { + level = if (BuildConfig.DEBUG) + HttpLoggingInterceptor.Level.BODY + else + HttpLoggingInterceptor.Level.NONE + }) + // TODO: 로그인 기능 연동 후 인증 인터셉터 추가 필요 + .build() @Provides @Singleton fun provideRetrofit(client: OkHttpClient): Retrofit { diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt b/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt index b055bcd..ca17eca 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt @@ -1,11 +1,8 @@ package com.sampoom.android.core.ui.component -import android.R.attr.onClick -import android.R.attr.text import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.FilledTonalButton @@ -126,7 +123,7 @@ fun CommonButton( shape = shape, modifier = modifier.height(height), colors = ButtonDefaults.textButtonColors( - contentColor = disableColor(), + contentColor = textSecondaryColor(), disabledContentColor = textSecondaryColor() ) ) { diff --git a/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt b/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt index 1f6de4f..8643dc7 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt @@ -1,12 +1,9 @@ package com.sampoom.android.core.ui.theme -import android.R.attr.fontFamily import androidx.compose.material3.Typography -import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.sp import com.sampoom.android.R val GmarketSansFamily = FontFamily( diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5b479e3..3d5c222 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,6 +12,7 @@ espressoCore = "3.7.0" lifecycleRuntimeKtx = "2.9.4" activityCompose = "1.11.0" composeBom = "2025.10.00" +loggingInterceptor = "5.2.1" material = "1.9.3" materialIconsCore = "1.7.8" navigationCompose = "2.9.5" @@ -43,6 +44,7 @@ androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "u androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" } +logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "loggingInterceptor" } retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofitVersion" } [plugins] From af51b99a5a71f9578805852a3f4da41161d1ddb6 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Wed, 15 Oct 2025 23:54:58 +0900 Subject: [PATCH 18/88] =?UTF-8?q?[FIX]=20=ED=8F=B0=ED=8A=B8=20Weight=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt b/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt index 8643dc7..ed5af64 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt @@ -8,7 +8,7 @@ import com.sampoom.android.R val GmarketSansFamily = FontFamily( Font(R.font.gmarket_sans_light, FontWeight.Light), - Font(R.font.gmarket_sans_medium, FontWeight.Normal), + Font(R.font.gmarket_sans_medium, FontWeight.Medium), Font(R.font.gmarket_sans_bold, FontWeight.Bold) ) From f791c1bb2130187bd1346345cf794076cbd648af Mon Sep 17 00:00:00 2001 From: Choosla Date: Thu, 16 Oct 2025 09:04:32 +0900 Subject: [PATCH 19/88] chore: Apply batch updates from central configuration --- .github/workflows/pr-reminder.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/pr-reminder.yml b/.github/workflows/pr-reminder.yml index d2410b3..c58e365 100644 --- a/.github/workflows/pr-reminder.yml +++ b/.github/workflows/pr-reminder.yml @@ -11,3 +11,5 @@ jobs: secrets: # 해당 시크릿은 조직의 시크릿에 저장되어 있음 SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + # 조직 변수 전달 + SLACK_USER_MAP: ${{ vars.SLACK_USER_MAP }} From 586171c90153147940de48ed0ac843f66f43d8e5 Mon Sep 17 00:00:00 2001 From: Choosla Date: Thu, 16 Oct 2025 14:25:23 +0900 Subject: [PATCH 20/88] chore: Apply batch updates from central configuration --- .github/workflows/pr-reminder.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr-reminder.yml b/.github/workflows/pr-reminder.yml index c58e365..e4b028b 100644 --- a/.github/workflows/pr-reminder.yml +++ b/.github/workflows/pr-reminder.yml @@ -2,14 +2,15 @@ name: PR Reminder on: schedule: - - cron: "47 23,4,7,8,10 * * *" # 아침 8시 47분, 오후 2시 47분, 오후 4시 47분, 오후 5시 47분, 오후 7시 47분 에 실행 (UTC 기준으로 설정해서 한국 시간에 맞춤) + - cron: "47 23,4,7,8,10 * * *" workflow_dispatch: jobs: call-reusable-reminder: + secrets: inherit uses: 33-Auto/.github/.github/workflows/reusable-pr-reminder.yml@main - secrets: - # 해당 시크릿은 조직의 시크릿에 저장되어 있음 + with: + # 시크릿 전달 SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} - # 조직 변수 전달 - SLACK_USER_MAP: ${{ vars.SLACK_USER_MAP }} + # 변수 전달 + SLACK_USER_MAP: ${{ vars.SLACK_USER_MAP }} \ No newline at end of file From 0c069c12af53f9744989eb0cd5ac1772a348eae2 Mon Sep 17 00:00:00 2001 From: Choosla Date: Thu, 16 Oct 2025 14:32:59 +0900 Subject: [PATCH 21/88] chore: Apply batch updates from central configuration --- .github/workflows/pr-reminder.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr-reminder.yml b/.github/workflows/pr-reminder.yml index e4b028b..8958a9c 100644 --- a/.github/workflows/pr-reminder.yml +++ b/.github/workflows/pr-reminder.yml @@ -7,10 +7,10 @@ on: jobs: call-reusable-reminder: - secrets: inherit uses: 33-Auto/.github/.github/workflows/reusable-pr-reminder.yml@main - with: - # 시크릿 전달 + + secrets: + # 조직 시크릿을 secrets 입력으로 전달 SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} - # 변수 전달 + # 조직 변수를 secrets 입력으로 전달 SLACK_USER_MAP: ${{ vars.SLACK_USER_MAP }} \ No newline at end of file From 6dda38439f24cec4feebd21d28a4495ac53b8d30 Mon Sep 17 00:00:00 2001 From: Choosla Date: Thu, 16 Oct 2025 14:36:16 +0900 Subject: [PATCH 22/88] chore: Apply batch updates from central configuration --- .github/workflows/pr-reminder.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-reminder.yml b/.github/workflows/pr-reminder.yml index 8958a9c..25ba9eb 100644 --- a/.github/workflows/pr-reminder.yml +++ b/.github/workflows/pr-reminder.yml @@ -13,4 +13,4 @@ jobs: # 조직 시크릿을 secrets 입력으로 전달 SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} # 조직 변수를 secrets 입력으로 전달 - SLACK_USER_MAP: ${{ vars.SLACK_USER_MAP }} \ No newline at end of file + SLACK_USER_MAP: ${{ secrets.SLACK_USER_MAP }} \ No newline at end of file From 81dbb20df636cf78464787a4d2abcc16e999bb21 Mon Sep 17 00:00:00 2001 From: Choosla Date: Thu, 16 Oct 2025 15:13:51 +0900 Subject: [PATCH 23/88] chore: Apply batch updates from central configuration --- .github/workflows/pr-reminder.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pr-reminder.yml b/.github/workflows/pr-reminder.yml index 25ba9eb..311c71b 100644 --- a/.github/workflows/pr-reminder.yml +++ b/.github/workflows/pr-reminder.yml @@ -2,15 +2,12 @@ name: PR Reminder on: schedule: - - cron: "47 23,4,7,8,10 * * *" + - cron: "47 23,4,7,8,10 * * *" # 아침 8시 47분, 오후 2시 47분, 오후 4시 47분, 오후 5시 47분, 오후 7시 47분 에 실행 (UTC 기준으로 설정해서 한국 시간에 맞춤) workflow_dispatch: jobs: call-reusable-reminder: uses: 33-Auto/.github/.github/workflows/reusable-pr-reminder.yml@main - secrets: - # 조직 시크릿을 secrets 입력으로 전달 - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} - # 조직 변수를 secrets 입력으로 전달 - SLACK_USER_MAP: ${{ secrets.SLACK_USER_MAP }} \ No newline at end of file + # 해당 시크릿은 조직의 시크릿에 저장되어 있음 + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} \ No newline at end of file From d4258369dbaec7b9b10ac0e1216ab488c84c352a Mon Sep 17 00:00:00 2001 From: Choosla Date: Thu, 16 Oct 2025 15:22:20 +0900 Subject: [PATCH 24/88] chore: Apply batch updates from central configuration --- .github/workflows/pr-reminder.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-reminder.yml b/.github/workflows/pr-reminder.yml index 311c71b..87dc299 100644 --- a/.github/workflows/pr-reminder.yml +++ b/.github/workflows/pr-reminder.yml @@ -10,4 +10,5 @@ jobs: uses: 33-Auto/.github/.github/workflows/reusable-pr-reminder.yml@main secrets: # 해당 시크릿은 조직의 시크릿에 저장되어 있음 - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} \ No newline at end of file + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + SLACK_USER_MAP : ${{ vars.SLACK_USER_MAP }} \ No newline at end of file From b2d98568aeea2f7e51440e493db454e410b5890b Mon Sep 17 00:00:00 2001 From: Choosla Date: Thu, 16 Oct 2025 15:25:34 +0900 Subject: [PATCH 25/88] chore: Apply batch updates from central configuration --- .github/workflows/pr-reminder.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-reminder.yml b/.github/workflows/pr-reminder.yml index 87dc299..c666fcd 100644 --- a/.github/workflows/pr-reminder.yml +++ b/.github/workflows/pr-reminder.yml @@ -11,4 +11,4 @@ jobs: secrets: # 해당 시크릿은 조직의 시크릿에 저장되어 있음 SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} - SLACK_USER_MAP : ${{ vars.SLACK_USER_MAP }} \ No newline at end of file + SLACK_USER_MAP : ${{ secrets.SLACK_USER_MAP }} \ No newline at end of file From cf4615814e490c9b7cbec5b7eb27c80798d3555f Mon Sep 17 00:00:00 2001 From: Choosla Date: Thu, 16 Oct 2025 15:36:43 +0900 Subject: [PATCH 26/88] chore: Apply batch updates from central configuration --- .github/workflows/pr-reminder.yml | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/.github/workflows/pr-reminder.yml b/.github/workflows/pr-reminder.yml index c666fcd..007e757 100644 --- a/.github/workflows/pr-reminder.yml +++ b/.github/workflows/pr-reminder.yml @@ -1,14 +1,15 @@ -name: PR Reminder + name: PR Reminder -on: - schedule: - - cron: "47 23,4,7,8,10 * * *" # 아침 8시 47분, 오후 2시 47분, 오후 4시 47분, 오후 5시 47분, 오후 7시 47분 에 실행 (UTC 기준으로 설정해서 한국 시간에 맞춤) - workflow_dispatch: + on: + schedule: + - cron: "47 23,4,7,8,10 * * *" # 아침 8시 47분, 오후 2시 47분, 오후 4시 47분, 오후 5시 47분, 오후 7시 47분 에 실행 (UTC 기준으로 설정해서 한국 시간에 맞춤) + workflow_dispatch: -jobs: - call-reusable-reminder: - uses: 33-Auto/.github/.github/workflows/reusable-pr-reminder.yml@main - secrets: - # 해당 시크릿은 조직의 시크릿에 저장되어 있음 - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} - SLACK_USER_MAP : ${{ secrets.SLACK_USER_MAP }} \ No newline at end of file + jobs: + call-reusable-reminder: + uses: 33-Auto/.github/.github/workflows/reusable-pr-reminder.yml@main + secrets: + # 해당 시크릿은 조직의 시크릿에 저장되어 있음 + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + with: + SLACK_USER_MAP: ${{ vars.SLACK_USER_MAP }} \ No newline at end of file From 868eb249ea897668d1724e2e187baed75cbf5a50 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Thu, 16 Oct 2025 17:07:11 +0900 Subject: [PATCH 27/88] =?UTF-8?q?[FEAT]=20=EB=B6=80=ED=92=88=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=A1=B0=ED=9A=8C,=20=EB=B6=80?= =?UTF-8?q?=ED=92=88=20=EA=B7=B8=EB=A3=B9=20=EC=A1=B0=ED=9A=8C=20=EC=97=B0?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/AppNavHost.kt | 10 +- .../sampoom/android/core/ui/theme/Color.kt | 216 +++++++++++ .../sampoom/android/core/ui/theme/Theme.kt | 81 ++++- .../feature/auth/data/remote/api/AuthApi.kt | 4 +- .../android/feature/auth/ui/LoginScreen.kt | 30 +- .../android/feature/auth/ui/LoginViewModel.kt | 30 +- .../android/feature/auth/ui/SignUpScreen.kt | 2 + .../feature/part/data/local/database/.gitkeep | 0 .../part/data/local/preferences/.gitkeep | 0 .../feature/part/data/mapper/PartMappers.kt | 9 +- .../feature/part/data/remote/api/PartApi.kt | 11 +- .../part/data/remote/dto/CategoryDto.kt | 7 + .../feature/part/data/remote/dto/GroupDto.kt | 8 + .../feature/part/data/remote/dto/PartDto.kt | 7 - .../data/repository/PartRepositoryImpl.kt | 17 +- .../feature/part/domain/model/Category.kt | 7 + .../feature/part/domain/model/CategoryList.kt | 11 + .../feature/part/domain/model/Group.kt | 8 + .../model/{PartList.kt => GroupList.kt} | 6 +- .../android/feature/part/domain/model/Part.kt | 7 - .../part/domain/repository/PartRepository.kt | 6 +- ...etPartUseCase.kt => GetCategoryUseCase.kt} | 6 +- .../part/domain/usecase/GetGroupUseCase.kt | 11 + .../android/feature/part/ui/PartScreen.kt | 342 +++++++++++++++--- .../android/feature/part/ui/PartUiEvent.kt | 6 + .../android/feature/part/ui/PartUiState.kt | 19 +- .../android/feature/part/ui/PartViewModel.kt | 114 ++++-- app/src/main/res/drawable/body.xml | 19 + app/src/main/res/drawable/cart.xml | 2 +- app/src/main/res/drawable/chassis.xml | 22 ++ app/src/main/res/drawable/chevron_right.xml | 5 + app/src/main/res/drawable/dashboard.xml | 2 +- app/src/main/res/drawable/delivery.xml | 2 +- app/src/main/res/drawable/electric.xml | 13 + app/src/main/res/drawable/engine.xml | 13 + app/src/main/res/drawable/orders.xml | 2 +- app/src/main/res/drawable/parts.xml | 2 +- app/src/main/res/drawable/search.xml | 2 +- app/src/main/res/drawable/transmission.xml | 9 + app/src/main/res/drawable/trim.xml | 13 + app/src/main/res/values/strings.xml | 12 +- 41 files changed, 925 insertions(+), 168 deletions(-) delete mode 100644 app/src/main/java/com/sampoom/android/feature/part/data/local/database/.gitkeep delete mode 100644 app/src/main/java/com/sampoom/android/feature/part/data/local/preferences/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/CategoryDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/GroupDto.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/PartDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/domain/model/Category.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/domain/model/CategoryList.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/domain/model/Group.kt rename app/src/main/java/com/sampoom/android/feature/part/domain/model/{PartList.kt => GroupList.kt} (65%) delete mode 100644 app/src/main/java/com/sampoom/android/feature/part/domain/model/Part.kt rename app/src/main/java/com/sampoom/android/feature/part/domain/usecase/{GetPartUseCase.kt => GetCategoryUseCase.kt} (51%) create mode 100644 app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetGroupUseCase.kt create mode 100644 app/src/main/res/drawable/body.xml create mode 100644 app/src/main/res/drawable/chassis.xml create mode 100644 app/src/main/res/drawable/chevron_right.xml create mode 100644 app/src/main/res/drawable/electric.xml create mode 100644 app/src/main/res/drawable/engine.xml create mode 100644 app/src/main/res/drawable/transmission.xml create mode 100644 app/src/main/res/drawable/trim.xml diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index d167d4b..2c0948d 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -1,5 +1,6 @@ package com.sampoom.android.app.navigation +import androidx.compose.foundation.background import androidx.compose.foundation.layout.padding import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon @@ -18,6 +19,7 @@ import androidx.navigation.compose.composable import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import com.sampoom.android.R +import com.sampoom.android.core.ui.theme.backgroundColor import com.sampoom.android.feature.auth.ui.LoginScreen import com.sampoom.android.feature.auth.ui.SignUpScreen import com.sampoom.android.feature.part.ui.PartScreen @@ -53,7 +55,7 @@ fun AppNavHost() { val navController = rememberNavController() // TODO: 임시 로그인 상태 확인 -> AuthRepository에서 확인하도록 변경 - val isLoggedIn = false + val isLoggedIn = true NavHost( navController = navController, @@ -82,7 +84,11 @@ fun AppNavHost() { ) } composable(ROUTE_HOME) { MainScreen(navController) } - composable(ROUTE_PARTS) { PartScreen() } + composable(ROUTE_PARTS) { PartScreen( + onNavigateBack = { + navController.navigateUp() + } + ) } } } diff --git a/app/src/main/java/com/sampoom/android/core/ui/theme/Color.kt b/app/src/main/java/com/sampoom/android/core/ui/theme/Color.kt index 72cdc9c..fe07c9a 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/theme/Color.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/theme/Color.kt @@ -4,6 +4,222 @@ import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color +val primaryLight = Color(0xFF4C4AC8) +val onPrimaryLight = Color(0xFFFFFFFF) +val primaryContainerLight = Color(0xFF6565E2) +val onPrimaryContainerLight = Color(0xFFFFFBFF) +val secondaryLight = Color(0xFF5B5D72) +val onSecondaryLight = Color(0xFFFFFFFF) +val secondaryContainerLight = Color(0xFFE6E6FF) +val onSecondaryContainerLight = Color(0xFF65667B) +val tertiaryLight = Color(0xFF5D5F5F) +val onTertiaryLight = Color(0xFFFFFFFF) +val tertiaryContainerLight = Color(0xFFF5F5F5) +val onTertiaryContainerLight = Color(0xFF6F7070) +val errorLight = Color(0xFFAD3035) +val onErrorLight = Color(0xFFFFFFFF) +val errorContainerLight = Color(0xFFFF6C6C) +val onErrorContainerLight = Color(0xFF6E0011) +val backgroundLight = Color(0xFFFCF8FF) +val onBackgroundLight = Color(0xFF1B1B23) +val surfaceLight = Color(0xFFFCF8F8) +val onSurfaceLight = Color(0xFF1C1B1B) +val surfaceVariantLight = Color(0xFFE0E3E3) +val onSurfaceVariantLight = Color(0xFF444748) +val outlineLight = Color(0xFF747878) +val outlineVariantLight = Color(0xFFC4C7C8) +val scrimLight = Color(0xFF000000) +val inverseSurfaceLight = Color(0xFF313030) +val inverseOnSurfaceLight = Color(0xFFF4F0EF) +val inversePrimaryLight = Color(0xFFC2C1FF) +val surfaceDimLight = Color(0xFFDDD9D9) +val surfaceBrightLight = Color(0xFFFCF8F8) +val surfaceContainerLowestLight = Color(0xFFFFFFFF) +val surfaceContainerLowLight = Color(0xFFF6F3F2) +val surfaceContainerLight = Color(0xFFF1EDEC) +val surfaceContainerHighLight = Color(0xFFEBE7E7) +val surfaceContainerHighestLight = Color(0xFFE5E2E1) + +val primaryLightMediumContrast = Color(0xFF231AA2) +val onPrimaryLightMediumContrast = Color(0xFFFFFFFF) +val primaryContainerLightMediumContrast = Color(0xFF5E5DDA) +val onPrimaryContainerLightMediumContrast = Color(0xFFFFFFFF) +val secondaryLightMediumContrast = Color(0xFF333548) +val onSecondaryLightMediumContrast = Color(0xFFFFFFFF) +val secondaryContainerLightMediumContrast = Color(0xFF6A6B81) +val onSecondaryContainerLightMediumContrast = Color(0xFFFFFFFF) +val tertiaryLightMediumContrast = Color(0xFF353637) +val onTertiaryLightMediumContrast = Color(0xFFFFFFFF) +val tertiaryContainerLightMediumContrast = Color(0xFF6C6D6D) +val onTertiaryContainerLightMediumContrast = Color(0xFFFFFFFF) +val errorLightMediumContrast = Color(0xFF730012) +val onErrorLightMediumContrast = Color(0xFFFFFFFF) +val errorContainerLightMediumContrast = Color(0xFFC13F42) +val onErrorContainerLightMediumContrast = Color(0xFFFFFFFF) +val backgroundLightMediumContrast = Color(0xFFFCF8FF) +val onBackgroundLightMediumContrast = Color(0xFF1B1B23) +val surfaceLightMediumContrast = Color(0xFFFCF8F8) +val onSurfaceLightMediumContrast = Color(0xFF111111) +val surfaceVariantLightMediumContrast = Color(0xFFE0E3E3) +val onSurfaceVariantLightMediumContrast = Color(0xFF333738) +val outlineLightMediumContrast = Color(0xFF4F5354) +val outlineVariantLightMediumContrast = Color(0xFF6A6E6E) +val scrimLightMediumContrast = Color(0xFF000000) +val inverseSurfaceLightMediumContrast = Color(0xFF313030) +val inverseOnSurfaceLightMediumContrast = Color(0xFFF4F0EF) +val inversePrimaryLightMediumContrast = Color(0xFFC2C1FF) +val surfaceDimLightMediumContrast = Color(0xFFC9C6C5) +val surfaceBrightLightMediumContrast = Color(0xFFFCF8F8) +val surfaceContainerLowestLightMediumContrast = Color(0xFFFFFFFF) +val surfaceContainerLowLightMediumContrast = Color(0xFFF6F3F2) +val surfaceContainerLightMediumContrast = Color(0xFFEBE7E7) +val surfaceContainerHighLightMediumContrast = Color(0xFFDFDCDB) +val surfaceContainerHighestLightMediumContrast = Color(0xFFD4D1D0) + +val primaryLightHighContrast = Color(0xFF160299) +val onPrimaryLightHighContrast = Color(0xFFFFFFFF) +val primaryContainerLightHighContrast = Color(0xFF3835B4) +val onPrimaryContainerLightHighContrast = Color(0xFFFFFFFF) +val secondaryLightHighContrast = Color(0xFF292B3D) +val onSecondaryLightHighContrast = Color(0xFFFFFFFF) +val secondaryContainerLightHighContrast = Color(0xFF46485C) +val onSecondaryContainerLightHighContrast = Color(0xFFFFFFFF) +val tertiaryLightHighContrast = Color(0xFF2A2C2D) +val onTertiaryLightHighContrast = Color(0xFFFFFFFF) +val tertiaryContainerLightHighContrast = Color(0xFF48494A) +val onTertiaryContainerLightHighContrast = Color(0xFFFFFFFF) +val errorLightHighContrast = Color(0xFF60000D) +val onErrorLightHighContrast = Color(0xFFFFFFFF) +val errorContainerLightHighContrast = Color(0xFF8F1922) +val onErrorContainerLightHighContrast = Color(0xFFFFFFFF) +val backgroundLightHighContrast = Color(0xFFFCF8FF) +val onBackgroundLightHighContrast = Color(0xFF1B1B23) +val surfaceLightHighContrast = Color(0xFFFCF8F8) +val onSurfaceLightHighContrast = Color(0xFF000000) +val surfaceVariantLightHighContrast = Color(0xFFE0E3E3) +val onSurfaceVariantLightHighContrast = Color(0xFF000000) +val outlineLightHighContrast = Color(0xFF292D2D) +val outlineVariantLightHighContrast = Color(0xFF464A4A) +val scrimLightHighContrast = Color(0xFF000000) +val inverseSurfaceLightHighContrast = Color(0xFF313030) +val inverseOnSurfaceLightHighContrast = Color(0xFFFFFFFF) +val inversePrimaryLightHighContrast = Color(0xFFC2C1FF) +val surfaceDimLightHighContrast = Color(0xFFBBB8B7) +val surfaceBrightLightHighContrast = Color(0xFFFCF8F8) +val surfaceContainerLowestLightHighContrast = Color(0xFFFFFFFF) +val surfaceContainerLowLightHighContrast = Color(0xFFF4F0EF) +val surfaceContainerLightHighContrast = Color(0xFFE5E2E1) +val surfaceContainerHighLightHighContrast = Color(0xFFD7D4D3) +val surfaceContainerHighestLightHighContrast = Color(0xFFC9C6C5) + +val primaryDark = Color(0xFFC2C1FF) +val onPrimaryDark = Color(0xFF1B0E9D) +val primaryContainerDark = Color(0xFF8283FF) +val onPrimaryContainerDark = Color(0xFF12008E) +val secondaryDark = Color(0xFFFFFFFF) +val onSecondaryDark = Color(0xFF2D2F42) +val secondaryContainerDark = Color(0xFFE0E0F9) +val onSecondaryContainerDark = Color(0xFF616378) +val tertiaryDark = Color(0xFFFFFFFF) +val onTertiaryDark = Color(0xFF2F3131) +val tertiaryContainerDark = Color(0xFFE2E2E2) +val onTertiaryContainerDark = Color(0xFF636565) +val errorDark = Color(0xFFFFB3B0) +val onErrorDark = Color(0xFF68000F) +val errorContainerDark = Color(0xFFFF6C6C) +val onErrorContainerDark = Color(0xFF6E0011) +val backgroundDark = Color(0xFF13131A) +val onBackgroundDark = Color(0xFFE4E1EC) +val surfaceDark = Color(0xFF141313) +val onSurfaceDark = Color(0xFFE5E2E1) +val surfaceVariantDark = Color(0xFF444748) +val onSurfaceVariantDark = Color(0xFFC4C7C8) +val outlineDark = Color(0xFF8E9192) +val outlineVariantDark = Color(0xFF444748) +val scrimDark = Color(0xFF000000) +val inverseSurfaceDark = Color(0xFFE5E2E1) +val inverseOnSurfaceDark = Color(0xFF313030) +val inversePrimaryDark = Color(0xFF4F4DCA) +val surfaceDimDark = Color(0xFF141313) +val surfaceBrightDark = Color(0xFF3A3939) +val surfaceContainerLowestDark = Color(0xFF0E0E0E) +val surfaceContainerLowDark = Color(0xFF1C1B1B) +val surfaceContainerDark = Color(0xFF201F1F) +val surfaceContainerHighDark = Color(0xFF2A2A2A) +val surfaceContainerHighestDark = Color(0xFF353434) + +val primaryDarkMediumContrast = Color(0xFFDBD9FF) +val onPrimaryDarkMediumContrast = Color(0xFF110088) +val primaryContainerDarkMediumContrast = Color(0xFF8283FF) +val onPrimaryContainerDarkMediumContrast = Color(0xFF000000) +val secondaryDarkMediumContrast = Color(0xFFFFFFFF) +val onSecondaryDarkMediumContrast = Color(0xFF2D2F42) +val secondaryContainerDarkMediumContrast = Color(0xFFE0E0F9) +val onSecondaryContainerDarkMediumContrast = Color(0xFF45475A) +val tertiaryDarkMediumContrast = Color(0xFFFFFFFF) +val onTertiaryDarkMediumContrast = Color(0xFF2F3131) +val tertiaryContainerDarkMediumContrast = Color(0xFFE2E2E2) +val onTertiaryContainerDarkMediumContrast = Color(0xFF464848) +val errorDarkMediumContrast = Color(0xFFFFD2CF) +val onErrorDarkMediumContrast = Color(0xFF54000A) +val errorContainerDarkMediumContrast = Color(0xFFFF6C6C) +val onErrorContainerDarkMediumContrast = Color(0xFF250002) +val backgroundDarkMediumContrast = Color(0xFF13131A) +val onBackgroundDarkMediumContrast = Color(0xFFE4E1EC) +val surfaceDarkMediumContrast = Color(0xFF141313) +val onSurfaceDarkMediumContrast = Color(0xFFFFFFFF) +val surfaceVariantDarkMediumContrast = Color(0xFF444748) +val onSurfaceVariantDarkMediumContrast = Color(0xFFDADDDD) +val outlineDarkMediumContrast = Color(0xFFAFB2B3) +val outlineVariantDarkMediumContrast = Color(0xFF8D9191) +val scrimDarkMediumContrast = Color(0xFF000000) +val inverseSurfaceDarkMediumContrast = Color(0xFFE5E2E1) +val inverseOnSurfaceDarkMediumContrast = Color(0xFF2A2A2A) +val inversePrimaryDarkMediumContrast = Color(0xFF3733B3) +val surfaceDimDarkMediumContrast = Color(0xFF141313) +val surfaceBrightDarkMediumContrast = Color(0xFF454444) +val surfaceContainerLowestDarkMediumContrast = Color(0xFF070707) +val surfaceContainerLowDarkMediumContrast = Color(0xFF1E1D1D) +val surfaceContainerDarkMediumContrast = Color(0xFF282828) +val surfaceContainerHighDarkMediumContrast = Color(0xFF333232) +val surfaceContainerHighestDarkMediumContrast = Color(0xFF3E3D3D) + +val primaryDarkHighContrast = Color(0xFFF1EEFF) +val onPrimaryDarkHighContrast = Color(0xFF000000) +val primaryContainerDarkHighContrast = Color(0xFFBDBCFF) +val onPrimaryContainerDarkHighContrast = Color(0xFF03003B) +val secondaryDarkHighContrast = Color(0xFFFFFFFF) +val onSecondaryDarkHighContrast = Color(0xFF000000) +val secondaryContainerDarkHighContrast = Color(0xFFE0E0F9) +val onSecondaryContainerDarkHighContrast = Color(0xFF27293B) +val tertiaryDarkHighContrast = Color(0xFFFFFFFF) +val onTertiaryDarkHighContrast = Color(0xFF000000) +val tertiaryContainerDarkHighContrast = Color(0xFFE2E2E2) +val onTertiaryContainerDarkHighContrast = Color(0xFF282A2B) +val errorDarkHighContrast = Color(0xFFFFECEA) +val onErrorDarkHighContrast = Color(0xFF000000) +val errorContainerDarkHighContrast = Color(0xFFFFADAA) +val onErrorContainerDarkHighContrast = Color(0xFF220002) +val backgroundDarkHighContrast = Color(0xFF13131A) +val onBackgroundDarkHighContrast = Color(0xFFE4E1EC) +val surfaceDarkHighContrast = Color(0xFF141313) +val onSurfaceDarkHighContrast = Color(0xFFFFFFFF) +val surfaceVariantDarkHighContrast = Color(0xFF444748) +val onSurfaceVariantDarkHighContrast = Color(0xFFFFFFFF) +val outlineDarkHighContrast = Color(0xFFEEF0F1) +val outlineVariantDarkHighContrast = Color(0xFFC0C3C4) +val scrimDarkHighContrast = Color(0xFF000000) +val inverseSurfaceDarkHighContrast = Color(0xFFE5E2E1) +val inverseOnSurfaceDarkHighContrast = Color(0xFF000000) +val inversePrimaryDarkHighContrast = Color(0xFF3733B3) +val surfaceDimDarkHighContrast = Color(0xFF141313) +val surfaceBrightDarkHighContrast = Color(0xFF51504F) +val surfaceContainerLowestDarkHighContrast = Color(0xFF000000) +val surfaceContainerLowDarkHighContrast = Color(0xFF201F1F) +val surfaceContainerDarkHighContrast = Color(0xFF313030) +val surfaceContainerHighDarkHighContrast = Color(0xFF3C3B3B) +val surfaceContainerHighestDarkHighContrast = Color(0xFF474646) + val White = Color(0xFFFFFFFF) val Black = Color(0xFF000000) diff --git a/app/src/main/java/com/sampoom/android/core/ui/theme/Theme.kt b/app/src/main/java/com/sampoom/android/core/ui/theme/Theme.kt index 9c55a3d..88e7334 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/theme/Theme.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/theme/Theme.kt @@ -12,31 +12,84 @@ import androidx.compose.ui.platform.LocalContext private val DarkColorScheme = darkColorScheme( primary = Main500, + onPrimary = onPrimaryDark, + primaryContainer = primaryContainerDark, + onPrimaryContainer = onPrimaryContainerDark, secondary = Main300, - tertiary = Main100 + onSecondary = onSecondaryDark, + secondaryContainer = secondaryContainerDark, + onSecondaryContainer = onSecondaryContainerDark, + tertiary = Main100, + onTertiary = onTertiaryDark, + tertiaryContainer = tertiaryContainerDark, + onTertiaryContainer = onTertiaryContainerDark, + error = errorDark, + onError = onErrorDark, + errorContainer = errorContainerDark, + onErrorContainer = onErrorContainerDark, + background = BgBlack, + onBackground = onBackgroundDark, + surface = BgBlack, + onSurface = onSurfaceDark, + surfaceVariant = surfaceVariantDark, + onSurfaceVariant = onSurfaceVariantDark, + outline = outlineDark, + outlineVariant = outlineVariantDark, + scrim = scrimDark, + inverseSurface = inverseSurfaceDark, + inverseOnSurface = inverseOnSurfaceDark, + inversePrimary = inversePrimaryDark, + surfaceDim = surfaceDimDark, + surfaceBright = surfaceBrightDark, + surfaceContainerLowest = surfaceContainerLowestDark, + surfaceContainerLow = surfaceContainerLowDark, + surfaceContainer = surfaceContainerDark, + surfaceContainerHigh = surfaceContainerHighDark, + surfaceContainerHighest = surfaceContainerHighestDark, ) private val LightColorScheme = lightColorScheme( primary = Main500, + onPrimary = onPrimaryLight, + primaryContainer = primaryContainerLight, + onPrimaryContainer = onPrimaryContainerLight, secondary = Main300, - tertiary = Main100 - - /* 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), - */ + onSecondary = onSecondaryLight, + secondaryContainer = secondaryContainerLight, + onSecondaryContainer = onSecondaryContainerLight, + tertiary = Main100, + onTertiary = onTertiaryLight, + tertiaryContainer = tertiaryContainerLight, + onTertiaryContainer = onTertiaryContainerLight, + error = errorLight, + onError = onErrorLight, + errorContainer = errorContainerLight, + onErrorContainer = onErrorContainerLight, + background = BgWhite, + onBackground = onBackgroundLight, + surface = BgWhite, + onSurface = onSurfaceLight, + surfaceVariant = surfaceVariantLight, + onSurfaceVariant = onSurfaceVariantLight, + outline = outlineLight, + outlineVariant = outlineVariantLight, + scrim = scrimLight, + inverseSurface = inverseSurfaceLight, + inverseOnSurface = inverseOnSurfaceLight, + inversePrimary = inversePrimaryLight, + surfaceDim = surfaceDimLight, + surfaceBright = surfaceBrightLight, + surfaceContainerLowest = surfaceContainerLowestLight, + surfaceContainerLow = surfaceContainerLowLight, + surfaceContainer = surfaceContainerLight, + surfaceContainerHigh = surfaceContainerHighLight, + surfaceContainerHighest = surfaceContainerHighestLight, ) @Composable fun SampoomManagementTheme( darkTheme: Boolean = isSystemInDarkTheme(), - // Dynamic color is available on Android 12+ - dynamicColor: Boolean = true, + dynamicColor: Boolean = false, content: @Composable () -> Unit ) { val colorScheme = when { diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt index 74ff84f..41ee5bd 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt @@ -9,9 +9,9 @@ import retrofit2.http.Body import retrofit2.http.POST interface AuthApi { - @POST("login") + @POST("auth/login") suspend fun login(@Body body: LoginRequestDto): ApiResponse - @POST("signup") + @POST("auth/signup") suspend fun signUp(@Body body: SignUpRequestDto): ApiResponse } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt index 36ed2a9..a894c8d 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt @@ -7,20 +7,16 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.ime import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment @@ -35,6 +31,7 @@ import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.sampoom.android.R import com.sampoom.android.core.ui.component.CommonButton import com.sampoom.android.core.ui.component.CommonTextField @@ -42,6 +39,7 @@ import com.sampoom.android.core.ui.theme.Main500 import com.sampoom.android.core.ui.component.ShowErrorSnackBar import com.sampoom.android.core.ui.component.rememberCommonSnackBarHostState import com.sampoom.android.core.ui.component.TopSnackBarHost +import com.sampoom.android.core.ui.theme.backgroundColor @Composable fun LoginScreen( @@ -57,15 +55,15 @@ fun LoginScreen( viewModel.bindLabel(emailLabel, passwordLabel, errorLabel) } - val state by viewModel.state.collectAsState() + val uiState by viewModel.uiState.collectAsStateWithLifecycle() - LaunchedEffect(state.success) { - if (state.success) onSuccess() + LaunchedEffect(uiState.success) { + if (uiState.success) onSuccess() } val snackBarHostState = rememberCommonSnackBarHostState() ShowErrorSnackBar( - errorMessage = state.error, + errorMessage = uiState.error, snackBarHostState = snackBarHostState, onConsumed = { viewModel.consumeError() } ) @@ -101,30 +99,30 @@ fun LoginScreen( Spacer(Modifier.height(48.dp)) CommonTextField( modifier = Modifier.fillMaxWidth(), - value = state.email, + value = uiState.email, onValueChange = { viewModel.onEvent(LoginUiEvent.EmailChanged(it)) }, placeholder = stringResource(R.string.login_placeholder_email), - isError = state.emailError != null, - errorMessage = state.emailError + isError = uiState.emailError != null, + errorMessage = uiState.emailError ) Spacer(Modifier.height(8.dp)) CommonTextField( modifier = Modifier.fillMaxWidth(), - value = state.password, + value = uiState.password, onValueChange = { viewModel.onEvent(LoginUiEvent.PasswordChanged(it)) }, placeholder = stringResource(R.string.login_placeholder_password), isPassword = true, - isError = state.passwordError != null, - errorMessage = state.passwordError + isError = uiState.passwordError != null, + errorMessage = uiState.passwordError ) Spacer(Modifier.height(48.dp)) CommonButton( onClick = { viewModel.onEvent(LoginUiEvent.Submit) }, - enabled = state.isValid && !state.loading, + enabled = uiState.isValid && !uiState.loading, modifier = Modifier.fillMaxWidth() ) { Text( - if (state.loading) stringResource(R.string.login_button_login_loading) + if (uiState.loading) stringResource(R.string.login_button_login_loading) else stringResource(R.string.login_button_login) ) } diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt index 997312c..83ba328 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt @@ -20,8 +20,8 @@ class LoginViewModel @Inject constructor( private val singIn: LoginUseCase, private val application: Application ) : ViewModel() { - private val _state = MutableStateFlow(LoginUiState()) - val state: StateFlow = _state + private val _uiState = MutableStateFlow(LoginUiState()) + val uiState: StateFlow = _uiState private var emailLabel: String = "" private var passwordLabel: String = "" @@ -35,26 +35,26 @@ class LoginViewModel @Inject constructor( fun onEvent(e: LoginUiEvent) = when (e) { is LoginUiEvent.EmailChanged -> { - _state.value = _state.value.copy(email = e.email) + _uiState.value = _uiState.value.copy(email = e.email) validateEmail() } is LoginUiEvent.PasswordChanged -> { - _state.value = _state.value.copy(password = e.password) + _uiState.value = _uiState.value.copy(password = e.password) validatePassword() } LoginUiEvent.Submit -> submit() } private fun validateEmail() { - val result = AuthValidator.validateNotEmpty(_state.value.email, emailLabel) - _state.value = _state.value.copy( + val result = AuthValidator.validateNotEmpty(_uiState.value.email, emailLabel) + _uiState.value = _uiState.value.copy( emailError = result.toErrorMessage() ) } private fun validatePassword() { - val result = AuthValidator.validateNotEmpty(_state.value.password, passwordLabel) - _state.value = _state.value.copy( + val result = AuthValidator.validateNotEmpty(_uiState.value.password, passwordLabel) + _uiState.value = _uiState.value.copy( passwordError = result.toErrorMessage() ) } @@ -71,22 +71,22 @@ class LoginViewModel @Inject constructor( validateEmail() validatePassword() - if (!_state.value.isValid) return@launch + if (!_uiState.value.isValid) return@launch - val s = _state.value - _state.update { it.copy(loading = true, error = null) } + val s = _uiState.value + _uiState.update { it.copy(loading = true, error = null) } runCatching { singIn(s.email, s.password) } - .onSuccess { _state.update { it.copy(loading = false, success = true) } } + .onSuccess { _uiState.update { it.copy(loading = false, success = true) } } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() - _state.update { + _uiState.update { it.copy(loading = false, error = backendMessage ?: (throwable.message ?: errorLabel)) } } - Log.d("LoginViewModel", "submit: ${_state.value}") + Log.d("LoginViewModel", "submit: ${_uiState.value}") } fun consumeError() { - _state.update { it.copy(error = null) } + _uiState.update { it.copy(error = null) } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt index 172037c..b252289 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt @@ -1,6 +1,7 @@ package com.sampoom.android.feature.auth.ui import androidx.compose.foundation.Image +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement @@ -41,6 +42,7 @@ import com.sampoom.android.core.ui.component.CommonTextField import com.sampoom.android.core.ui.component.ShowErrorSnackBar import com.sampoom.android.core.ui.component.rememberCommonSnackBarHostState import com.sampoom.android.core.ui.component.TopSnackBarHost +import com.sampoom.android.core.ui.theme.backgroundColor @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/local/database/.gitkeep b/app/src/main/java/com/sampoom/android/feature/part/data/local/database/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/local/preferences/.gitkeep b/app/src/main/java/com/sampoom/android/feature/part/data/local/preferences/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt b/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt index 0c06f6a..ffd1330 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt @@ -1,6 +1,9 @@ package com.sampoom.android.feature.part.data.mapper -import com.sampoom.android.feature.part.data.remote.dto.PartDto -import com.sampoom.android.feature.part.domain.model.Part +import com.sampoom.android.feature.part.data.remote.dto.CategoryDto +import com.sampoom.android.feature.part.data.remote.dto.GroupDto +import com.sampoom.android.feature.part.domain.model.Category +import com.sampoom.android.feature.part.domain.model.Group -fun PartDto.toModel(): Part = Part(id, name, count) \ No newline at end of file +fun CategoryDto.toModel(): Category = Category(id, code, name) +fun GroupDto.toModel(): Group = Group(id, code, name, categoryId) diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt b/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt index e5a4998..a9f44a9 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt @@ -1,10 +1,15 @@ package com.sampoom.android.feature.part.data.remote.api import com.sampoom.android.core.network.ApiResponse -import com.sampoom.android.feature.part.data.remote.dto.PartDto +import com.sampoom.android.feature.part.data.remote.dto.CategoryDto +import com.sampoom.android.feature.part.data.remote.dto.GroupDto import retrofit2.http.GET +import retrofit2.http.Path interface PartApi { - @GET("part") - suspend fun getPartList(): ApiResponse> + @GET("agency/category") + suspend fun getCategoryList(): ApiResponse> + + @GET("agency/category/{categoryId}") + suspend fun getGroupList(@Path("categoryId") categoryId: Long): ApiResponse> } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/CategoryDto.kt b/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/CategoryDto.kt new file mode 100644 index 0000000..313b6cb --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/CategoryDto.kt @@ -0,0 +1,7 @@ +package com.sampoom.android.feature.part.data.remote.dto + +data class CategoryDto( + val id: Long, + val code: String, + val name: String +) diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/GroupDto.kt b/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/GroupDto.kt new file mode 100644 index 0000000..991e1fe --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/GroupDto.kt @@ -0,0 +1,8 @@ +package com.sampoom.android.feature.part.data.remote.dto + +data class GroupDto( + val id: Long, + val code: String, + val name: String, + val categoryId: Long +) diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/PartDto.kt b/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/PartDto.kt deleted file mode 100644 index d7973be..0000000 --- a/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/PartDto.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.sampoom.android.feature.part.data.remote.dto - -data class PartDto( - val id: Int, - val name: String, - val count: Int -) diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt index 663cd0a..c36b64b 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt @@ -2,16 +2,23 @@ package com.sampoom.android.feature.part.data.repository import com.sampoom.android.feature.part.data.mapper.toModel import com.sampoom.android.feature.part.data.remote.api.PartApi -import com.sampoom.android.feature.part.domain.model.PartList +import com.sampoom.android.feature.part.domain.model.CategoryList +import com.sampoom.android.feature.part.domain.model.GroupList import com.sampoom.android.feature.part.domain.repository.PartRepository import javax.inject.Inject class PartRepositoryImpl @Inject constructor( private val api: PartApi ) : PartRepository { - override suspend fun getPartList(): PartList { - val response = api.getPartList() - val partItems = response.data.map { it.toModel() } - return PartList(items = partItems) + override suspend fun getCategoryList(): CategoryList { + val dto = api.getCategoryList() + val categoryItems = dto.data.map { it.toModel() } + return CategoryList(items = categoryItems) + } + + override suspend fun getGroupList(categoryId: Long): GroupList { + val response = api.getGroupList(categoryId) + val groupItems = response.data.map { it.toModel() } + return GroupList(items = groupItems) } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/model/Category.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/model/Category.kt new file mode 100644 index 0000000..18834d6 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/model/Category.kt @@ -0,0 +1,7 @@ +package com.sampoom.android.feature.part.domain.model + +data class Category( + val id: Long, + val code: String, + val name: String +) diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/model/CategoryList.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/model/CategoryList.kt new file mode 100644 index 0000000..95d8248 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/model/CategoryList.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.part.domain.model + +data class CategoryList( + val items: List, + val totalCount: Int = items.size, + val isEmpty: Boolean = items.isEmpty() +) { + companion object Companion { + fun empty() = CategoryList(emptyList()) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/model/Group.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/model/Group.kt new file mode 100644 index 0000000..833c004 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/model/Group.kt @@ -0,0 +1,8 @@ +package com.sampoom.android.feature.part.domain.model + +data class Group( + val id: Long, + val code: String, + val name: String, + val categoryId: Long +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/model/PartList.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/model/GroupList.kt similarity index 65% rename from app/src/main/java/com/sampoom/android/feature/part/domain/model/PartList.kt rename to app/src/main/java/com/sampoom/android/feature/part/domain/model/GroupList.kt index 74b0891..34bdd22 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/domain/model/PartList.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/model/GroupList.kt @@ -1,11 +1,11 @@ package com.sampoom.android.feature.part.domain.model -data class PartList( - val items: List, +data class GroupList( + val items: List, val totalCount: Int = items.size, val isEmpty: Boolean = items.isEmpty() ) { companion object Companion { - fun empty() = PartList(emptyList()) + fun empty() = GroupList(emptyList()) } } diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/model/Part.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/model/Part.kt deleted file mode 100644 index 9c1bb23..0000000 --- a/app/src/main/java/com/sampoom/android/feature/part/domain/model/Part.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.sampoom.android.feature.part.domain.model - -data class Part( - val id: Int, - val name: String, - val count: Int -) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt index 06c46d5..e0f05dd 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt @@ -1,7 +1,9 @@ package com.sampoom.android.feature.part.domain.repository -import com.sampoom.android.feature.part.domain.model.PartList +import com.sampoom.android.feature.part.domain.model.CategoryList +import com.sampoom.android.feature.part.domain.model.GroupList interface PartRepository { - suspend fun getPartList(): PartList + suspend fun getCategoryList(): CategoryList + suspend fun getGroupList(categoryId: Long): GroupList } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetPartUseCase.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetCategoryUseCase.kt similarity index 51% rename from app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetPartUseCase.kt rename to app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetCategoryUseCase.kt index 9fdd394..3029262 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetPartUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetCategoryUseCase.kt @@ -1,11 +1,11 @@ package com.sampoom.android.feature.part.domain.usecase -import com.sampoom.android.feature.part.domain.model.PartList +import com.sampoom.android.feature.part.domain.model.CategoryList import com.sampoom.android.feature.part.domain.repository.PartRepository import javax.inject.Inject -class GetPartUseCase @Inject constructor( +class GetCategoryUseCase @Inject constructor( private val repository: PartRepository ) { - suspend operator fun invoke(): PartList = repository.getPartList() + suspend operator fun invoke(): CategoryList = repository.getCategoryList() } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetGroupUseCase.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetGroupUseCase.kt new file mode 100644 index 0000000..256be21 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetGroupUseCase.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.part.domain.usecase + +import com.sampoom.android.feature.part.domain.model.GroupList +import com.sampoom.android.feature.part.domain.repository.PartRepository +import javax.inject.Inject + +class GetGroupUseCase @Inject constructor( + private val repository: PartRepository +) { + suspend operator fun invoke(categoryId: Long): GroupList = repository.getGroupList(categoryId) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index 1164887..d7202a2 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -3,79 +3,250 @@ package com.sampoom.android.feature.part.ui import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Search import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.sampoom.android.R +import com.sampoom.android.core.ui.theme.FailRed +import com.sampoom.android.core.ui.theme.Main500 +import com.sampoom.android.core.ui.theme.White +import com.sampoom.android.core.ui.theme.backgroundCardColor +import com.sampoom.android.core.ui.theme.textColor +import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.feature.part.domain.model.Category +import com.sampoom.android.feature.part.domain.model.Group +@OptIn(ExperimentalMaterial3Api::class) @Composable fun PartScreen( + onNavigateBack: () -> Unit = {}, viewModel: PartViewModel = hiltViewModel() ) { + val errorLabel = stringResource(R.string.common_error) + + LaunchedEffect(errorLabel) { + viewModel.bindLabel(errorLabel) + } + val uiState by viewModel.uiState.collectAsStateWithLifecycle() +// val snackBarHostState = rememberCommonSnackBarHostState() +// ShowErrorSnackBar( +// errorMessage = uiState.categoryError, +// snackBarHostState = snackBarHostState, +// onConsumed = { viewModel.consumeError() } +// ) - Scaffold { innerPadding -> + Scaffold( + topBar = { + TopAppBar( + title = { Text(stringResource(R.string.part_title)) }, + navigationIcon = { + IconButton(onClick = onNavigateBack) { + Icon( + painter = painterResource(R.drawable.ic_arrow_back), + contentDescription = stringResource(R.string.nav_back) + ) + } + } + ) + } + ) { innerPadding -> Column( modifier = Modifier .fillMaxSize() .padding(innerPadding) .padding(16.dp) ) { + // 검색 바 + OutlinedTextField( + value = "uiState.searchQuery", + onValueChange = { "viewModel.onSearchQueryChanged(it)" }, + placeholder = { Text("부품명으로 검색") }, + trailingIcon = { + Icon( + Icons.Default.Search, + contentDescription = "검색", + tint = MaterialTheme.colorScheme.onSurfaceVariant + ) + }, + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp), + shape = RoundedCornerShape(24.dp), + singleLine = true, + colors = OutlinedTextFieldDefaults.colors( + focusedBorderColor = Color.Transparent, + unfocusedBorderColor = Color.Transparent, + focusedContainerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f), + unfocusedContainerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f), + ) + ) + + // Category 선택 제목 Text( - text = stringResource(R.string.part_title), - style = MaterialTheme.typography.headlineMedium, + text = stringResource(R.string.part_title_category), + style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.Bold, - modifier = Modifier.padding(bottom = 16.dp) + modifier = Modifier.padding(vertical = 16.dp) ) + // Category 섹션 when { - uiState.loading -> { + uiState.categoryLoading -> { Box( - modifier = Modifier.fillMaxSize(), + modifier = Modifier + .fillMaxWidth() + .height(200.dp), contentAlignment = Alignment.Center ) { CircularProgressIndicator() } } - uiState.error != null -> { + uiState.categoryError != null -> { + ErrorContent( + onRetry = { viewModel.onEvent(PartUiEvent.RetryCategories) }, + modifier = Modifier.height(200.dp) + ) + } + + uiState.categoryList.isEmpty() -> { + EmptyContent( + message = stringResource(R.string.part_empty_category), + modifier = Modifier.height(200.dp) + ) + } + + else -> { + // 2x3 그리드로 카테고리 배치 Column( - modifier = Modifier.fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(8.dp) ) { - Text( - text = "${stringResource(R.string.common_error)}: ${uiState.error}", - color = MaterialTheme.colorScheme.error - ) - Spacer(modifier = Modifier.height(16.dp)) - Button(onClick = { viewModel.refreshPart() }) { - Text(stringResource((R.string.common_retry))) + // 첫 번째 줄 (3개) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + uiState.categoryList.take(3).forEach { category -> + CategoryItem( + category = category, + isSelected = category.id == uiState.selectedCategory?.id, + onClick = { + viewModel.onEvent( + PartUiEvent.CategorySelected( + category + ) + ) + }, + modifier = Modifier.weight(1f) + ) + } + } + + // 두 번째 줄 (3개) + if (uiState.categoryList.size > 3) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + uiState.categoryList.drop(3).take(3).forEach { category -> + CategoryItem( + category = category, + isSelected = category.id == uiState.selectedCategory?.id, + onClick = { + viewModel.onEvent( + PartUiEvent.CategorySelected( + category + ) + ) + }, + modifier = Modifier.weight(1f) + ) + } + } } } } + } - uiState.partList.isEmpty() -> { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { - Text(stringResource(R.string.part_empty)) - } + Spacer(Modifier.height(24.dp)) + + // 그룹 리스트 섹션 + if (uiState.selectedCategory == null) { + // 초기 상태: 카테고리 선택 안내 + Column( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 32.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Icon( + painter = painterResource(R.drawable.search), + contentDescription = null, + modifier = Modifier.size(32.dp), + tint = textSecondaryColor() + ) + Spacer(modifier = Modifier.height(8.dp)) + Text( + text = stringResource(R.string.part_select_category), + style = MaterialTheme.typography.bodyMedium, + color = textSecondaryColor() + ) } + } else { + // 그룹 선택 제목 + Text( + text = stringResource(R.string.part_title_group), + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(vertical = 16.dp) + ) - else -> { - LazyColumn( - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - items(uiState.partList) { inventory -> - PartItemCard(part = inventory) + // 그룹 리스트 + when { + uiState.groupLoading -> { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + + uiState.groupError != null -> { + ErrorContent( + onRetry = { viewModel.onEvent(PartUiEvent.RetryGroups) }, + modifier = Modifier.height(200.dp) + ) + } + + uiState.groupList.isEmpty() -> { + EmptyContent( + message = stringResource(R.string.part_empty_group), + modifier = Modifier.height(200.dp) + ) + } + + else -> { + LazyColumn( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + items(uiState.groupList) { inventory -> + PartItemCard(group = inventory) + } } } } @@ -84,13 +255,62 @@ fun PartScreen( } } +// Category 아이템 +@Composable +fun CategoryItem( + category: Category, + isSelected: Boolean, + onClick: () -> Unit, + modifier: Modifier = Modifier +) { + Card( + onClick = { onClick() }, + shape = RoundedCornerShape(16.dp), + colors = CardDefaults.cardColors( + containerColor = if (isSelected) Main500 else backgroundCardColor() + ), + modifier = modifier.height(100.dp) + ) { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Icon( + painter = painterResource(id = resourceMapper(category.code)), + contentDescription = category.name, + modifier = Modifier.size(32.dp), + tint = if (isSelected) White else textColor() + ) + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = category.name, + style = MaterialTheme.typography.bodySmall, + color = if (isSelected) White else textColor() + ) + } + } +} + +private fun resourceMapper(code: String): Int { + return when (code) { + "ENG" -> R.drawable.engine + "TRN" -> R.drawable.transmission + "CHS" -> R.drawable.chassis + "BDY" -> R.drawable.body + "TRM" -> R.drawable.trim + "ELE" -> R.drawable.electric + else -> R.drawable.parts + } +} + @Composable private fun PartItemCard( - part: com.sampoom.android.feature.part.domain.model.Part + group: Group ) { Card( modifier = Modifier.fillMaxWidth(), - elevation = CardDefaults.cardElevation(defaultElevation = 4.dp) + colors = CardDefaults.cardColors(containerColor = backgroundCardColor()), ) { Row( modifier = Modifier @@ -99,25 +319,49 @@ private fun PartItemCard( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - Column { - Text( - text = part.name, - style = MaterialTheme.typography.titleMedium, - fontWeight = FontWeight.Bold - ) - Text( - text = "ID: ${part.id}", - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - } - Text( - text = "${part.count}개", - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.primary + text = group.name, + style = MaterialTheme.typography.titleMedium + ) + + Icon( + painterResource(R.drawable.chevron_right), + contentDescription = stringResource(R.string.common_detail) ) } } +} + +@Composable +fun ErrorContent( + onRetry: () -> Unit, + modifier: Modifier = Modifier +) { + Column( + modifier = modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Text( + text = stringResource(R.string.common_error), + color = FailRed + ) + Spacer(modifier = Modifier.height(16.dp)) + Button(onClick = onRetry) { + Text(stringResource((R.string.common_retry))) + } + } +} + +@Composable +fun EmptyContent( + message: String, + modifier: Modifier = Modifier +) { + Box( + modifier = modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Text(message) + } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiEvent.kt index e6a49d0..7dbf889 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiEvent.kt @@ -1,4 +1,10 @@ package com.sampoom.android.feature.part.ui +import com.sampoom.android.feature.part.domain.model.Category + sealed interface PartUiEvent { + object LoadCategories : PartUiEvent + data class CategorySelected(val category: Category) : PartUiEvent + object RetryCategories : PartUiEvent + object RetryGroups : PartUiEvent } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt index d343dbe..f43a4f6 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt @@ -1,10 +1,19 @@ package com.sampoom.android.feature.part.ui -import com.sampoom.android.feature.part.domain.model.Part +import com.sampoom.android.feature.part.domain.model.Category +import com.sampoom.android.feature.part.domain.model.Group data class PartUiState( - val loading: Boolean = false, - val error: String? = null, - val success: Boolean = false, - val partList: List = emptyList() + // Part + val groupList: List = emptyList(), + val groupLoading: Boolean = false, + val groupError: String? = null, + + // 선택된 Category + val selectedCategory: Category? = null, + + // Category + val categoryList: List = emptyList(), + val categoryLoading: Boolean = false, + val categoryError: String? = null ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt index c979584..98aa727 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt @@ -1,47 +1,115 @@ package com.sampoom.android.feature.part.ui +import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sampoom.android.feature.part.domain.usecase.GetPartUseCase +import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.feature.part.domain.model.Category +import com.sampoom.android.feature.part.domain.usecase.GetCategoryUseCase +import com.sampoom.android.feature.part.domain.usecase.GetGroupUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class PartViewModel @Inject constructor( - private val getPartUseCase: GetPartUseCase + private val getCategoryUseCase: GetCategoryUseCase, + private val getGroupUseCase: GetGroupUseCase ) : ViewModel() { - private val _uiState = MutableStateFlow(PartUiState()) - val uiState: StateFlow = _uiState.asStateFlow() + val uiState: StateFlow = _uiState + + private var errorLabel: String = "" + + fun bindLabel(error: String) { + errorLabel = error + } init { - loadPart() + loadCategory() + } + + fun onEvent(event: PartUiEvent) { + when (event) { + is PartUiEvent.LoadCategories -> loadCategory() + is PartUiEvent.CategorySelected -> selectCategory(event.category) + is PartUiEvent.RetryCategories -> loadCategory() + is PartUiEvent.RetryGroups -> loadGroup() + } } - private fun loadPart() { + private fun loadCategory() { viewModelScope.launch { - _uiState.value = _uiState.value.copy(loading = true, error = null) - try { - val partListResult = getPartUseCase() - _uiState.value = _uiState.value.copy( - loading = false, - partList = partListResult.items, - success = true - ) - } catch (e: Exception) { - _uiState.value = _uiState.value.copy( - loading = false, - error = e.message ?: "Unknown error occurred" - ) - } + _uiState.update { it.copy(categoryLoading = true, categoryError = null) } + + runCatching { getCategoryUseCase() } + .onSuccess { categoryList -> + _uiState.update { + it.copy( + categoryList = categoryList.items, + categoryLoading = false, + categoryError = null + ) + } + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + categoryLoading = false, + categoryError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + } + Log.d("PartViewModel", "submit: ${_uiState.value}") } } - fun refreshPart() { - loadPart() + private fun selectCategory(category: Category) { + viewModelScope.launch { + _uiState.update { it.copy(selectedCategory = category) } + loadGroup(category.id) + } } + + private fun loadGroup(categoryId: Long) { + viewModelScope.launch { + _uiState.update { it.copy(groupLoading = true, groupError = null) } + + runCatching { getGroupUseCase(categoryId) } + .onSuccess { groupList -> + _uiState.update { + it.copy( + groupList = groupList.items, + groupLoading = false, + groupError = null + ) + } + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + groupLoading = false, + groupError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + } + Log.d("PartViewModel", "submit: ${_uiState.value}") + } + } + + private fun loadGroup() { + val selectedCategory = _uiState.value.selectedCategory + if (selectedCategory != null) { + loadGroup(selectedCategory.id) + } + } + +// fun refreshPart() { +// loadCategory() +// } } \ No newline at end of file diff --git a/app/src/main/res/drawable/body.xml b/app/src/main/res/drawable/body.xml new file mode 100644 index 0000000..3ddac4e --- /dev/null +++ b/app/src/main/res/drawable/body.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/cart.xml b/app/src/main/res/drawable/cart.xml index afc4912..12a29bd 100644 --- a/app/src/main/res/drawable/cart.xml +++ b/app/src/main/res/drawable/cart.xml @@ -8,6 +8,6 @@ android:pathData="M0.077,0h24.077v24.333h-24.077z"/> + android:fillColor="@color/text"/> diff --git a/app/src/main/res/drawable/chassis.xml b/app/src/main/res/drawable/chassis.xml new file mode 100644 index 0000000..b73b9dd --- /dev/null +++ b/app/src/main/res/drawable/chassis.xml @@ -0,0 +1,22 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/chevron_right.xml b/app/src/main/res/drawable/chevron_right.xml new file mode 100644 index 0000000..6c71c89 --- /dev/null +++ b/app/src/main/res/drawable/chevron_right.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/dashboard.xml b/app/src/main/res/drawable/dashboard.xml index c2c0e05..f7b65e4 100644 --- a/app/src/main/res/drawable/dashboard.xml +++ b/app/src/main/res/drawable/dashboard.xml @@ -5,5 +5,5 @@ android:viewportHeight="25"> + android:fillColor="@color/text"/> diff --git a/app/src/main/res/drawable/delivery.xml b/app/src/main/res/drawable/delivery.xml index ca411d4..9069781 100644 --- a/app/src/main/res/drawable/delivery.xml +++ b/app/src/main/res/drawable/delivery.xml @@ -8,6 +8,6 @@ android:pathData="M0.615,0h24v24h-24z"/> + android:fillColor="@color/text"/> diff --git a/app/src/main/res/drawable/electric.xml b/app/src/main/res/drawable/electric.xml new file mode 100644 index 0000000..223c5da --- /dev/null +++ b/app/src/main/res/drawable/electric.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/drawable/engine.xml b/app/src/main/res/drawable/engine.xml new file mode 100644 index 0000000..3785215 --- /dev/null +++ b/app/src/main/res/drawable/engine.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/drawable/orders.xml b/app/src/main/res/drawable/orders.xml index 7521789..41a7732 100644 --- a/app/src/main/res/drawable/orders.xml +++ b/app/src/main/res/drawable/orders.xml @@ -5,5 +5,5 @@ android:viewportHeight="25"> + android:fillColor="@color/text"/> diff --git a/app/src/main/res/drawable/parts.xml b/app/src/main/res/drawable/parts.xml index ff89964..f55ed30 100644 --- a/app/src/main/res/drawable/parts.xml +++ b/app/src/main/res/drawable/parts.xml @@ -5,5 +5,5 @@ android:viewportHeight="25"> + android:fillColor="@color/text"/> diff --git a/app/src/main/res/drawable/search.xml b/app/src/main/res/drawable/search.xml index 519d2d6..c8582cb 100644 --- a/app/src/main/res/drawable/search.xml +++ b/app/src/main/res/drawable/search.xml @@ -8,6 +8,6 @@ android:strokeLineJoin="round" android:strokeWidth="2" android:fillColor="#00000000" - android:strokeColor="#36393F" + android:strokeColor="@color/text" android:strokeLineCap="round"/> diff --git a/app/src/main/res/drawable/transmission.xml b/app/src/main/res/drawable/transmission.xml new file mode 100644 index 0000000..0af0ab7 --- /dev/null +++ b/app/src/main/res/drawable/transmission.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/trim.xml b/app/src/main/res/drawable/trim.xml new file mode 100644 index 0000000..ffb4a25 --- /dev/null +++ b/app/src/main/res/drawable/trim.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5de1348..64f0427 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -37,14 +37,20 @@ 회원가입 회원 가입 중… - - 부품 목록 - 부품 목록이 없습니다. + + 부품조회 + 부품명으로 검색 + 카테고리 선택 + 그룹 선택 + 카테고리 목록이 없습니다. + 카테고리를 선택해주세요. + 그룹 목록이 없습니다. 오류가 발생했습니다 다시 시도 닫기 + 상세 보기 이메일을 입력해주세요 From d53f9100f8587a1d1b89d895eebc6716f2a4cfb9 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Thu, 16 Oct 2025 19:59:15 +0900 Subject: [PATCH 28/88] =?UTF-8?q?[FEAT]=20=EB=B6=80=ED=92=88=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=ED=99=94=EB=A9=B4=20=EC=97=B0?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/AppNavHost.kt | 56 ++++-- .../feature/part/data/mapper/PartMappers.kt | 3 + .../feature/part/data/remote/api/PartApi.kt | 4 + .../feature/part/data/remote/dto/PartDto.kt | 8 + .../data/repository/PartRepositoryImpl.kt | 7 + .../android/feature/part/domain/model/Part.kt | 8 + .../feature/part/domain/model/PartList.kt | 11 ++ .../part/domain/repository/PartRepository.kt | 2 + .../part/domain/usecase/GetPartUseCase.kt | 11 ++ .../android/feature/part/ui/PartListScreen.kt | 168 ++++++++++++++++++ .../feature/part/ui/PartListUiEvent.kt | 6 + .../feature/part/ui/PartListUiState.kt | 9 + .../feature/part/ui/PartListViewModel.kt | 71 ++++++++ .../android/feature/part/ui/PartScreen.kt | 20 ++- app/src/main/res/values/strings.xml | 1 + 15 files changed, 364 insertions(+), 21 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/PartDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/domain/model/Part.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/domain/model/PartList.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetPartUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiEvent.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiState.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 2c0948d..550b9ec 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -14,14 +14,17 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.navigation.NavHostController +import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController +import androidx.navigation.navArgument import com.sampoom.android.R import com.sampoom.android.core.ui.theme.backgroundColor import com.sampoom.android.feature.auth.ui.LoginScreen import com.sampoom.android.feature.auth.ui.SignUpScreen +import com.sampoom.android.feature.part.ui.PartListScreen import com.sampoom.android.feature.part.ui.PartScreen const val ROUTE_LOGIN = "login" @@ -36,6 +39,8 @@ const val ROUTE_ORDERS = "orders" // Detail Screen const val ROUTE_PARTS = "parts" +const val ROUTE_PART_LIST = "{agencyId}/group/{groupId}" +fun routePartList(agencyId: Long, groupId: Long): String = "$agencyId/group/$groupId" const val ROUTE_EMPLOYEE = "employee" const val ROUTE_SETTINGS = "settings" @@ -62,11 +67,12 @@ fun AppNavHost() { startDestination = if (isLoggedIn) ROUTE_HOME else ROUTE_LOGIN ) { composable(ROUTE_LOGIN) { - LoginScreen(onSuccess = { - navController.navigate(ROUTE_HOME) { - popUpTo(ROUTE_LOGIN) { inclusive = true } // 로그인 화면 스택 제거 - } - }, + LoginScreen( + onSuccess = { + navController.navigate(ROUTE_HOME) { + popUpTo(ROUTE_LOGIN) { inclusive = true } // 로그인 화면 스택 제거 + } + }, onNavigateSignUp = { navController.navigate(ROUTE_SIGNUP) }) @@ -84,11 +90,29 @@ fun AppNavHost() { ) } composable(ROUTE_HOME) { MainScreen(navController) } - composable(ROUTE_PARTS) { PartScreen( - onNavigateBack = { - navController.navigateUp() - } - ) } + composable(ROUTE_PARTS) { + PartScreen( + onNavigateBack = { + navController.navigateUp() + }, + onNavigatePartList = { group -> + navController.navigate(routePartList(1, group.id)) + } + ) + } + composable( + ROUTE_PART_LIST, + arguments = listOf( + navArgument("agencyId") { type = NavType.LongType }, + navArgument("groupId") { type = NavType.LongType } + ) + ) { + PartListScreen( + onNavigateBack = { + navController.navigateUp() + } + ) + } } } @@ -128,7 +152,10 @@ fun PartsFab(navController: NavHostController) { } } ) { - Icon(painterResource(R.drawable.parts), contentDescription = stringResource(R.string.part_title)) + Icon( + painterResource(R.drawable.parts), + contentDescription = stringResource(R.string.part_title) + ) } } @@ -147,7 +174,12 @@ fun BottomNavigationBar(navController: NavHostController) { val currentDestination = navBackStackEntry?.destination NavigationBarItem( - icon = { Icon(painterResource(id = item.icon), contentDescription = stringResource(item.title)) }, + icon = { + Icon( + painterResource(id = item.icon), + contentDescription = stringResource(item.title) + ) + }, label = { Text(stringResource(item.title)) }, selected = currentDestination?.route == item.route, onClick = { diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt b/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt index ffd1330..65800a6 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt @@ -2,8 +2,11 @@ package com.sampoom.android.feature.part.data.mapper import com.sampoom.android.feature.part.data.remote.dto.CategoryDto import com.sampoom.android.feature.part.data.remote.dto.GroupDto +import com.sampoom.android.feature.part.data.remote.dto.PartDto import com.sampoom.android.feature.part.domain.model.Category import com.sampoom.android.feature.part.domain.model.Group +import com.sampoom.android.feature.part.domain.model.Part fun CategoryDto.toModel(): Category = Category(id, code, name) fun GroupDto.toModel(): Group = Group(id, code, name, categoryId) +fun PartDto.toModel(): Part = Part(partId, code, name, quantity) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt b/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt index a9f44a9..06f1004 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt @@ -3,6 +3,7 @@ package com.sampoom.android.feature.part.data.remote.api import com.sampoom.android.core.network.ApiResponse import com.sampoom.android.feature.part.data.remote.dto.CategoryDto import com.sampoom.android.feature.part.data.remote.dto.GroupDto +import com.sampoom.android.feature.part.data.remote.dto.PartDto import retrofit2.http.GET import retrofit2.http.Path @@ -12,4 +13,7 @@ interface PartApi { @GET("agency/category/{categoryId}") suspend fun getGroupList(@Path("categoryId") categoryId: Long): ApiResponse> + + @GET("agency/1/group/{groupId}") + suspend fun getPartList(@Path("groupId") groupId: Long): ApiResponse> } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/PartDto.kt b/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/PartDto.kt new file mode 100644 index 0000000..41872f7 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/PartDto.kt @@ -0,0 +1,8 @@ +package com.sampoom.android.feature.part.data.remote.dto + +data class PartDto( + val partId: Long, + val code: String, + val name: String, + val quantity: Long +) diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt index c36b64b..f40c510 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt @@ -4,6 +4,7 @@ import com.sampoom.android.feature.part.data.mapper.toModel import com.sampoom.android.feature.part.data.remote.api.PartApi import com.sampoom.android.feature.part.domain.model.CategoryList import com.sampoom.android.feature.part.domain.model.GroupList +import com.sampoom.android.feature.part.domain.model.PartList import com.sampoom.android.feature.part.domain.repository.PartRepository import javax.inject.Inject @@ -21,4 +22,10 @@ class PartRepositoryImpl @Inject constructor( val groupItems = response.data.map { it.toModel() } return GroupList(items = groupItems) } + + override suspend fun getPartList(groupId: Long): PartList { + val response = api.getPartList(groupId) + val partItems = response.data.map { it.toModel() } + return PartList(items = partItems) + } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/model/Part.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/model/Part.kt new file mode 100644 index 0000000..019b63b --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/model/Part.kt @@ -0,0 +1,8 @@ +package com.sampoom.android.feature.part.domain.model + +data class Part( + val partId: Long, + val code: String, + val name: String, + val quantity: Long +) diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/model/PartList.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/model/PartList.kt new file mode 100644 index 0000000..74b0891 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/model/PartList.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.part.domain.model + +data class PartList( + val items: List, + val totalCount: Int = items.size, + val isEmpty: Boolean = items.isEmpty() +) { + companion object Companion { + fun empty() = PartList(emptyList()) + } +} diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt index e0f05dd..3d761e0 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt @@ -2,8 +2,10 @@ package com.sampoom.android.feature.part.domain.repository import com.sampoom.android.feature.part.domain.model.CategoryList import com.sampoom.android.feature.part.domain.model.GroupList +import com.sampoom.android.feature.part.domain.model.PartList interface PartRepository { suspend fun getCategoryList(): CategoryList suspend fun getGroupList(categoryId: Long): GroupList + suspend fun getPartList(groupId: Long): PartList } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetPartUseCase.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetPartUseCase.kt new file mode 100644 index 0000000..93ca316 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetPartUseCase.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.part.domain.usecase + +import com.sampoom.android.feature.part.domain.model.PartList +import com.sampoom.android.feature.part.domain.repository.PartRepository +import javax.inject.Inject + +class GetPartUseCase @Inject constructor( + private val repository: PartRepository +) { + suspend operator fun invoke(groupId: Long): PartList = repository.getPartList(groupId) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt new file mode 100644 index 0000000..61f6997 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt @@ -0,0 +1,168 @@ +package com.sampoom.android.feature.part.ui + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.sampoom.android.R +import com.sampoom.android.core.ui.theme.backgroundCardColor +import com.sampoom.android.core.ui.theme.textColor +import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.feature.part.domain.model.Part + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun PartListScreen( + onNavigateBack: () -> Unit = {}, + viewModel: PartListViewModel = hiltViewModel() +) { + val errorLabel = stringResource(R.string.common_error) + + LaunchedEffect(errorLabel) { + viewModel.bindLabel(errorLabel) + } + + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + + Scaffold( + topBar = { + TopAppBar( + title = { Text(stringResource(R.string.part_title)) }, + navigationIcon = { + IconButton(onClick = onNavigateBack) { + Icon( + painter = painterResource(R.drawable.ic_arrow_back), + contentDescription = stringResource(R.string.nav_back) + ) + } + } + ) + } + ) { innerPadding -> + when { + uiState.partListLoading -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + + uiState.partListError != null -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + ErrorContent( + onRetry = { viewModel.onEvent(PartListUiEvent.RetryPartList) }, + modifier = Modifier.height(200.dp) + ) + } + } + + uiState.partList.isEmpty() -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + EmptyContent( + message = stringResource(R.string.part_empty_part), + modifier = Modifier.height(200.dp) + ) + } + } + + else -> { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(innerPadding), + contentPadding = PaddingValues(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + items(uiState.partList) { part -> + PartListItemCard(part = part) + } + } + } + } + } +} + +@Composable +private fun PartListItemCard( + part: Part +) { + Card( + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors(containerColor = backgroundCardColor()) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier.weight(1F) + ) { + Text( + text = part.name, + color = textColor(), + style = MaterialTheme.typography.titleMedium + ) + Text( + text = part.code, + color = textSecondaryColor(), + style = MaterialTheme.typography.bodySmall, + fontWeight = FontWeight.Light + ) + } + + Text( + text = part.quantity.toString(), + color = textColor(), + style = MaterialTheme.typography.titleMedium + ) + + Icon( + painterResource(R.drawable.chevron_right), + contentDescription = stringResource(R.string.common_detail), + tint = textSecondaryColor() + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiEvent.kt new file mode 100644 index 0000000..8026605 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiEvent.kt @@ -0,0 +1,6 @@ +package com.sampoom.android.feature.part.ui + +sealed interface PartListUiEvent { + object LoadPartList : PartListUiEvent + object RetryPartList : PartListUiEvent +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiState.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiState.kt new file mode 100644 index 0000000..e5bbee1 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiState.kt @@ -0,0 +1,9 @@ +package com.sampoom.android.feature.part.ui + +import com.sampoom.android.feature.part.domain.model.Part + +data class PartListUiState( + val partList: List = emptyList(), + val partListLoading: Boolean = false, + val partListError: String? = null +) diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt new file mode 100644 index 0000000..8bd7990 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt @@ -0,0 +1,71 @@ +package com.sampoom.android.feature.part.ui + +import android.util.Log +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.feature.part.domain.usecase.GetPartUseCase +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class PartListViewModel @Inject constructor( + private val getPartListUseCase: GetPartUseCase, + savedStateHandle: SavedStateHandle +) : ViewModel() { + private val _uiState = MutableStateFlow(PartListUiState()) + val uiState: StateFlow = _uiState + + // Navigation 인자 로드 + private val agencyId: Long = savedStateHandle.get("agencyId") ?: 0L + private val groupId: Long = savedStateHandle.get("groupId") ?: 0L + + private var errorLabel: String = "" + + fun bindLabel(error: String) { + errorLabel = error + } + + init { + loadPartList(groupId) + } + + fun onEvent(event: PartListUiEvent) { + when (event) { + is PartListUiEvent.LoadPartList -> loadPartList(groupId) + is PartListUiEvent.RetryPartList -> loadPartList(groupId) + } + } + + private fun loadPartList(groupId: Long) { + viewModelScope.launch { + _uiState.update { it.copy(partListLoading = true, partListError = null) } + + runCatching { getPartListUseCase(groupId) } + .onSuccess { partList -> + _uiState.update { + it.copy( + partList = partList.items, + partListLoading = false, + partListError = null + ) + } + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + partListLoading = false, + partListError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + } + Log.d("PartListViewModel", "submit: ${_uiState.value}") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index d7202a2..0890f12 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -17,6 +17,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.viewmodel.compose.viewModel import com.sampoom.android.R import com.sampoom.android.core.ui.theme.FailRed import com.sampoom.android.core.ui.theme.Main500 @@ -26,11 +27,13 @@ import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.part.domain.model.Category import com.sampoom.android.feature.part.domain.model.Group +import com.sampoom.android.feature.part.ui.PartItemCard @OptIn(ExperimentalMaterial3Api::class) @Composable fun PartScreen( onNavigateBack: () -> Unit = {}, + onNavigatePartList: (Group) -> Unit, viewModel: PartViewModel = hiltViewModel() ) { val errorLabel = stringResource(R.string.common_error) @@ -40,12 +43,6 @@ fun PartScreen( } val uiState by viewModel.uiState.collectAsStateWithLifecycle() -// val snackBarHostState = rememberCommonSnackBarHostState() -// ShowErrorSnackBar( -// errorMessage = uiState.categoryError, -// snackBarHostState = snackBarHostState, -// onConsumed = { viewModel.consumeError() } -// ) Scaffold( topBar = { @@ -244,8 +241,11 @@ fun PartScreen( LazyColumn( verticalArrangement = Arrangement.spacedBy(8.dp) ) { - items(uiState.groupList) { inventory -> - PartItemCard(group = inventory) + items(uiState.groupList) { group -> + PartItemCard( + group = group, + onClick = { onNavigatePartList(group) } + ) } } } @@ -306,9 +306,11 @@ private fun resourceMapper(code: String): Int { @Composable private fun PartItemCard( - group: Group + group: Group, + onClick: () -> Unit ) { Card( + onClick = { onClick() }, modifier = Modifier.fillMaxWidth(), colors = CardDefaults.cardColors(containerColor = backgroundCardColor()), ) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 64f0427..0e06ff4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -43,6 +43,7 @@ 카테고리 선택 그룹 선택 카테고리 목록이 없습니다. + 부품 목록이 없습니다. 카테고리를 선택해주세요. 그룹 목록이 없습니다. From 08b589bcd1b62f76f7144fc35d5101c1866b1794 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Sat, 18 Oct 2025 09:45:51 +0900 Subject: [PATCH 29/88] =?UTF-8?q?[FIX]=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EA=B7=B8=EB=A6=AC=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/part/ui/PartScreen.kt | 46 ++++++++----------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index 0890f12..3d2ffe8 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -3,13 +3,16 @@ package com.sampoom.android.feature.part.ui import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Search import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.focusModifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -63,8 +66,11 @@ fun PartScreen( modifier = Modifier .fillMaxSize() .padding(innerPadding) - .padding(16.dp) + .padding(horizontal = 16.dp) + .verticalScroll(rememberScrollState()) ) { + Spacer(Modifier.height(16.dp)) + // 검색 바 OutlinedTextField( value = "uiState.searchQuery", @@ -131,34 +137,12 @@ fun PartScreen( modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(8.dp) ) { - // 첫 번째 줄 (3개) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - uiState.categoryList.take(3).forEach { category -> - CategoryItem( - category = category, - isSelected = category.id == uiState.selectedCategory?.id, - onClick = { - viewModel.onEvent( - PartUiEvent.CategorySelected( - category - ) - ) - }, - modifier = Modifier.weight(1f) - ) - } - } - - // 두 번째 줄 (3개) - if (uiState.categoryList.size > 3) { + uiState.categoryList.chunked(3).forEach { categoryChunk -> Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp) ) { - uiState.categoryList.drop(3).take(3).forEach { category -> + categoryChunk.forEach { category -> CategoryItem( category = category, isSelected = category.id == uiState.selectedCategory?.id, @@ -172,6 +156,11 @@ fun PartScreen( modifier = Modifier.weight(1f) ) } + + // 3개 미만인 경우 빈 공간 채우기 + repeat(3 - categoryChunk.size) { + Spacer(modifier = Modifier.weight(1f)) + } } } } @@ -238,10 +227,11 @@ fun PartScreen( } else -> { - LazyColumn( + Column( + Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(8.dp) ) { - items(uiState.groupList) { group -> + uiState.groupList.forEach { group -> PartItemCard( group = group, onClick = { onNavigatePartList(group) } @@ -251,6 +241,8 @@ fun PartScreen( } } } + + Spacer(Modifier.height(32.dp)) } } } From 2efb8d0e31fb4a4ea256a297ca0b3b3576974111 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Sat, 18 Oct 2025 12:49:14 +0900 Subject: [PATCH 30/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/AppNavHost.kt | 4 +- .../android/core/ui/component/EmptyContent.kt | 21 +++++++++ .../android/core/ui/component/ErrorContent.kt | 37 +++++++++++++++ .../feature/part/ui/PartListViewModel.kt | 4 +- .../android/feature/part/ui/PartScreen.kt | 47 ++----------------- .../android/feature/part/ui/PartViewModel.kt | 9 +++- app/src/main/res/values/strings.xml | 3 +- 7 files changed, 78 insertions(+), 47 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/core/ui/component/EmptyContent.kt create mode 100644 app/src/main/java/com/sampoom/android/core/ui/component/ErrorContent.kt diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 550b9ec..049d4ac 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -39,8 +39,8 @@ const val ROUTE_ORDERS = "orders" // Detail Screen const val ROUTE_PARTS = "parts" -const val ROUTE_PART_LIST = "{agencyId}/group/{groupId}" -fun routePartList(agencyId: Long, groupId: Long): String = "$agencyId/group/$groupId" +const val ROUTE_PART_LIST = "parts/{agencyId}/group/{groupId}" +fun routePartList(agencyId: Long, groupId: Long): String = "parts/$agencyId/group/$groupId" const val ROUTE_EMPLOYEE = "employee" const val ROUTE_SETTINGS = "settings" diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/EmptyContent.kt b/app/src/main/java/com/sampoom/android/core/ui/component/EmptyContent.kt new file mode 100644 index 0000000..ba9ed2a --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/ui/component/EmptyContent.kt @@ -0,0 +1,21 @@ +package com.sampoom.android.core.ui.component + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier + +@Composable +fun EmptyContent( + message: String, + modifier: Modifier = Modifier +) { + Box( + modifier = modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Text(message) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/ErrorContent.kt b/app/src/main/java/com/sampoom/android/core/ui/component/ErrorContent.kt new file mode 100644 index 0000000..0d4b7ec --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/ui/component/ErrorContent.kt @@ -0,0 +1,37 @@ +package com.sampoom.android.core.ui.component + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.sampoom.android.R +import com.sampoom.android.core.ui.theme.FailRed + +@Composable +fun ErrorContent( + onRetry: () -> Unit, + modifier: Modifier = Modifier +) { + Column( + modifier = modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Text( + text = stringResource(R.string.common_error), + color = FailRed + ) + Spacer(modifier = Modifier.height(16.dp)) + Button(onClick = onRetry) { + Text(stringResource((R.string.common_retry))) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt index 8bd7990..d0c4e80 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt @@ -1,6 +1,7 @@ package com.sampoom.android.feature.part.ui import android.util.Log +import androidx.compose.ui.res.stringResource import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -32,7 +33,8 @@ class PartListViewModel @Inject constructor( } init { - loadPartList(groupId) + if (groupId > 0L) loadPartList(groupId) + else _uiState.update { it.copy(partListError = errorLabel) } } fun onEvent(event: PartListUiEvent) { diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index 3d2ffe8..11e1f22 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -1,8 +1,7 @@ package com.sampoom.android.feature.part.ui +import android.R.attr.singleLine import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll @@ -12,7 +11,6 @@ import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.focus.focusModifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -20,9 +18,9 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.lifecycle.viewmodel.compose.viewModel import com.sampoom.android.R -import com.sampoom.android.core.ui.theme.FailRed +import com.sampoom.android.core.ui.component.EmptyContent +import com.sampoom.android.core.ui.component.ErrorContent import com.sampoom.android.core.ui.theme.Main500 import com.sampoom.android.core.ui.theme.White import com.sampoom.android.core.ui.theme.backgroundCardColor @@ -30,7 +28,6 @@ import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.part.domain.model.Category import com.sampoom.android.feature.part.domain.model.Group -import com.sampoom.android.feature.part.ui.PartItemCard @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -75,11 +72,11 @@ fun PartScreen( OutlinedTextField( value = "uiState.searchQuery", onValueChange = { "viewModel.onSearchQueryChanged(it)" }, - placeholder = { Text("부품명으로 검색") }, + placeholder = { Text(stringResource(R.string.part_placeholder_search)) }, trailingIcon = { Icon( Icons.Default.Search, - contentDescription = "검색", + contentDescription = stringResource(R.string.part_title_search), tint = MaterialTheme.colorScheme.onSurfaceVariant ) }, @@ -324,38 +321,4 @@ private fun PartItemCard( ) } } -} - -@Composable -fun ErrorContent( - onRetry: () -> Unit, - modifier: Modifier = Modifier -) { - Column( - modifier = modifier.fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - Text( - text = stringResource(R.string.common_error), - color = FailRed - ) - Spacer(modifier = Modifier.height(16.dp)) - Button(onClick = onRetry) { - Text(stringResource((R.string.common_retry))) - } - } -} - -@Composable -fun EmptyContent( - message: String, - modifier: Modifier = Modifier -) { - Box( - modifier = modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { - Text(message) - } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt index 98aa727..6bcf62a 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt @@ -8,6 +8,7 @@ import com.sampoom.android.feature.part.domain.model.Category import com.sampoom.android.feature.part.domain.usecase.GetCategoryUseCase import com.sampoom.android.feature.part.domain.usecase.GetGroupUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update @@ -22,6 +23,7 @@ class PartViewModel @Inject constructor( private val _uiState = MutableStateFlow(PartUiState()) val uiState: StateFlow = _uiState + private var groupLoadJob: Job? = null private var errorLabel: String = "" fun bindLabel(error: String) { @@ -71,16 +73,20 @@ class PartViewModel @Inject constructor( private fun selectCategory(category: Category) { viewModelScope.launch { _uiState.update { it.copy(selectedCategory = category) } + groupLoadJob?.cancel() // 기존 그룹 로드 취소 후 새 요청 loadGroup(category.id) } } private fun loadGroup(categoryId: Long) { - viewModelScope.launch { + groupLoadJob?.cancel() + groupLoadJob = viewModelScope.launch { _uiState.update { it.copy(groupLoading = true, groupError = null) } runCatching { getGroupUseCase(categoryId) } .onSuccess { groupList -> + // 최신 선택과 불일치하면 무시 + if (_uiState.value.selectedCategory?.id != categoryId) return@onSuccess _uiState.update { it.copy( groupList = groupList.items, @@ -91,6 +97,7 @@ class PartViewModel @Inject constructor( } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + if (_uiState.value.selectedCategory?.id != categoryId) return@onFailure _uiState.update { it.copy( groupLoading = false, diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0e06ff4..7f7d2ab 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -39,9 +39,10 @@ 부품조회 - 부품명으로 검색 + 검색 카테고리 선택 그룹 선택 + 부품명으로 검색 카테고리 목록이 없습니다. 부품 목록이 없습니다. 카테고리를 선택해주세요. From 2d7606226a6c2146fb745ab15ab685bd66e74512 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Sat, 18 Oct 2025 12:50:10 +0900 Subject: [PATCH 31/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/sampoom/android/app/navigation/AppNavHost.kt | 2 -- .../com/sampoom/android/feature/part/ui/PartListViewModel.kt | 1 - .../main/java/com/sampoom/android/feature/part/ui/PartScreen.kt | 1 - 3 files changed, 4 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 049d4ac..91cd311 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -1,6 +1,5 @@ package com.sampoom.android.app.navigation -import androidx.compose.foundation.background import androidx.compose.foundation.layout.padding import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon @@ -21,7 +20,6 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import com.sampoom.android.R -import com.sampoom.android.core.ui.theme.backgroundColor import com.sampoom.android.feature.auth.ui.LoginScreen import com.sampoom.android.feature.auth.ui.SignUpScreen import com.sampoom.android.feature.part.ui.PartListScreen diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt index d0c4e80..999d8a9 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt @@ -1,7 +1,6 @@ package com.sampoom.android.feature.part.ui import android.util.Log -import androidx.compose.ui.res.stringResource import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index 11e1f22..97ae617 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -1,6 +1,5 @@ package com.sampoom.android.feature.part.ui -import android.R.attr.singleLine import androidx.compose.foundation.layout.* import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape From 9e73aacc45b9e95946854f6bbf0864355e2727d1 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Sat, 18 Oct 2025 13:14:25 +0900 Subject: [PATCH 32/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/sampoom/android/core/ui/component/EmptyContent.kt | 3 +-- .../com/sampoom/android/core/ui/component/ErrorContent.kt | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/EmptyContent.kt b/app/src/main/java/com/sampoom/android/core/ui/component/EmptyContent.kt index ba9ed2a..83439f1 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/EmptyContent.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/EmptyContent.kt @@ -1,7 +1,6 @@ package com.sampoom.android.core.ui.component import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -13,7 +12,7 @@ fun EmptyContent( modifier: Modifier = Modifier ) { Box( - modifier = modifier.fillMaxSize(), + modifier = modifier, contentAlignment = Alignment.Center ) { Text(message) diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/ErrorContent.kt b/app/src/main/java/com/sampoom/android/core/ui/component/ErrorContent.kt index 0d4b7ec..6e102cb 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/ErrorContent.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/ErrorContent.kt @@ -21,7 +21,7 @@ fun ErrorContent( modifier: Modifier = Modifier ) { Column( - modifier = modifier.fillMaxSize(), + modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { @@ -31,7 +31,7 @@ fun ErrorContent( ) Spacer(modifier = Modifier.height(16.dp)) Button(onClick = onRetry) { - Text(stringResource((R.string.common_retry))) + Text(stringResource(R.string.common_retry)) } } } \ No newline at end of file From 8c649565b3b9971db245558c1cd3bda3c0aaa2b3 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Sun, 19 Oct 2025 12:55:03 +0900 Subject: [PATCH 33/88] =?UTF-8?q?[FEAT]=20=EB=B6=80=ED=92=88=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20Bottom=20Sheet=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/core/ui/component/CommonButton.kt | 28 ++- .../feature/part/ui/PartDetailBottomSheet.kt | 183 ++++++++++++++++++ .../feature/part/ui/PartDetailUiEvent.kt | 13 ++ .../feature/part/ui/PartDetailUiState.kt | 10 + .../feature/part/ui/PartDetailViewModel.kt | 59 ++++++ .../android/feature/part/ui/PartListScreen.kt | 44 ++++- .../feature/part/ui/PartListUiEvent.kt | 4 + .../feature/part/ui/PartListUiState.kt | 3 +- .../feature/part/ui/PartListViewModel.kt | 2 + app/src/main/res/values/strings.xml | 9 + 10 files changed, 350 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiState.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt b/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt index ca17eca..0765410 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt @@ -1,5 +1,6 @@ package com.sampoom.android.core.ui.component +import android.R.attr.enabled import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.height @@ -12,15 +13,18 @@ import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Text import androidx.compose.material3.TextButton 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.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.sampoom.android.core.ui.theme.FailRed import com.sampoom.android.core.ui.theme.Main500 import com.sampoom.android.core.ui.theme.White import com.sampoom.android.core.ui.theme.disableColor +import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor /** @@ -140,8 +144,26 @@ fun CommonButton( shape = shape, modifier = modifier.height(height), colors = ButtonDefaults.buttonColors( - containerColor = Color(0xFF000000), - contentColor = Color.White, + containerColor = disableColor(), + contentColor = textColor(), + disabledContainerColor = disableColor(), + disabledContentColor = textSecondaryColor() + ) + ) { + if (leadingIcon != null) leadingIcon() + content() + } + } + + ButtonVariant.Error -> { + Button( + onClick = onClick, + enabled = enabled, + shape = shape, + modifier = modifier.height(height), + colors = ButtonDefaults.buttonColors( + containerColor = FailRed, + contentColor = White, disabledContainerColor = disableColor(), disabledContentColor = textSecondaryColor() ) @@ -168,6 +190,8 @@ enum class ButtonVariant { /** Solid dark/neutral fill. */ Neutral, + + Error } enum class ButtonSize { Large, Medium, Small } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt new file mode 100644 index 0000000..f99c727 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt @@ -0,0 +1,183 @@ +package com.sampoom.android.feature.part.ui + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.OutlinedTextFieldDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.sampoom.android.R +import com.sampoom.android.core.ui.component.ButtonSize +import com.sampoom.android.core.ui.component.ButtonVariant +import com.sampoom.android.core.ui.component.CommonButton +import com.sampoom.android.core.ui.theme.textColor +import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.feature.part.domain.model.Part + +@Composable +fun PartDetailBottomSheet( + part: Part, + viewModel: PartDetailViewModel = hiltViewModel() +) { + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + + LaunchedEffect(part) { + viewModel.onEvent(PartDetailUiEvent.Initialize(part)) + } + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(24.dp), + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier.weight(1F) + ) { + Text( + text = part.name, + style = MaterialTheme.typography.titleMedium, + color = textColor(), + modifier = Modifier.fillMaxWidth() + ) + Text( + text = part.code, + style = MaterialTheme.typography.bodySmall, + color = textSecondaryColor(), + modifier = Modifier.fillMaxWidth() + ) + } + Text( + stringResource(R.string.part_current_quantity) + + part.quantity.toString() + + stringResource(R.string.common_EA) + ) + } + + Spacer(Modifier.height(16.dp)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End, + verticalAlignment = Alignment.CenterVertically, + ) { + Text(text = stringResource(R.string.part_title_quantity), Modifier.weight(1F)) + Row( + verticalAlignment = Alignment.CenterVertically, + ) { + CommonButton( + variant = ButtonVariant.Neutral, + size = ButtonSize.Large, + onClick = { viewModel.onEvent(PartDetailUiEvent.DecreaseQuantity) }, + enabled = uiState.quantity > 1 && !uiState.isUpdating + ) { + Text( + text = stringResource(R.string.part_minus), + style = MaterialTheme.typography.titleLarge + ) + } + OutlinedTextField( + value = uiState.quantity.toString(), + onValueChange = { newValue -> + when { + newValue.isEmpty() -> viewModel.onEvent(PartDetailUiEvent.SetQuantity(1)) + newValue == "0" -> viewModel.onEvent(PartDetailUiEvent.SetQuantity(1)) + else -> { + val newQuantity = newValue.toLongOrNull() + if (newQuantity != null && newQuantity > 0) viewModel.onEvent( + PartDetailUiEvent.SetQuantity(newQuantity) + ) + else viewModel.onEvent(PartDetailUiEvent.SetQuantity(1)) + } + } + }, + modifier = Modifier.width(100.dp), + singleLine = true, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), + textStyle = MaterialTheme.typography.titleMedium.copy(textAlign = TextAlign.Center), + colors = OutlinedTextFieldDefaults.colors( + focusedBorderColor = Color.Transparent, + unfocusedBorderColor = Color.Transparent, + disabledBorderColor = Color.Transparent, + errorBorderColor = Color.Transparent + ) + ) + CommonButton( + variant = ButtonVariant.Neutral, + size = ButtonSize.Large, + onClick = { viewModel.onEvent(PartDetailUiEvent.IncreaseQuantity) }, + enabled = !uiState.isUpdating + ) { + Text( + text = stringResource(R.string.part_plus), + style = MaterialTheme.typography.titleLarge + ) + } + } + } + + Spacer(Modifier.height(16.dp)) + + Row(modifier = Modifier.fillMaxWidth()) { + CommonButton( + modifier = Modifier.weight(1F), + variant = ButtonVariant.Error, + size = ButtonSize.Large, + leadingIcon = { + Icon( + painterResource(R.drawable.delivery), + contentDescription = null + ) + }, + onClick = {} // TODO: API 연동 + ) { Text(stringResource(R.string.part_add_delivery)) } + Spacer(Modifier.width(8.dp)) + CommonButton( + modifier = Modifier.weight(1F), + variant = ButtonVariant.Primary, + size = ButtonSize.Large, + leadingIcon = { Icon(painterResource(R.drawable.cart), contentDescription = null) }, + onClick = {} // TODO: API 연동 + ) { Text(stringResource(R.string.part_add_cart)) } + } + } +} + +@Preview(showBackground = true) +@Composable +fun PartDetailBottomSheetPreview() { + PartDetailBottomSheet( + part = Part( + partId = 1, + name = "엔진", + code = "ENG", + quantity = 12 + ) + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt new file mode 100644 index 0000000..f63c7e5 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt @@ -0,0 +1,13 @@ +package com.sampoom.android.feature.part.ui + +import com.sampoom.android.feature.part.domain.model.Part + +sealed interface PartDetailUiEvent { + data class Initialize(val part: Part) : PartDetailUiEvent + object IncreaseQuantity : PartDetailUiEvent + object DecreaseQuantity : PartDetailUiEvent + data class SetQuantity(val quantity: Long) : PartDetailUiEvent + object UpdateQuantity : PartDetailUiEvent + object ClearError : PartDetailUiEvent + object Dismiss : PartDetailUiEvent +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiState.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiState.kt new file mode 100644 index 0000000..dd19fd2 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiState.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.part.ui + +import com.sampoom.android.feature.part.domain.model.Part + +data class PartDetailUiState( + val part: Part? = null, + val quantity: Long = 1, + val isUpdating: Boolean = false, + val updateError: String? = null +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt new file mode 100644 index 0000000..7e0980d --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt @@ -0,0 +1,59 @@ +package com.sampoom.android.feature.part.ui + +import androidx.lifecycle.ViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import jakarta.inject.Inject +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update + +@HiltViewModel +class PartDetailViewModel @Inject constructor( +) : ViewModel() { + private val _uiState = MutableStateFlow(PartDetailUiState()) + val uiState: StateFlow = _uiState + + fun onEvent(event: PartDetailUiEvent) { + when (event) { + is PartDetailUiEvent.Initialize -> { + _uiState.update { + it.copy( + part = event.part, + quantity = 1, + updateError = null + ) + } + } + is PartDetailUiEvent.IncreaseQuantity -> { + val currentQuantity = _uiState.value.quantity + _uiState.update { it.copy(quantity = currentQuantity + 1) } + } + is PartDetailUiEvent.DecreaseQuantity -> { + val currentQuantity = _uiState.value.quantity + _uiState.update { it.copy(quantity = currentQuantity - 1) } + } + is PartDetailUiEvent.SetQuantity -> { + if (event.quantity > 0) { + _uiState.update { it.copy(quantity = event.quantity) } + } + } + is PartDetailUiEvent.UpdateQuantity -> { + val part = _uiState.value.part + val quantity = _uiState.value.quantity + if (part != null) { + // TODO : updatePartQuantity(part.partId, quantity) + } + } + is PartDetailUiEvent.ClearError -> _uiState.update { it.copy(updateError = null) } + is PartDetailUiEvent.Dismiss -> { + _uiState.update { + it.copy( + part = null, + quantity = 1, + updateError = null + ) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt index 61f6997..493705d 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt @@ -1,5 +1,7 @@ package com.sampoom.android.feature.part.ui +import android.app.ProgressDialog.show +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -18,12 +20,18 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar +import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource @@ -33,10 +41,13 @@ import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.sampoom.android.R +import com.sampoom.android.core.ui.component.EmptyContent +import com.sampoom.android.core.ui.component.ErrorContent import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.part.domain.model.Part +import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -52,6 +63,11 @@ fun PartListScreen( val uiState by viewModel.uiState.collectAsStateWithLifecycle() + // ModalBottomSheet 상태 관리 + val sheetState = rememberModalBottomSheetState() + val scope = rememberCoroutineScope() + var showBottomSheet by remember { mutableStateOf(false) } + Scaffold( topBar = { TopAppBar( @@ -113,19 +129,43 @@ fun PartListScreen( verticalArrangement = Arrangement.spacedBy(8.dp) ) { items(uiState.partList) { part -> - PartListItemCard(part = part) + PartListItemCard( + part = part, + onClick = { + viewModel.onEvent(PartListUiEvent.ShowBottomSheet(part)) + showBottomSheet = true + } + ) } } } } } + + if (showBottomSheet) { + uiState.selectedPart?.let { selectedPart -> + ModalBottomSheet( + onDismissRequest = { + showBottomSheet = false + viewModel.onEvent(PartListUiEvent.DismissBottomSheet) + }, + sheetState = sheetState + ) { + PartDetailBottomSheet( + part = selectedPart + ) + } + } + } } @Composable private fun PartListItemCard( - part: Part + part: Part, + onClick: () -> Unit ) { Card( + onClick = { onClick() }, modifier = Modifier.fillMaxWidth(), colors = CardDefaults.cardColors(containerColor = backgroundCardColor()) ) { diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiEvent.kt index 8026605..a99d6d5 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiEvent.kt @@ -1,6 +1,10 @@ package com.sampoom.android.feature.part.ui +import com.sampoom.android.feature.part.domain.model.Part + sealed interface PartListUiEvent { object LoadPartList : PartListUiEvent object RetryPartList : PartListUiEvent + data class ShowBottomSheet(val part: Part) : PartListUiEvent + object DismissBottomSheet : PartListUiEvent } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiState.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiState.kt index e5bbee1..10f4cbb 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListUiState.kt @@ -5,5 +5,6 @@ import com.sampoom.android.feature.part.domain.model.Part data class PartListUiState( val partList: List = emptyList(), val partListLoading: Boolean = false, - val partListError: String? = null + val partListError: String? = null, + val selectedPart: Part? = null ) diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt index 999d8a9..649431a 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt @@ -40,6 +40,8 @@ class PartListViewModel @Inject constructor( when (event) { is PartListUiEvent.LoadPartList -> loadPartList(groupId) is PartListUiEvent.RetryPartList -> loadPartList(groupId) + is PartListUiEvent.ShowBottomSheet -> _uiState.update { it.copy(selectedPart = event.part) } + is PartListUiEvent.DismissBottomSheet -> _uiState.update { it.copy(selectedPart = null) } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7f7d2ab..04b4785 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -48,11 +48,20 @@ 카테고리를 선택해주세요. 그룹 목록이 없습니다. + + 현재 재고 : + 수량 + - + + + 출고목록에 추가 + 장바구니에 추가 + 오류가 발생했습니다 다시 시도 닫기 상세 보기 + EA 이메일을 입력해주세요 From dbb40182e8ea45208bf080f9612fac15cda259a9 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Sun, 19 Oct 2025 18:06:58 +0900 Subject: [PATCH 34/88] =?UTF-8?q?[FEAT]=20=EC=B6=9C=EA=B3=A0=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EA=B5=AC=ED=98=84,=20=EB=B6=80=ED=92=88=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=EC=97=90=EC=84=9C=20=EC=B6=9C=EA=B3=A0=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=B6=94=EA=B0=80=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/AppNavHost.kt | 13 +- .../android/core/network/ApiResponse.kt | 6 + .../android/core/network/NetworkModule.kt | 2 +- .../feature/cart/data/local/database/.gitkeep | 0 .../cart/data/local/preferences/.gitkeep | 0 .../android/feature/cart/data/mapper/.gitkeep | 0 .../feature/cart/data/remote/api/.gitkeep | 0 .../feature/cart/data/remote/dto/.gitkeep | 0 .../feature/cart/data/repository/.gitkeep | 0 .../sampoom/android/feature/cart/di/.gitkeep | 0 .../feature/cart/domain/model/.gitkeep | 0 .../feature/cart/domain/repository/.gitkeep | 0 .../feature/cart/domain/usecase/.gitkeep | 0 .../sampoom/android/feature/cart/ui/.gitkeep | 0 .../outbound/data/mapper/OutboundMappers.kt | 12 + .../outbound/data/remote/api/OutboundApi.kt | 38 ++ .../data/remote/dto/AddOutboundRequestDto.kt | 6 + .../outbound/data/remote/dto/OutboundDto.kt | 21 ++ .../remote/dto/UpdateOutboundRequestDto.kt | 5 + .../data/repository/OutboundRepositoryImpl.kt | 46 +++ .../feature/outbound/di/OutboundModules.kt | 27 ++ .../feature/outbound/domain/model/Outbound.kt | 21 ++ .../outbound/domain/model/OutboundList.kt | 11 + .../domain/repository/OutboundRepository.kt | 10 + .../domain/usecase/AddOutboundUseCase.kt | 10 + .../domain/usecase/DeleteOutboundUseCase.kt | 10 + .../domain/usecase/GetOutboundUseCase.kt | 10 + .../usecase/UpdateOutboundQuantityUseCase.kt | 10 + .../feature/outbound/ui/OutboundListScreen.kt | 334 ++++++++++++++++++ .../outbound/ui/OutboundListUiEvent.kt | 10 + .../outbound/ui/OutboundListUiState.kt | 14 + .../outbound/ui/OutboundListViewModel.kt | 160 +++++++++ .../feature/part/ui/PartDetailBottomSheet.kt | 81 ++++- .../feature/part/ui/PartDetailUiEvent.kt | 2 +- .../feature/part/ui/PartDetailUiState.kt | 3 +- .../feature/part/ui/PartDetailViewModel.kt | 45 ++- .../android/feature/part/ui/PartListScreen.kt | 8 +- app/src/main/res/drawable/delete.xml | 9 + .../drawable/{delivery.xml => outbound.xml} | 0 app/src/main/res/values/strings.xml | 9 + 40 files changed, 901 insertions(+), 32 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/local/database/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/local/preferences/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/mapper/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/repository/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/di/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/domain/model/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/domain/repository/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/ui/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/data/mapper/OutboundMappers.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/AddOutboundRequestDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/OutboundDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/UpdateOutboundRequestDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/di/OutboundModules.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/domain/model/Outbound.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/domain/model/OutboundList.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/domain/repository/OutboundRepository.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/AddOutboundUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteOutboundUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/GetOutboundUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/UpdateOutboundQuantityUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiEvent.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt create mode 100644 app/src/main/res/drawable/delete.xml rename app/src/main/res/drawable/{delivery.xml => outbound.xml} (100%) diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 91cd311..0c123e9 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -22,6 +22,7 @@ import androidx.navigation.navArgument import com.sampoom.android.R import com.sampoom.android.feature.auth.ui.LoginScreen import com.sampoom.android.feature.auth.ui.SignUpScreen +import com.sampoom.android.feature.outbound.ui.OutboundListScreen import com.sampoom.android.feature.part.ui.PartListScreen import com.sampoom.android.feature.part.ui.PartScreen @@ -31,7 +32,7 @@ const val ROUTE_HOME = "home" // Main Screen const val ROUTE_DASHBOARD = "dashboard" -const val ROUTE_DELIVERY = "delivery" +const val ROUTE_OUTBOUND = "outbound" const val ROUTE_CART = "cart" const val ROUTE_ORDERS = "orders" @@ -48,7 +49,7 @@ sealed class BottomNavItem( val icon: Int ) { object Dashboard : BottomNavItem(ROUTE_DASHBOARD, R.string.nav_dashboard, R.drawable.dashboard) - object Delivery : BottomNavItem(ROUTE_DELIVERY, R.string.nav_delivery, R.drawable.delivery) + object Delivery : BottomNavItem(ROUTE_OUTBOUND, R.string.nav_delivery, R.drawable.outbound) object Cart : BottomNavItem(ROUTE_CART, R.string.nav_cart, R.drawable.cart) object Orders : BottomNavItem(ROUTE_ORDERS, R.string.nav_order, R.drawable.orders) } @@ -130,7 +131,7 @@ fun MainScreen( modifier = Modifier.padding(innerPadding) ) { composable(ROUTE_DASHBOARD) { DashboardScreen() } - composable(ROUTE_DELIVERY) { DeliveryScreen() } + composable(ROUTE_OUTBOUND) { OutboundListScreen() } composable(ROUTE_CART) { CartScreen() } composable(ROUTE_ORDERS) { OrderScreen() } } @@ -201,12 +202,6 @@ private fun DashboardScreen() { Text("대시보드 화면") } -@Composable -private fun DeliveryScreen() { - // 프로필 화면 구현 - Text("Delivery 화면") -} - @Composable private fun CartScreen() { // 프로필 화면 구현 diff --git a/app/src/main/java/com/sampoom/android/core/network/ApiResponse.kt b/app/src/main/java/com/sampoom/android/core/network/ApiResponse.kt index e6977d7..a0b1c1a 100644 --- a/app/src/main/java/com/sampoom/android/core/network/ApiResponse.kt +++ b/app/src/main/java/com/sampoom/android/core/network/ApiResponse.kt @@ -5,4 +5,10 @@ data class ApiResponse( val success: Boolean, val message: String, val data: T +) + +data class ApiSuccessResponse( + val status: Int, + val success: Boolean, + val message: String ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt index fb48025..dac6a14 100644 --- a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt +++ b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt @@ -33,7 +33,7 @@ object NetworkModule { @Provides @Singleton fun provideRetrofit(client: OkHttpClient): Retrofit { val gson = GsonBuilder() - .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .setFieldNamingPolicy(FieldNamingPolicy.IDENTITY) .create() return Retrofit.Builder() .baseUrl("https://sampoom.store/api/") diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/local/database/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/data/local/database/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/local/preferences/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/data/local/preferences/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/mapper/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/data/mapper/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/repository/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/data/repository/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/di/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/di/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/model/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/domain/model/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/repository/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/domain/repository/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/ui/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/mapper/OutboundMappers.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/mapper/OutboundMappers.kt new file mode 100644 index 0000000..1f38519 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/mapper/OutboundMappers.kt @@ -0,0 +1,12 @@ +package com.sampoom.android.feature.outbound.data.mapper + +import com.sampoom.android.feature.outbound.data.remote.dto.OutboundDto +import com.sampoom.android.feature.outbound.data.remote.dto.OutboundGroupDto +import com.sampoom.android.feature.outbound.data.remote.dto.OutboundPartDto +import com.sampoom.android.feature.outbound.domain.model.Outbound +import com.sampoom.android.feature.outbound.domain.model.OutboundGroup +import com.sampoom.android.feature.outbound.domain.model.OutboundPart + +fun OutboundDto.toModel(): Outbound = Outbound(categoryId, categoryName, groups.map { it.toModel() }) +fun OutboundGroupDto.toModel(): OutboundGroup = OutboundGroup(groupId, groupName, parts.map { it.toModel() }) +fun OutboundPartDto.toModel(): OutboundPart = OutboundPart(outboundId, partId, code, name, quantity) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt new file mode 100644 index 0000000..7ef2dd5 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt @@ -0,0 +1,38 @@ +package com.sampoom.android.feature.outbound.data.remote.api + +import com.sampoom.android.core.network.ApiResponse +import com.sampoom.android.core.network.ApiSuccessResponse +import com.sampoom.android.feature.outbound.data.remote.dto.AddOutboundRequestDto +import com.sampoom.android.feature.outbound.data.remote.dto.OutboundDto +import com.sampoom.android.feature.outbound.data.remote.dto.UpdateOutboundRequestDto +import retrofit2.http.Body +import retrofit2.http.DELETE +import retrofit2.http.GET +import retrofit2.http.PATCH +import retrofit2.http.POST +import retrofit2.http.Path + +interface OutboundApi { + // 출고 목록 조회 + @GET("agency/1/outbound") + suspend fun getOutboundList(): ApiResponse> + + // 출고 목록에 부품 추가 + @POST("agency/1/outbound") + suspend fun addOutbound(@Body body: AddOutboundRequestDto): ApiSuccessResponse + + // 출고 처리 + @POST("agency/1/outbound/process") + suspend fun processOutbound(): ApiSuccessResponse + + // 출고 항목 삭제 + @DELETE("agency/1/outbound/{outboundId}") + suspend fun deleteOutbound(@Path("outboundId") outboundId: Long): ApiSuccessResponse + + // 출고 수량 변경 + @PATCH("agency/1/outbound/{outboundId}") + suspend fun updateOutbound( + @Path("outboundId") outboundId: Long, + @Body body: UpdateOutboundRequestDto + ): ApiSuccessResponse +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/AddOutboundRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/AddOutboundRequestDto.kt new file mode 100644 index 0000000..f3f0ca7 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/AddOutboundRequestDto.kt @@ -0,0 +1,6 @@ +package com.sampoom.android.feature.outbound.data.remote.dto + +data class AddOutboundRequestDto( + val partId: Long, + val quantity: Long +) diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/OutboundDto.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/OutboundDto.kt new file mode 100644 index 0000000..462b63e --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/OutboundDto.kt @@ -0,0 +1,21 @@ +package com.sampoom.android.feature.outbound.data.remote.dto + +data class OutboundDto( + val categoryId: Long, + val categoryName: String, + val groups: List +) + +data class OutboundGroupDto( + val groupId: Long, + val groupName: String, + val parts: List +) + +data class OutboundPartDto( + val outboundId: Long, + val partId: Long, + val code: String, + val name: String, + val quantity: Long +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/UpdateOutboundRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/UpdateOutboundRequestDto.kt new file mode 100644 index 0000000..b0e542b --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/UpdateOutboundRequestDto.kt @@ -0,0 +1,5 @@ +package com.sampoom.android.feature.outbound.data.remote.dto + +data class UpdateOutboundRequestDto( + val quantity: Long +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt new file mode 100644 index 0000000..6940a07 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt @@ -0,0 +1,46 @@ +package com.sampoom.android.feature.outbound.data.repository + +import com.sampoom.android.feature.outbound.data.mapper.toModel +import com.sampoom.android.feature.outbound.data.remote.api.OutboundApi +import com.sampoom.android.feature.outbound.data.remote.dto.AddOutboundRequestDto +import com.sampoom.android.feature.outbound.data.remote.dto.UpdateOutboundRequestDto +import com.sampoom.android.feature.outbound.domain.model.OutboundList +import com.sampoom.android.feature.outbound.domain.repository.OutboundRepository +import jakarta.inject.Inject + +class OutboundRepositoryImpl @Inject constructor( + private val api: OutboundApi +) : OutboundRepository { + override suspend fun getOutboundList(): OutboundList { + val dto = api.getOutboundList() + val outboundItems = dto.data.map { it.toModel() } + return OutboundList(items = outboundItems) + } + + override suspend fun addOutbound( + partId: Long, + quantity: Long + ): Result { + val dto = api.addOutbound(AddOutboundRequestDto(partId, quantity)) + return runCatching { + if (!dto.success) throw Exception(dto.message) + } + } + + override suspend fun deleteOutbound(outboundId: Long): Result { + val dto = api.deleteOutbound(outboundId) + return runCatching { + if (!dto.success) throw Exception(dto.message) + } + } + + override suspend fun updateOutboundQuantity( + outboundId: Long, + quantity: Long + ): Result { + val dto = api.updateOutbound(outboundId, UpdateOutboundRequestDto(quantity)) + return runCatching { + if (!dto.success) throw Exception(dto.message) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/di/OutboundModules.kt b/app/src/main/java/com/sampoom/android/feature/outbound/di/OutboundModules.kt new file mode 100644 index 0000000..7aa5276 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/di/OutboundModules.kt @@ -0,0 +1,27 @@ +package com.sampoom.android.feature.outbound.di + +import com.sampoom.android.feature.outbound.data.remote.api.OutboundApi +import com.sampoom.android.feature.outbound.data.repository.OutboundRepositoryImpl +import com.sampoom.android.feature.outbound.domain.repository.OutboundRepository +import dagger.Binds +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import retrofit2.Retrofit +import javax.inject.Singleton +import kotlin.jvm.java + +@Module +@InstallIn(SingletonComponent::class) +abstract class OutboundBinModule { + @Binds @Singleton + abstract fun bindOutboundRepository(impl: OutboundRepositoryImpl): OutboundRepository +} + +@Module +@InstallIn(SingletonComponent::class) +object OutboundModule { + @Provides @Singleton + fun provideOutboundApi(retrofit: Retrofit): OutboundApi = retrofit.create(OutboundApi::class.java) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/model/Outbound.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/model/Outbound.kt new file mode 100644 index 0000000..1033bfc --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/model/Outbound.kt @@ -0,0 +1,21 @@ +package com.sampoom.android.feature.outbound.domain.model + +data class Outbound( + val categoryId: Long, + val categoryName: String, + val groups: List +) + +data class OutboundGroup( + val groupId: Long, + val groupName: String, + val parts: List +) + +data class OutboundPart( + val outboundId: Long, + val partId: Long, + val code: String, + val name: String, + val quantity: Long +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/model/OutboundList.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/model/OutboundList.kt new file mode 100644 index 0000000..16ced52 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/model/OutboundList.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.outbound.domain.model + +data class OutboundList( + val items: List, + val totalCount: Int = items.size, + val isEmpty: Boolean = items.isEmpty() +) { + companion object Companion { + fun empty() = OutboundList(emptyList()) + } +} diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/repository/OutboundRepository.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/repository/OutboundRepository.kt new file mode 100644 index 0000000..68d3dd6 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/repository/OutboundRepository.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.outbound.domain.repository + +import com.sampoom.android.feature.outbound.domain.model.OutboundList + +interface OutboundRepository { + suspend fun getOutboundList(): OutboundList + suspend fun addOutbound(partId: Long, quantity: Long): Result + suspend fun deleteOutbound(outboundId: Long): Result + suspend fun updateOutboundQuantity(outboundId: Long, quantity: Long): Result +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/AddOutboundUseCase.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/AddOutboundUseCase.kt new file mode 100644 index 0000000..d00c5d8 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/AddOutboundUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.outbound.domain.usecase + +import com.sampoom.android.feature.outbound.domain.repository.OutboundRepository +import javax.inject.Inject + +class AddOutboundUseCase @Inject constructor( + private val repository: OutboundRepository +) { + suspend operator fun invoke(partId: Long, quantity: Long) = repository.addOutbound(partId, quantity) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteOutboundUseCase.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteOutboundUseCase.kt new file mode 100644 index 0000000..9c3a12f --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteOutboundUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.outbound.domain.usecase + +import com.sampoom.android.feature.outbound.domain.repository.OutboundRepository +import javax.inject.Inject + +class DeleteOutboundUseCase @Inject constructor( + private val repository: OutboundRepository +){ + suspend operator fun invoke(outboundId: Long) = repository.deleteOutbound(outboundId) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/GetOutboundUseCase.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/GetOutboundUseCase.kt new file mode 100644 index 0000000..20047c4 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/GetOutboundUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.outbound.domain.usecase + +import com.sampoom.android.feature.outbound.domain.repository.OutboundRepository +import javax.inject.Inject + +class GetOutboundUseCase @Inject constructor( + private val repository: OutboundRepository +) { + suspend operator fun invoke() = repository.getOutboundList() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/UpdateOutboundQuantityUseCase.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/UpdateOutboundQuantityUseCase.kt new file mode 100644 index 0000000..31166db --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/UpdateOutboundQuantityUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.outbound.domain.usecase + +import com.sampoom.android.feature.outbound.domain.repository.OutboundRepository +import javax.inject.Inject + +class UpdateOutboundQuantityUseCase @Inject constructor( + private val repository: OutboundRepository +) { + suspend operator fun invoke(outboundId: Long, quantity: Long) = repository.updateOutboundQuantity(outboundId, quantity) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt new file mode 100644 index 0000000..ae1984f --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt @@ -0,0 +1,334 @@ +package com.sampoom.android.feature.outbound.ui + +import android.util.Log.v +import android.view.RoundedCorner +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.OutlinedTextFieldDefaults +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.viewmodel.compose.viewModel +import com.sampoom.android.R +import com.sampoom.android.core.ui.component.ButtonSize +import com.sampoom.android.core.ui.component.ButtonVariant +import com.sampoom.android.core.ui.component.CommonButton +import com.sampoom.android.core.ui.component.EmptyContent +import com.sampoom.android.core.ui.component.ErrorContent +import com.sampoom.android.core.ui.theme.FailRed +import com.sampoom.android.core.ui.theme.Main500 +import com.sampoom.android.core.ui.theme.backgroundCardColor +import com.sampoom.android.core.ui.theme.textColor +import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.feature.outbound.domain.model.OutboundPart +import com.sampoom.android.feature.part.ui.PartDetailUiEvent + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun OutboundListScreen( + viewModel: OutboundListViewModel = hiltViewModel() +) { + val errorLabel = stringResource(R.string.common_error) + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + + LaunchedEffect(errorLabel) { + viewModel.bindLabel(errorLabel) + viewModel.onEvent(OutboundListUiEvent.LoadOutboundList) + } + + Column(Modifier.fillMaxSize()) { + Text( + text = stringResource(R.string.outbound_title), + style = MaterialTheme.typography.titleLarge, + color = textColor(), + modifier = Modifier + .fillMaxWidth() + .padding(24.dp) + ) + + when { + uiState.outboundLoading -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + + uiState.outboundError != null -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + ErrorContent( + onRetry = { viewModel.onEvent(OutboundListUiEvent.RetryOutboundList) }, + modifier = Modifier.height(200.dp) + ) + } + } + + uiState.outboundList.isEmpty() -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + EmptyContent( + message = stringResource(R.string.outbound_empty_outbound), + modifier = Modifier.height(200.dp) + ) + } + } + + else -> { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + uiState.outboundList.forEach { category -> + category.groups.forEach { group -> + item { + OutboundSection( + categoryName = category.categoryName, + groupName = group.groupName, + parts = group.parts, + isUpdating = uiState.isUpdating, + isDeleting = uiState.isDeleting, + onEvent = { viewModel.onEvent(it) } + ) + } + } + } + } + } + } + } +} + +@Composable +private fun OutboundSection( + categoryName: String, + groupName: String, + parts: List, + isUpdating: Boolean, + isDeleting: Boolean, + onEvent: (OutboundListUiEvent) -> Unit +) { + Column( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + text = "$categoryName > $groupName", + style = MaterialTheme.typography.titleMedium, + color = textColor() + ) + + parts.forEach { part -> + OutboundPartItem( + part = part, + isUpdating = isUpdating, + isDeleting = isDeleting, + onEvent = onEvent + ) + } + } +} + +@Composable +private fun OutboundPartItem( + part: OutboundPart, + isUpdating: Boolean, + isDeleting: Boolean, + onEvent: (OutboundListUiEvent) -> Unit +) { + Card( + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors(containerColor = backgroundCardColor()) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier.weight(1F) + ) { + Text( + text = part.name, + style = MaterialTheme.typography.titleMedium, + color = textColor(), + modifier = Modifier.fillMaxWidth() + ) + Text( + text = part.code, + style = MaterialTheme.typography.bodySmall, + color = textSecondaryColor(), + modifier = Modifier.fillMaxWidth() + ) + } + + IconButton( + onClick = { + onEvent(OutboundListUiEvent.DeleteOutbound(part.outboundId)) + }, + enabled = !isDeleting + ) { + Icon( + painter = painterResource(R.drawable.delete), + contentDescription = stringResource(R.string.common_delete), + tint = FailRed + ) + } + } + + Spacer(Modifier.height(16.dp)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End, + verticalAlignment = Alignment.CenterVertically, + ) { + Text(text = stringResource(R.string.part_title_quantity), Modifier.weight(1F)) + Row( + verticalAlignment = Alignment.CenterVertically, + ) { + CommonButton( + variant = ButtonVariant.Neutral, + size = ButtonSize.Large, + onClick = { + if (part.quantity > 1) onEvent( + OutboundListUiEvent.UpdateQuantity( + part.outboundId, + part.quantity - 1 + ) + ) + }, + enabled = !isUpdating && part.quantity > 1 + ) { + Text( + text = stringResource(R.string.part_minus), + style = MaterialTheme.typography.titleLarge + ) + } + + Text( + text = part.quantity.toString(), + style = MaterialTheme.typography.titleMedium, + modifier = Modifier.padding(horizontal = 24.dp) + ) +// OutlinedTextField( +// value = part.quantity.toString(), +// onValueChange = { newValue -> +// when { +// newValue.isEmpty() -> onEvent(OutboundListUiEvent.UpdateQuantity(part.outboundId, 1)) +// newValue == "0" -> onEvent(OutboundListUiEvent.UpdateQuantity(part.outboundId, 1)) +// else -> { +// val newQuantity = newValue.toLongOrNull() +// if (newQuantity != null && newQuantity > 0) onEvent(OutboundListUiEvent.UpdateQuantity(part.outboundId, newQuantity)) +// else onEvent(OutboundListUiEvent.UpdateQuantity(part.outboundId, 1)) +// } +// } +// }, +// modifier = Modifier.width(100.dp), +// singleLine = true, +// keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), +// textStyle = MaterialTheme.typography.titleMedium.copy(textAlign = TextAlign.Center), +// colors = OutlinedTextFieldDefaults.colors( +// focusedBorderColor = Color.Transparent, +// unfocusedBorderColor = Color.Transparent, +// disabledBorderColor = Color.Transparent, +// errorBorderColor = Color.Transparent +// ) +// ) + CommonButton( + variant = ButtonVariant.Neutral, + size = ButtonSize.Large, + onClick = { + onEvent( + OutboundListUiEvent.UpdateQuantity( + part.outboundId, + part.quantity + 1 + ) + ) + }, + enabled = !isUpdating + ) { + Text( + text = stringResource(R.string.part_plus), + style = MaterialTheme.typography.titleLarge + ) + } + } + } + + // 오른쪽: 삭제 버튼과 수량 조절 + /*Column( + horizontalAlignment = Alignment.End + ) { + // 삭제 버튼 + IconButton( + onClick = { *//* 삭제 로직 *//* } + ) { + Icon( + painter = painterResource(id = R.drawable.ic_delete), + contentDescription = "삭제", + tint = MaterialTheme.colorScheme.error + ) + } + + // 수량 조절 컨트롤 + QuantityControl( + quantity = part.quantity, + onQuantityChange = { newQuantity -> + // 수량 변경 로직 + } + ) + }*/ + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiEvent.kt new file mode 100644 index 0000000..b6bdf76 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiEvent.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.outbound.ui + +sealed interface OutboundListUiEvent { + object LoadOutboundList : OutboundListUiEvent + object RetryOutboundList : OutboundListUiEvent + data class UpdateQuantity(val outboundId: Long, val quantity: Long) : OutboundListUiEvent + data class DeleteOutbound(val outboundId: Long) : OutboundListUiEvent + object ClearUpdateError : OutboundListUiEvent + object ClearDeleteError : OutboundListUiEvent +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt new file mode 100644 index 0000000..031753c --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt @@ -0,0 +1,14 @@ +package com.sampoom.android.feature.outbound.ui + +import com.sampoom.android.feature.outbound.domain.model.Outbound + +data class OutboundListUiState( + val outboundList: List = emptyList(), + val outboundLoading: Boolean = false, + val outboundError: String? = null, + val selectedOutbound: Outbound? = null, + val isUpdating: Boolean = false, + val updateError: String? = null, + val isDeleting: Boolean = false, + val deleteError: String? = null +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt new file mode 100644 index 0000000..84e3bd2 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt @@ -0,0 +1,160 @@ +package com.sampoom.android.feature.outbound.ui + +import android.util.Log +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.feature.outbound.domain.usecase.DeleteOutboundUseCase +import com.sampoom.android.feature.outbound.domain.usecase.GetOutboundUseCase +import com.sampoom.android.feature.outbound.domain.usecase.UpdateOutboundQuantityUseCase +import dagger.hilt.android.lifecycle.HiltViewModel +import jakarta.inject.Inject +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch + +@HiltViewModel +class OutboundListViewModel @Inject constructor( + private val getOutboundUseCase: GetOutboundUseCase, + private val updateOutboundQuantityUseCase: UpdateOutboundQuantityUseCase, + private val deleteOutboundUseCase: DeleteOutboundUseCase +) : ViewModel() { + private val _uiState = MutableStateFlow(OutboundListUiState()) + val uiState: StateFlow = _uiState + + private var errorLabel: String = "" + + fun bindLabel(error: String) { + errorLabel = error + } + + init { + loadOutboundList() + } + + fun onEvent(event: OutboundListUiEvent) { + when (event) { + is OutboundListUiEvent.LoadOutboundList -> loadOutboundList() + is OutboundListUiEvent.RetryOutboundList -> loadOutboundList() + is OutboundListUiEvent.UpdateQuantity -> updateQuantity(event.outboundId, event.quantity) + is OutboundListUiEvent.DeleteOutbound -> deleteOutbound(event.outboundId) + is OutboundListUiEvent.ClearUpdateError -> _uiState.update { it.copy(updateError = null) } + is OutboundListUiEvent.ClearDeleteError -> _uiState.update { it.copy(deleteError = null) } + } + } + + private fun loadOutboundList() { + viewModelScope.launch { + _uiState.update { it.copy(outboundLoading = true, outboundError = null) } + + runCatching { getOutboundUseCase() } + .onSuccess { outboundList -> + _uiState.update { + it.copy( + outboundList = outboundList.items, + outboundLoading = false, + outboundError = null + ) + } + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + outboundLoading = false, + outboundError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + + } + Log.d("OutboundListViewModel", "submit: ${_uiState.value}") + } + } + + private fun updateQuantity(outboundId: Long, newQuantity: Long) { + viewModelScope.launch { + _uiState.update { it.copy(isUpdating = true, updateError = null) } + + runCatching { updateOutboundQuantityUseCase(outboundId, newQuantity) } + .onSuccess { + _uiState.update { it.copy(isUpdating = false) } + updateLocalQuantity(outboundId, newQuantity) + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + isUpdating = false, + updateError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + } + Log.d("OutboundListViewModel", "submit: ${_uiState.value}") + } + } + + private fun updateLocalQuantity(outboundId: Long, newQuantity: Long) { + _uiState.update { currentState -> + val updatedList = currentState.outboundList.map { category -> + category.copy( + groups = category.groups.map { group -> + group.copy( + parts = group.parts.map { part -> + if (part.outboundId == outboundId) { + part.copy(quantity = newQuantity) + } else { + part + } + } + ) + } + ) + } + currentState.copy(outboundList = updatedList) + } + } + + private fun deleteOutbound(outboundId: Long) { + viewModelScope.launch { + _uiState.update { it.copy(isDeleting = true, deleteError = null) } + + runCatching { deleteOutboundUseCase(outboundId) } + .onSuccess { + _uiState.update { it.copy(isDeleting = false) } + removeFromLocalList(outboundId) + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + isUpdating = false, + updateError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + } + Log.d("OutboundListViewModel", "submit: ${_uiState.value}") + } + } + + private fun removeFromLocalList(outboundId: Long) { + _uiState.update { currentState -> + val updatedList = currentState.outboundList.map { category -> + category.copy( + groups = category.groups.map { group -> + group.copy( + parts = group.parts.filter { part -> + part.outboundId != outboundId + } + ) + }.filter { group -> + group.parts.isNotEmpty() + } + ) + }.filter { category -> + category.groups.isNotEmpty() + } + currentState.copy(outboundList = updatedList) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt index f99c727..41a2f9c 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt @@ -1,5 +1,6 @@ package com.sampoom.android.feature.part.ui +import android.widget.Toast import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -9,17 +10,23 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.AlertDialog import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.KeyboardType @@ -35,18 +42,47 @@ import com.sampoom.android.core.ui.component.CommonButton import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.part.domain.model.Part +import kotlinx.coroutines.delay @Composable fun PartDetailBottomSheet( part: Part, + onDismiss: () -> Unit, viewModel: PartDetailViewModel = hiltViewModel() ) { + val errorLabel = stringResource(R.string.common_error) val uiState by viewModel.uiState.collectAsStateWithLifecycle() + var showConfirmDialog by remember { mutableStateOf(false) } + val context = LocalContext.current - LaunchedEffect(part) { + LaunchedEffect(Unit) { + viewModel.clearSuccess() + } + + LaunchedEffect(errorLabel) { + viewModel.bindLabel(errorLabel) + } + + LaunchedEffect(part.partId) { viewModel.onEvent(PartDetailUiEvent.Initialize(part)) } + // 성공 시 Toast 표시 후 다이얼로그 닫기 + LaunchedEffect(uiState.isSuccess) { + if (uiState.isSuccess) { + Toast.makeText(context, context.getString(R.string.outbound_toast_success), Toast.LENGTH_SHORT).show() + } + viewModel.clearSuccess() + } + + // 실패 시 Toast 표시 + LaunchedEffect(uiState.updateError) { + uiState.updateError?.let { error -> + Toast.makeText(context, error, Toast.LENGTH_LONG).show() + viewModel.onEvent(PartDetailUiEvent.ClearError) + } + } + Column( modifier = Modifier .fillMaxWidth() @@ -151,11 +187,11 @@ fun PartDetailBottomSheet( size = ButtonSize.Large, leadingIcon = { Icon( - painterResource(R.drawable.delivery), + painterResource(R.drawable.outbound), contentDescription = null ) }, - onClick = {} // TODO: API 연동 + onClick = { showConfirmDialog = true } ) { Text(stringResource(R.string.part_add_delivery)) } Spacer(Modifier.width(8.dp)) CommonButton( @@ -167,17 +203,34 @@ fun PartDetailBottomSheet( ) { Text(stringResource(R.string.part_add_cart)) } } } -} -@Preview(showBackground = true) -@Composable -fun PartDetailBottomSheetPreview() { - PartDetailBottomSheet( - part = Part( - partId = 1, - name = "엔진", - code = "ENG", - quantity = 12 + // 확인 다이얼로그 + if (showConfirmDialog) { + AlertDialog( + onDismissRequest = { showConfirmDialog = false }, + text = { Text(stringResource(R.string.outbound_dialog_text)) }, + confirmButton = { + TextButton( + onClick = { + showConfirmDialog = false + viewModel.onEvent( + PartDetailUiEvent.AddToOutbound( + partId = part.partId, + quantity = uiState.quantity + ) + ) + } + ) { + Text(stringResource(R.string.common_confirm)) + } + }, + dismissButton = { + TextButton( + onClick = { showConfirmDialog = false } + ) { + Text(stringResource(R.string.common_cancel)) + } + } ) - ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt index f63c7e5..137ab66 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt @@ -7,7 +7,7 @@ sealed interface PartDetailUiEvent { object IncreaseQuantity : PartDetailUiEvent object DecreaseQuantity : PartDetailUiEvent data class SetQuantity(val quantity: Long) : PartDetailUiEvent - object UpdateQuantity : PartDetailUiEvent + data class AddToOutbound(val partId: Long, val quantity: Long) : PartDetailUiEvent object ClearError : PartDetailUiEvent object Dismiss : PartDetailUiEvent } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiState.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiState.kt index dd19fd2..dc500b2 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiState.kt @@ -6,5 +6,6 @@ data class PartDetailUiState( val part: Part? = null, val quantity: Long = 1, val isUpdating: Boolean = false, - val updateError: String? = null + val updateError: String? = null, + val isSuccess: Boolean = false ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt index 7e0980d..d49e6c8 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt @@ -1,18 +1,30 @@ package com.sampoom.android.feature.part.ui +import android.util.Log import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.feature.outbound.domain.usecase.AddOutboundUseCase import dagger.hilt.android.lifecycle.HiltViewModel import jakarta.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch @HiltViewModel class PartDetailViewModel @Inject constructor( + private val addOutboundUseCase: AddOutboundUseCase ) : ViewModel() { private val _uiState = MutableStateFlow(PartDetailUiState()) val uiState: StateFlow = _uiState + private var errorLabel: String = "" + + fun bindLabel(error: String) { + errorLabel = error + } + fun onEvent(event: PartDetailUiEvent) { when (event) { is PartDetailUiEvent.Initialize -> { @@ -20,7 +32,9 @@ class PartDetailViewModel @Inject constructor( it.copy( part = event.part, quantity = 1, - updateError = null + isUpdating = false, + updateError = null, + isSuccess = false ) } } @@ -37,11 +51,11 @@ class PartDetailViewModel @Inject constructor( _uiState.update { it.copy(quantity = event.quantity) } } } - is PartDetailUiEvent.UpdateQuantity -> { + is PartDetailUiEvent.AddToOutbound -> { val part = _uiState.value.part val quantity = _uiState.value.quantity if (part != null) { - // TODO : updatePartQuantity(part.partId, quantity) + addToOutbound(part.partId, quantity) } } is PartDetailUiEvent.ClearError -> _uiState.update { it.copy(updateError = null) } @@ -56,4 +70,29 @@ class PartDetailViewModel @Inject constructor( } } } + + private fun addToOutbound(partId: Long, quantity: Long) { + viewModelScope.launch { + _uiState.update { it.copy(isUpdating = true, updateError = null) } + + runCatching { addOutboundUseCase(partId, quantity) } + .onSuccess { + _uiState.update { it.copy(isUpdating = false, isSuccess = true) } + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + isUpdating = false, + updateError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + } + Log.d("OutboundDetailViewModel", "submit: ${_uiState.value}") + } + } + + fun clearSuccess() { + _uiState.update { it.copy(isSuccess = false) } + } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt index 493705d..17f7c76 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt @@ -1,7 +1,5 @@ package com.sampoom.android.feature.part.ui -import android.app.ProgressDialog.show -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -152,7 +150,11 @@ fun PartListScreen( sheetState = sheetState ) { PartDetailBottomSheet( - part = selectedPart + part = selectedPart, + onDismiss = { + showBottomSheet = false + viewModel.onEvent(PartListUiEvent.DismissBottomSheet) + } ) } } diff --git a/app/src/main/res/drawable/delete.xml b/app/src/main/res/drawable/delete.xml new file mode 100644 index 0000000..b5b0071 --- /dev/null +++ b/app/src/main/res/drawable/delete.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/delivery.xml b/app/src/main/res/drawable/outbound.xml similarity index 100% rename from app/src/main/res/drawable/delivery.xml rename to app/src/main/res/drawable/outbound.xml diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 04b4785..4e0fc5c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -56,10 +56,19 @@ 출고목록에 추가 장바구니에 추가 + + 출고목록 + 출고목록이 없습니다. + 출고 목록에 추가하시겠습니까? + 출고 목록에 추가되었습니다 + 오류가 발생했습니다 다시 시도 + 확인 + 취소 닫기 + 삭제 상세 보기 EA From 72c28ce75a0f8bcf5b2926e76fe4131ad348b609 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Sun, 19 Oct 2025 22:03:11 +0900 Subject: [PATCH 35/88] =?UTF-8?q?[FEAT]=20=EC=B6=9C=EA=B3=A0=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D,=20=EC=9E=A5=EB=B0=94=EA=B5=AC=EB=8B=88=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20/=20=EC=B6=9C=EA=B3=A0=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80,=20=EC=9E=A5=EB=B0=94=EA=B5=AC=EB=8B=88=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=B6=94=EA=B0=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/AppNavHost.kt | 9 +- .../feature/cart/data/local/database/.gitkeep | 0 .../cart/data/local/preferences/.gitkeep | 0 .../android/feature/cart/data/mapper/.gitkeep | 0 .../feature/cart/data/mapper/CartMappers.kt | 12 + .../feature/cart/data/remote/api/.gitkeep | 0 .../feature/cart/data/remote/api/CartApi.kt | 38 ++ .../feature/cart/data/remote/dto/.gitkeep | 0 .../cart/data/remote/dto/AddCartRequestDto.kt | 6 + .../feature/cart/data/remote/dto/CartDto.kt | 21 + .../data/remote/dto/UpdateCartRequestDto.kt | 5 + .../feature/cart/data/repository/.gitkeep | 0 .../data/repository/CartRepositoryImpl.kt | 53 +++ .../sampoom/android/feature/cart/di/.gitkeep | 0 .../android/feature/cart/di/CartModules.kt | 27 ++ .../feature/cart/domain/model/.gitkeep | 0 .../android/feature/cart/domain/model/Cart.kt | 21 + .../feature/cart/domain/model/CartList.kt | 11 + .../feature/cart/domain/repository/.gitkeep | 0 .../cart/domain/repository/CartRepository.kt | 11 + .../feature/cart/domain/usecase/.gitkeep | 0 .../cart/domain/usecase/AddCartUseCase.kt | 10 + .../domain/usecase/DeleteAllCartUseCase.kt | 10 + .../cart/domain/usecase/DeleteCartUseCase.kt | 10 + .../cart/domain/usecase/GetCartUseCase.kt | 10 + .../usecase/UpdateCartQuantityUseCase.kt | 10 + .../sampoom/android/feature/cart/ui/.gitkeep | 0 .../android/feature/cart/ui/CartListScreen.kt | 406 ++++++++++++++++++ .../feature/cart/ui/CartListUiEvent.kt | 12 + .../feature/cart/ui/CartListUiState.kt | 15 + .../feature/cart/ui/CartListViewModel.kt | 219 ++++++++++ .../outbound/data/remote/api/OutboundApi.kt | 4 + .../data/repository/OutboundRepositoryImpl.kt | 14 + .../domain/repository/OutboundRepository.kt | 2 + .../usecase/DeleteAllOutboundUseCase.kt | 10 + .../domain/usecase/ProcessOutboundUseCase.kt | 10 + .../feature/outbound/ui/OutboundListScreen.kt | 177 ++++++-- .../outbound/ui/OutboundListUiEvent.kt | 2 + .../outbound/ui/OutboundListUiState.kt | 3 +- .../outbound/ui/OutboundListViewModel.kt | 63 ++- .../feature/part/ui/PartDetailBottomSheet.kt | 56 ++- .../feature/part/ui/PartDetailUiEvent.kt | 1 + .../feature/part/ui/PartDetailUiState.kt | 3 +- .../feature/part/ui/PartDetailViewModel.kt | 39 +- app/src/main/res/values/strings.xml | 16 + 45 files changed, 1246 insertions(+), 70 deletions(-) delete mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/local/database/.gitkeep delete mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/local/preferences/.gitkeep delete mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/mapper/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/mapper/CartMappers.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/AddCartRequestDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/CartDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/UpdateCartRequestDto.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/repository/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/cart/di/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/di/CartModules.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/cart/domain/model/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/domain/model/Cart.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/domain/model/CartList.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/cart/domain/repository/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/domain/repository/CartRepository.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/AddCartUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteAllCartUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteCartUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/GetCartUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/UpdateCartQuantityUseCase.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/cart/ui/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiEvent.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteAllOutboundUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/ProcessOutboundUseCase.kt diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 0c123e9..fdf8411 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -22,6 +22,7 @@ import androidx.navigation.navArgument import com.sampoom.android.R import com.sampoom.android.feature.auth.ui.LoginScreen import com.sampoom.android.feature.auth.ui.SignUpScreen +import com.sampoom.android.feature.cart.ui.CartListScreen import com.sampoom.android.feature.outbound.ui.OutboundListScreen import com.sampoom.android.feature.part.ui.PartListScreen import com.sampoom.android.feature.part.ui.PartScreen @@ -132,7 +133,7 @@ fun MainScreen( ) { composable(ROUTE_DASHBOARD) { DashboardScreen() } composable(ROUTE_OUTBOUND) { OutboundListScreen() } - composable(ROUTE_CART) { CartScreen() } + composable(ROUTE_CART) { CartListScreen() } composable(ROUTE_ORDERS) { OrderScreen() } } } @@ -202,12 +203,6 @@ private fun DashboardScreen() { Text("대시보드 화면") } -@Composable -private fun CartScreen() { - // 프로필 화면 구현 - Text("Cart 화면") -} - @Composable private fun OrderScreen() { // 프로필 화면 구현 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/local/database/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/data/local/database/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/local/preferences/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/data/local/preferences/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/mapper/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/data/mapper/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/mapper/CartMappers.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/mapper/CartMappers.kt new file mode 100644 index 0000000..e6729c3 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/mapper/CartMappers.kt @@ -0,0 +1,12 @@ +package com.sampoom.android.feature.cart.data.mapper + +import com.sampoom.android.feature.cart.data.remote.dto.CartDto +import com.sampoom.android.feature.cart.data.remote.dto.CartGroupDto +import com.sampoom.android.feature.cart.data.remote.dto.CartPartDto +import com.sampoom.android.feature.cart.domain.model.Cart +import com.sampoom.android.feature.cart.domain.model.CartGroup +import com.sampoom.android.feature.cart.domain.model.CartPart + +fun CartDto.toModel(): Cart = Cart(categoryId, categoryName, groups.map { it.toModel() }) +fun CartGroupDto.toModel(): CartGroup = CartGroup(groupId, groupName, parts.map { it.toModel() }) +fun CartPartDto.toModel(): CartPart = CartPart(cartItemId, partId, code, name, quantity) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt new file mode 100644 index 0000000..ed96820 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt @@ -0,0 +1,38 @@ +package com.sampoom.android.feature.cart.data.remote.api + +import com.sampoom.android.core.network.ApiResponse +import com.sampoom.android.core.network.ApiSuccessResponse +import com.sampoom.android.feature.cart.data.remote.dto.AddCartRequestDto +import com.sampoom.android.feature.cart.data.remote.dto.CartDto +import com.sampoom.android.feature.cart.data.remote.dto.UpdateCartRequestDto +import retrofit2.http.Body +import retrofit2.http.DELETE +import retrofit2.http.GET +import retrofit2.http.POST +import retrofit2.http.PUT +import retrofit2.http.Path + +interface CartApi { + // 장바구니 목록 조회 + @GET("agency/1/cart") + suspend fun getCartList(): ApiResponse> + + // 장바구니에 부품 추가 + @POST("agency/1/cart") + suspend fun addCart(@Body body: AddCartRequestDto): ApiSuccessResponse + + // 장바구니 항목 삭제 + @DELETE("agency/1/cart/{cartItemId}") + suspend fun deleteCart(@Path("cartItemId") cartItemId: Long): ApiSuccessResponse + + // 장바구니 수량 변경 + @PUT("agency/1/cart/{cartItemId}") + suspend fun updateCart( + @Path("cartItemId") cartItemId: Long, + @Body body: UpdateCartRequestDto + ): ApiSuccessResponse + + // 징바구니 전체 비우기 + @DELETE("agency/1/cart/clear") + suspend fun deleteAllCart(): ApiSuccessResponse +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/AddCartRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/AddCartRequestDto.kt new file mode 100644 index 0000000..a47af11 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/AddCartRequestDto.kt @@ -0,0 +1,6 @@ +package com.sampoom.android.feature.cart.data.remote.dto + +data class AddCartRequestDto( + val partId: Long, + val quantity: Long +) diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/CartDto.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/CartDto.kt new file mode 100644 index 0000000..6f4b211 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/CartDto.kt @@ -0,0 +1,21 @@ +package com.sampoom.android.feature.cart.data.remote.dto + +data class CartDto( + val categoryId: Long, + val categoryName: String, + val groups: List +) + +data class CartGroupDto( + val groupId: Long, + val groupName: String, + val parts: List +) + +data class CartPartDto( + val cartItemId: Long, + val partId: Long, + val code: String, + val name: String, + val quantity: Long +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/UpdateCartRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/UpdateCartRequestDto.kt new file mode 100644 index 0000000..87d5841 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/UpdateCartRequestDto.kt @@ -0,0 +1,5 @@ +package com.sampoom.android.feature.cart.data.remote.dto + +data class UpdateCartRequestDto( + val quantity: Long +) diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/repository/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/data/repository/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt new file mode 100644 index 0000000..70021a1 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt @@ -0,0 +1,53 @@ +package com.sampoom.android.feature.cart.data.repository + +import com.sampoom.android.feature.cart.data.mapper.toModel +import com.sampoom.android.feature.cart.data.remote.api.CartApi +import com.sampoom.android.feature.cart.data.remote.dto.AddCartRequestDto +import com.sampoom.android.feature.cart.data.remote.dto.UpdateCartRequestDto +import com.sampoom.android.feature.cart.domain.model.CartList +import com.sampoom.android.feature.cart.domain.repository.CartRepository +import javax.inject.Inject + +class CartRepositoryImpl @Inject constructor( + private val api: CartApi +) : CartRepository { + override suspend fun getCartList(): CartList { + val dto = api.getCartList() + val cartItems = dto.data.map { it.toModel() } + return CartList(items = cartItems) + } + + override suspend fun addCart( + partId: Long, + quantity: Long + ): Result { + val dto = api.addCart(AddCartRequestDto(partId, quantity)) + return runCatching { + if (!dto.success) throw Exception(dto.message) + } + } + + override suspend fun deleteCart(cartItemId: Long): Result { + val dto = api.deleteCart(cartItemId) + return runCatching { + if (!dto.success) throw Exception(dto.message) + } + } + + override suspend fun deleteAllCart(): Result { + val dto = api.deleteAllCart() + return runCatching { + if (!dto.success) throw Exception(dto.message) + } + } + + override suspend fun updateCartQuantity( + cartItemId: Long, + quantity: Long + ): Result { + val dto = api.updateCart(cartItemId, UpdateCartRequestDto(quantity)) + return runCatching { + if (!dto.success) throw Exception(dto.message) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/di/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/di/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/di/CartModules.kt b/app/src/main/java/com/sampoom/android/feature/cart/di/CartModules.kt new file mode 100644 index 0000000..83573bd --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/di/CartModules.kt @@ -0,0 +1,27 @@ +package com.sampoom.android.feature.cart.di + +import com.sampoom.android.feature.cart.data.remote.api.CartApi +import com.sampoom.android.feature.cart.data.repository.CartRepositoryImpl +import com.sampoom.android.feature.cart.domain.repository.CartRepository +import dagger.Binds +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import retrofit2.Retrofit +import javax.inject.Singleton +import kotlin.jvm.java + +@Module +@InstallIn(SingletonComponent::class) +abstract class CartBinModule { + @Binds @Singleton + abstract fun bindCartRepository(impl: CartRepositoryImpl): CartRepository +} + +@Module +@InstallIn(SingletonComponent::class) +object CartModule { + @Provides @Singleton + fun provideCartApi(retrofit: Retrofit): CartApi = retrofit.create(CartApi::class.java) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/model/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/domain/model/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/model/Cart.kt b/app/src/main/java/com/sampoom/android/feature/cart/domain/model/Cart.kt new file mode 100644 index 0000000..1caf613 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/domain/model/Cart.kt @@ -0,0 +1,21 @@ +package com.sampoom.android.feature.cart.domain.model + +data class Cart( + val categoryId: Long, + val categoryName: String, + val groups: List +) + +data class CartGroup( + val groupId: Long, + val groupName: String, + val parts: List +) + +data class CartPart( + val cartItemId: Long, + val partId: Long, + val code: String, + val name: String, + val quantity: Long +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/model/CartList.kt b/app/src/main/java/com/sampoom/android/feature/cart/domain/model/CartList.kt new file mode 100644 index 0000000..ac270e4 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/domain/model/CartList.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.cart.domain.model + +data class CartList( + val items: List, + val totalCount: Int = items.size, + val isEmpty: Boolean = items.isEmpty() +) { + companion object Companion { + fun empty() = CartList(emptyList()) + } +} diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/repository/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/domain/repository/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/repository/CartRepository.kt b/app/src/main/java/com/sampoom/android/feature/cart/domain/repository/CartRepository.kt new file mode 100644 index 0000000..3620388 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/domain/repository/CartRepository.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.cart.domain.repository + +import com.sampoom.android.feature.cart.domain.model.CartList + +interface CartRepository { + suspend fun getCartList(): CartList + suspend fun addCart(partId: Long, quantity: Long): Result + suspend fun deleteCart(cartItemId: Long): Result + suspend fun deleteAllCart(): Result + suspend fun updateCartQuantity(cartItemId: Long, quantity: Long): Result +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/AddCartUseCase.kt b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/AddCartUseCase.kt new file mode 100644 index 0000000..b174a9e --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/AddCartUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.cart.domain.usecase + +import com.sampoom.android.feature.cart.domain.repository.CartRepository +import jakarta.inject.Inject + +class AddCartUseCase @Inject constructor( + private val repository: CartRepository +) { + suspend operator fun invoke(partId: Long, quantity: Long) = repository.addCart(partId, quantity) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteAllCartUseCase.kt b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteAllCartUseCase.kt new file mode 100644 index 0000000..53c3aff --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteAllCartUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.cart.domain.usecase + +import com.sampoom.android.feature.cart.domain.repository.CartRepository +import javax.inject.Inject + +class DeleteAllCartUseCase @Inject constructor( + private val repository: CartRepository +) { + suspend operator fun invoke() = repository.deleteAllCart() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteCartUseCase.kt b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteCartUseCase.kt new file mode 100644 index 0000000..9b16880 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteCartUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.cart.domain.usecase + +import com.sampoom.android.feature.cart.domain.repository.CartRepository +import javax.inject.Inject + +class DeleteCartUseCase @Inject constructor( + private val repository: CartRepository +) { + suspend operator fun invoke(cartItemId: Long) = repository.deleteCart(cartItemId) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/GetCartUseCase.kt b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/GetCartUseCase.kt new file mode 100644 index 0000000..5c71e2b --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/GetCartUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.cart.domain.usecase + +import com.sampoom.android.feature.cart.domain.repository.CartRepository +import javax.inject.Inject + +class GetCartUseCase @Inject constructor( + private val repository: CartRepository +) { + suspend operator fun invoke() = repository.getCartList() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/UpdateCartQuantityUseCase.kt b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/UpdateCartQuantityUseCase.kt new file mode 100644 index 0000000..0c26680 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/UpdateCartQuantityUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.cart.domain.usecase + +import com.sampoom.android.feature.cart.domain.repository.CartRepository +import javax.inject.Inject + +class UpdateCartQuantityUseCase @Inject constructor( + private val repository: CartRepository +) { + suspend operator fun invoke(cartItemId: Long, quantity: Long) = repository.updateCartQuantity(cartItemId, quantity) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/.gitkeep b/app/src/main/java/com/sampoom/android/feature/cart/ui/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt new file mode 100644 index 0000000..4496d46 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt @@ -0,0 +1,406 @@ +package com.sampoom.android.feature.cart.ui + +import android.R.attr.onClick +import android.widget.Toast +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.shadow +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.sampoom.android.R +import com.sampoom.android.core.ui.component.ButtonSize +import com.sampoom.android.core.ui.component.ButtonVariant +import com.sampoom.android.core.ui.component.CommonButton +import com.sampoom.android.core.ui.component.EmptyContent +import com.sampoom.android.core.ui.component.ErrorContent +import com.sampoom.android.core.ui.theme.FailRed +import com.sampoom.android.core.ui.theme.backgroundCardColor +import com.sampoom.android.core.ui.theme.textColor +import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.feature.cart.domain.model.CartPart +import com.sampoom.android.feature.outbound.ui.OutboundListUiEvent +import kotlin.collections.forEach + +@Composable +fun CartListScreen( + viewModel: CartListViewModel = hiltViewModel() +) { + val errorLabel = stringResource(R.string.common_error) + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + var showEmptyCartDialog by remember { mutableStateOf(false) } + var showConfirmDialog by remember { mutableStateOf(false) } + val context = LocalContext.current + + LaunchedEffect(Unit) { + viewModel.clearSuccess() + } + + LaunchedEffect(errorLabel) { + viewModel.bindLabel(errorLabel) + viewModel.onEvent(CartListUiEvent.LoadCartList) + } + + LaunchedEffect(uiState.isOrderSuccess) { + if (uiState.isOrderSuccess) { + Toast.makeText( + context, + context.getString(R.string.cart_toast_order_text), + Toast.LENGTH_SHORT + ).show() + } + viewModel.clearSuccess() + } + + Column(Modifier.fillMaxSize()) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + modifier = Modifier + .padding(vertical = 16.dp), + text = stringResource(R.string.cart_title), + style = MaterialTheme.typography.titleLarge, + color = textColor() + ) + + when { + uiState.cartLoading -> {} + uiState.cartError != null -> {} + uiState.cartList.isEmpty() -> {} + else -> { + TextButton( + onClick = { showEmptyCartDialog = true } + ) { + Text( + text = stringResource(R.string.cart_empty_list), + style = MaterialTheme.typography.titleMedium, + color = FailRed + ) + } + } + } + } + + + when { + uiState.cartLoading -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + + uiState.cartError != null -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + ErrorContent( + onRetry = { viewModel.onEvent(CartListUiEvent.RetryCartList) }, + modifier = Modifier.height(200.dp) + ) + } + } + + uiState.cartList.isEmpty() -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + EmptyContent( + message = stringResource(R.string.cart_empty_outbound), + modifier = Modifier.height(200.dp) + ) + } + } + + else -> { + Box(modifier = Modifier.fillMaxSize()) { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + uiState.cartList.forEach { category -> + category.groups.forEach { group -> + item { + CartSection( + categoryName = category.categoryName, + groupName = group.groupName, + parts = group.parts, + isUpdating = uiState.isUpdating, + isDeleting = uiState.isDeleting, + onEvent = { viewModel.onEvent(it) } + ) + } + } + } + item { Spacer(Modifier.height(100.dp)) } + } + + CommonButton( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.BottomEnd) + .padding(16.dp) + .padding(end = 72.dp), + variant = ButtonVariant.Primary, + size = ButtonSize.Large, + onClick = { showConfirmDialog = true } + ) { Text(stringResource(R.string.cart_order_parts)) } + } + } + } + } + + if (showEmptyCartDialog) { + AlertDialog( + onDismissRequest = { showEmptyCartDialog = false }, + text = { Text(stringResource(R.string.cart_dialog_empty_text)) }, + confirmButton = { + TextButton( + onClick = { + showEmptyCartDialog = false + viewModel.onEvent(CartListUiEvent.DeleteAllCart) + } + ) { + Text(stringResource(R.string.common_confirm)) + } + }, + dismissButton = { + TextButton( + onClick = { showConfirmDialog = false } + ) { + Text(stringResource(R.string.common_cancel)) + } + } + ) + } + + if (showConfirmDialog) { + AlertDialog( + onDismissRequest = { showConfirmDialog = false }, + text = { Text(stringResource(R.string.cart_dialog_order_text)) }, + confirmButton = { + TextButton( + onClick = { + showConfirmDialog = false + viewModel.onEvent(CartListUiEvent.ProcessOrder) + } + ) { + Text(stringResource(R.string.common_confirm)) + } + }, + dismissButton = { + TextButton( + onClick = { showConfirmDialog = false } + ) { + Text(stringResource(R.string.common_cancel)) + } + } + ) + } +} + +@Composable +private fun CartSection( + categoryName: String, + groupName: String, + parts: List, + isUpdating: Boolean, + isDeleting: Boolean, + onEvent: (CartListUiEvent) -> Unit +) { + Column( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + text = "$categoryName > $groupName", + style = MaterialTheme.typography.titleMedium, + color = textColor() + ) + + parts.forEach { part -> + CartPartItem( + part = part, + isUpdating = isUpdating, + isDeleting = isDeleting, + onEvent = onEvent + ) + } + } +} + +@Composable +private fun CartPartItem( + part: CartPart, + isUpdating: Boolean, + isDeleting: Boolean, + onEvent: (CartListUiEvent) -> Unit +) { + Card( + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors(containerColor = backgroundCardColor()) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier.weight(1F) + ) { + Text( + text = part.name, + style = MaterialTheme.typography.titleMedium, + color = textColor(), + modifier = Modifier.fillMaxWidth() + ) + Text( + text = part.code, + style = MaterialTheme.typography.bodySmall, + color = textSecondaryColor(), + modifier = Modifier.fillMaxWidth() + ) + } + + IconButton( + onClick = { + onEvent(CartListUiEvent.DeleteCart(part.cartItemId)) + }, + enabled = !isDeleting + ) { + Icon( + painter = painterResource(R.drawable.delete), + contentDescription = stringResource(R.string.common_delete), + tint = FailRed + ) + } + } + + Spacer(Modifier.height(16.dp)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End, + verticalAlignment = Alignment.CenterVertically, + ) { + Text(text = stringResource(R.string.part_title_quantity), Modifier.weight(1F)) + Row( + verticalAlignment = Alignment.CenterVertically, + ) { + CommonButton( + variant = ButtonVariant.Neutral, + size = ButtonSize.Large, + onClick = { + if (part.quantity > 1) onEvent( + CartListUiEvent.UpdateQuantity( + part.cartItemId, + part.quantity - 1 + ) + ) + }, + enabled = !isUpdating && part.quantity > 1 + ) { + Text( + text = stringResource(R.string.part_minus), + style = MaterialTheme.typography.titleLarge + ) + } + + Text( + text = part.quantity.toString(), + style = MaterialTheme.typography.titleMedium, + modifier = Modifier.padding(horizontal = 24.dp) + ) +// OutlinedTextField( +// value = part.quantity.toString(), +// onValueChange = { newValue -> +// when { +// newValue.isEmpty() -> onEvent(OutboundListUiEvent.UpdateQuantity(part.outboundId, 1)) +// newValue == "0" -> onEvent(OutboundListUiEvent.UpdateQuantity(part.outboundId, 1)) +// else -> { +// val newQuantity = newValue.toLongOrNull() +// if (newQuantity != null && newQuantity > 0) onEvent(OutboundListUiEvent.UpdateQuantity(part.outboundId, newQuantity)) +// else onEvent(OutboundListUiEvent.UpdateQuantity(part.outboundId, 1)) +// } +// } +// }, +// modifier = Modifier.width(100.dp), +// singleLine = true, +// keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), +// textStyle = MaterialTheme.typography.titleMedium.copy(textAlign = TextAlign.Center), +// colors = OutlinedTextFieldDefaults.colors( +// focusedBorderColor = Color.Transparent, +// unfocusedBorderColor = Color.Transparent, +// disabledBorderColor = Color.Transparent, +// errorBorderColor = Color.Transparent +// ) +// ) + CommonButton( + variant = ButtonVariant.Neutral, + size = ButtonSize.Large, + onClick = { + onEvent( + CartListUiEvent.UpdateQuantity( + part.cartItemId, + part.quantity + 1 + ) + ) + }, + enabled = !isUpdating + ) { + Text( + text = stringResource(R.string.part_plus), + style = MaterialTheme.typography.titleLarge + ) + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiEvent.kt new file mode 100644 index 0000000..f96cb48 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiEvent.kt @@ -0,0 +1,12 @@ +package com.sampoom.android.feature.cart.ui + +sealed interface CartListUiEvent { + object LoadCartList : CartListUiEvent + object RetryCartList : CartListUiEvent + object ProcessOrder : CartListUiEvent + data class UpdateQuantity(val cartItemId: Long, val quantity: Long) : CartListUiEvent + data class DeleteCart(val cartItemId: Long) : CartListUiEvent + object DeleteAllCart : CartListUiEvent + object ClearUpdateError : CartListUiEvent + object ClearDeleteError : CartListUiEvent +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt new file mode 100644 index 0000000..d6ae356 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt @@ -0,0 +1,15 @@ +package com.sampoom.android.feature.cart.ui + +import com.sampoom.android.feature.cart.domain.model.Cart + +data class CartListUiState( + val cartList: List = emptyList(), + val cartLoading: Boolean = false, + val cartError: String? = null, + val selectedCart: Cart? = null, + val isUpdating: Boolean = false, + val updateError: String? = null, + val isDeleting: Boolean = false, + val deleteError: String? = null, + val isOrderSuccess: Boolean = false +) diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt new file mode 100644 index 0000000..7f9f1db --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt @@ -0,0 +1,219 @@ +package com.sampoom.android.feature.cart.ui + +import android.util.Log +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.feature.cart.domain.usecase.DeleteAllCartUseCase +import com.sampoom.android.feature.cart.domain.usecase.DeleteCartUseCase +import com.sampoom.android.feature.cart.domain.usecase.GetCartUseCase +import com.sampoom.android.feature.cart.domain.usecase.UpdateCartQuantityUseCase +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class CartListViewModel @Inject constructor( + private val getCartListUseCase: GetCartUseCase, + private val updateCartQuantityUseCase: UpdateCartQuantityUseCase, + private val deleteCartUseCase: DeleteCartUseCase, + private val deleteAllCartUseCase: DeleteAllCartUseCase +) : ViewModel() { + private val _uiState = MutableStateFlow(CartListUiState()) + val uiState: StateFlow = _uiState + + private var errorLabel: String = "" + + fun bindLabel(error: String) { + errorLabel = error + } + + init { + loadCartList() + } + + fun onEvent(event: CartListUiEvent) { + when (event) { + is CartListUiEvent.LoadCartList -> loadCartList() + is CartListUiEvent.RetryCartList -> loadCartList() + is CartListUiEvent.ProcessOrder -> processOrder() + is CartListUiEvent.UpdateQuantity -> updateQuantity(event.cartItemId, event.quantity) + is CartListUiEvent.DeleteCart -> deleteCart(event.cartItemId) + is CartListUiEvent.DeleteAllCart -> deleteAllCart() + is CartListUiEvent.ClearUpdateError -> _uiState.update { it.copy(updateError = null) } + is CartListUiEvent.ClearDeleteError -> _uiState.update { it.copy(deleteError = null) } + } + } + + private fun loadCartList() { + viewModelScope.launch { + _uiState.update { it.copy(cartLoading = true, cartError = null) } + + runCatching { getCartListUseCase() } + .onSuccess { cartList -> + _uiState.update { + it.copy( + cartList = cartList.items, + cartLoading = false, + cartError = null + ) + } + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + cartLoading = false, + cartError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + + } + Log.d("CartListViewModel", "submit: ${_uiState.value}") + } + } + + // TODO() : 주문 생성 로직 + private fun processOrder() { + viewModelScope.launch { + _uiState.update { it.copy(cartLoading = true, cartError = null) } + +// runCatching { processCartUseCase() } +// .onSuccess { +// _uiState.update { it.copy(isUpdating = false, isOrderSuccess = true) } +// loadCartList() +// } +// .onFailure { throwable -> +// val backendMessage = throwable.serverMessageOrNull() +// _uiState.update { +// it.copy( +// isUpdating = false, +// updateError = backendMessage ?: (throwable.message ?: errorLabel) +// ) +// } +// } + Log.d("OutboundListViewModel", "submit: ${_uiState.value}") + } + } + + private fun updateQuantity(cartItemId: Long, newQuantity: Long) { + viewModelScope.launch { + _uiState.update { it.copy(isUpdating = true, updateError = null) } + + runCatching { updateCartQuantityUseCase(cartItemId, newQuantity) } + .onSuccess { + _uiState.update { it.copy(isUpdating = false) } + updateLocalQuantity(cartItemId, newQuantity) + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + isUpdating = false, + updateError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + } + Log.d("CartListViewModel", "submit: ${_uiState.value}") + } + } + + private fun updateLocalQuantity(cartItemId: Long, newQuantity: Long) { + _uiState.update { currentState -> + val updatedList = currentState.cartList.map { category -> + category.copy( + groups = category.groups.map { group -> + group.copy( + parts = group.parts.map { part -> + if (part.cartItemId == cartItemId) { + part.copy(quantity = newQuantity) + } else { + part + } + } + ) + } + ) + } + currentState.copy(cartList = updatedList) + } + } + + private fun deleteCart(cartItemId: Long) { + viewModelScope.launch { + _uiState.update { it.copy(isDeleting = true, deleteError = null) } + + runCatching { deleteCartUseCase(cartItemId) } + .onSuccess { + _uiState.update { it.copy(isDeleting = false) } + removeFromLocalList(cartItemId) + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + isUpdating = false, + updateError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + } + Log.d("CartListViewModel", "submit: ${_uiState.value}") + } + } + + private fun deleteAllCart() { + viewModelScope.launch { + _uiState.update { it.copy(isDeleting = true, deleteError = null) } + + runCatching { deleteAllCartUseCase() } + .onSuccess { + _uiState.update { it.copy(isDeleting = false) } + removeAllFromLocalList() + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + isUpdating = false, + updateError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + } + Log.d("CartListViewModel", "submit: ${_uiState.value}") + } + } + + private fun removeFromLocalList(cartItemId: Long) { + _uiState.update { currentState -> + val updatedList = currentState.cartList.map { category -> + category.copy( + groups = category.groups.map { group -> + group.copy( + parts = group.parts.filter { part -> + part.cartItemId != cartItemId + } + ) + }.filter { group -> + group.parts.isNotEmpty() + } + ) + }.filter { category -> + category.groups.isNotEmpty() + } + currentState.copy(cartList = updatedList) + } + } + + private fun removeAllFromLocalList() { + _uiState.update { currentState -> + currentState.copy(cartList = emptyList()) + } + } + + fun clearSuccess() { + _uiState.update { it.copy(isOrderSuccess = false) } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt index 7ef2dd5..02c13bf 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt @@ -35,4 +35,8 @@ interface OutboundApi { @Path("outboundId") outboundId: Long, @Body body: UpdateOutboundRequestDto ): ApiSuccessResponse + + // 출고 목록 전체 비우기 + @DELETE("agency/1/outbound/clear") + suspend fun deleteAllOutbound(): ApiSuccessResponse } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt index 6940a07..1139cf5 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt @@ -17,6 +17,13 @@ class OutboundRepositoryImpl @Inject constructor( return OutboundList(items = outboundItems) } + override suspend fun processOutbound(): Result { + val dto = api.processOutbound() + return runCatching { + if (!dto.success) throw Exception(dto.message) + } + } + override suspend fun addOutbound( partId: Long, quantity: Long @@ -34,6 +41,13 @@ class OutboundRepositoryImpl @Inject constructor( } } + override suspend fun deleteAllOutbound(): Result { + val dto = api.deleteAllOutbound() + return runCatching { + if (!dto.success) throw Exception(dto.message) + } + } + override suspend fun updateOutboundQuantity( outboundId: Long, quantity: Long diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/repository/OutboundRepository.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/repository/OutboundRepository.kt index 68d3dd6..8633113 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/domain/repository/OutboundRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/repository/OutboundRepository.kt @@ -4,7 +4,9 @@ import com.sampoom.android.feature.outbound.domain.model.OutboundList interface OutboundRepository { suspend fun getOutboundList(): OutboundList + suspend fun processOutbound(): Result suspend fun addOutbound(partId: Long, quantity: Long): Result suspend fun deleteOutbound(outboundId: Long): Result + suspend fun deleteAllOutbound(): Result suspend fun updateOutboundQuantity(outboundId: Long, quantity: Long): Result } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteAllOutboundUseCase.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteAllOutboundUseCase.kt new file mode 100644 index 0000000..5bbaef5 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteAllOutboundUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.outbound.domain.usecase + +import com.sampoom.android.feature.outbound.domain.repository.OutboundRepository +import javax.inject.Inject + +class DeleteAllOutboundUseCase @Inject constructor( + private val repository: OutboundRepository +){ + suspend operator fun invoke() = repository.deleteAllOutbound() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/ProcessOutboundUseCase.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/ProcessOutboundUseCase.kt new file mode 100644 index 0000000..221570a --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/ProcessOutboundUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.outbound.domain.usecase + +import com.sampoom.android.feature.outbound.domain.repository.OutboundRepository +import javax.inject.Inject + +class ProcessOutboundUseCase @Inject constructor( + private val repository: OutboundRepository +){ + suspend operator fun invoke() = repository.processOutbound() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt index ae1984f..fca0a3e 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt @@ -2,6 +2,7 @@ package com.sampoom.android.feature.outbound.ui import android.util.Log.v import android.view.RoundedCorner +import android.widget.Toast import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -18,6 +19,7 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.AlertDialog import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.CircularProgressIndicator @@ -28,14 +30,19 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.KeyboardType @@ -65,21 +72,59 @@ fun OutboundListScreen( ) { val errorLabel = stringResource(R.string.common_error) val uiState by viewModel.uiState.collectAsStateWithLifecycle() + var showEmptyOutboundDialog by remember { mutableStateOf(false) } + var showConfirmDialog by remember { mutableStateOf(false) } + val context = LocalContext.current + + LaunchedEffect(Unit) { + viewModel.clearSuccess() + } LaunchedEffect(errorLabel) { viewModel.bindLabel(errorLabel) viewModel.onEvent(OutboundListUiEvent.LoadOutboundList) } + LaunchedEffect(uiState.isOrderSuccess) { + if (uiState.isOrderSuccess) { + Toast.makeText(context, context.getString(R.string.outbound_toast_order_text), Toast.LENGTH_SHORT).show() + } + viewModel.clearSuccess() + } + Column(Modifier.fillMaxSize()) { - Text( - text = stringResource(R.string.outbound_title), - style = MaterialTheme.typography.titleLarge, - color = textColor(), + Row( modifier = Modifier .fillMaxWidth() - .padding(24.dp) - ) + .padding(horizontal = 16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + modifier = Modifier + .padding(vertical = 16.dp), + text = stringResource(R.string.outbound_title), + style = MaterialTheme.typography.titleLarge, + color = textColor() + ) + + when { + uiState.outboundLoading -> {} + uiState.outboundError != null -> {} + uiState.outboundList.isEmpty() -> {} + else -> { + TextButton( + onClick = { showEmptyOutboundDialog = true } + ) { + Text( + text = stringResource(R.string.outbound_empty_list), + style = MaterialTheme.typography.titleMedium, + color = FailRed + ) + } + } + } + } when { uiState.outboundLoading -> { @@ -119,30 +164,92 @@ fun OutboundListScreen( } else -> { - LazyColumn( - modifier = Modifier - .fillMaxSize() - .padding(horizontal = 16.dp), - verticalArrangement = Arrangement.spacedBy(16.dp) - ) { - uiState.outboundList.forEach { category -> - category.groups.forEach { group -> - item { - OutboundSection( - categoryName = category.categoryName, - groupName = group.groupName, - parts = group.parts, - isUpdating = uiState.isUpdating, - isDeleting = uiState.isDeleting, - onEvent = { viewModel.onEvent(it) } - ) + Box(modifier = Modifier.fillMaxSize()) { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + uiState.outboundList.forEach { category -> + category.groups.forEach { group -> + item { + OutboundSection( + categoryName = category.categoryName, + groupName = group.groupName, + parts = group.parts, + isUpdating = uiState.isUpdating, + isDeleting = uiState.isDeleting, + onEvent = { viewModel.onEvent(it) } + ) + } } } + item { Spacer(Modifier.height(100.dp)) } } + + CommonButton( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.BottomEnd) + .padding(16.dp) + .padding(end = 72.dp), + variant = ButtonVariant.Error, + size = ButtonSize.Large, + onClick = { showConfirmDialog = true } + ) { Text(stringResource(R.string.outbound_order_parts)) } } } } } + + if (showEmptyOutboundDialog) { + AlertDialog( + onDismissRequest = { showEmptyOutboundDialog = false }, + text = { Text(stringResource(R.string.outbound_dialog_empty_text)) }, + confirmButton = { + TextButton( + onClick = { + showEmptyOutboundDialog = false + viewModel.onEvent(OutboundListUiEvent.DeleteAllOutbound) + } + ) { + Text(stringResource(R.string.common_confirm)) + } + }, + dismissButton = { + TextButton( + onClick = { showEmptyOutboundDialog = false } + ) { + Text(stringResource(R.string.common_cancel)) + } + } + ) + } + + if (showConfirmDialog) { + AlertDialog( + onDismissRequest = { showConfirmDialog = false }, + text = { Text(stringResource(R.string.outbound_dialog_order_text)) }, + confirmButton = { + TextButton( + onClick = { + showConfirmDialog = false + viewModel.onEvent(OutboundListUiEvent.ProcessOutbound) + } + ) { + Text(stringResource(R.string.common_confirm)) + } + }, + dismissButton = { + TextButton( + onClick = { showConfirmDialog = false } + ) { + Text(stringResource(R.string.common_cancel)) + } + } + ) + } } @Composable @@ -305,30 +412,6 @@ private fun OutboundPartItem( } } } - - // 오른쪽: 삭제 버튼과 수량 조절 - /*Column( - horizontalAlignment = Alignment.End - ) { - // 삭제 버튼 - IconButton( - onClick = { *//* 삭제 로직 *//* } - ) { - Icon( - painter = painterResource(id = R.drawable.ic_delete), - contentDescription = "삭제", - tint = MaterialTheme.colorScheme.error - ) - } - - // 수량 조절 컨트롤 - QuantityControl( - quantity = part.quantity, - onQuantityChange = { newQuantity -> - // 수량 변경 로직 - } - ) - }*/ } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiEvent.kt index b6bdf76..48a2ca2 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiEvent.kt @@ -3,8 +3,10 @@ package com.sampoom.android.feature.outbound.ui sealed interface OutboundListUiEvent { object LoadOutboundList : OutboundListUiEvent object RetryOutboundList : OutboundListUiEvent + object ProcessOutbound : OutboundListUiEvent data class UpdateQuantity(val outboundId: Long, val quantity: Long) : OutboundListUiEvent data class DeleteOutbound(val outboundId: Long) : OutboundListUiEvent + object DeleteAllOutbound : OutboundListUiEvent object ClearUpdateError : OutboundListUiEvent object ClearDeleteError : OutboundListUiEvent } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt index 031753c..65ba96d 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt @@ -10,5 +10,6 @@ data class OutboundListUiState( val isUpdating: Boolean = false, val updateError: String? = null, val isDeleting: Boolean = false, - val deleteError: String? = null + val deleteError: String? = null, + val isOrderSuccess: Boolean = false ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt index 84e3bd2..115f049 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt @@ -1,11 +1,14 @@ package com.sampoom.android.feature.outbound.ui import android.util.Log +import android.util.Log.v import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.feature.outbound.domain.usecase.DeleteAllOutboundUseCase import com.sampoom.android.feature.outbound.domain.usecase.DeleteOutboundUseCase import com.sampoom.android.feature.outbound.domain.usecase.GetOutboundUseCase +import com.sampoom.android.feature.outbound.domain.usecase.ProcessOutboundUseCase import com.sampoom.android.feature.outbound.domain.usecase.UpdateOutboundQuantityUseCase import dagger.hilt.android.lifecycle.HiltViewModel import jakarta.inject.Inject @@ -17,8 +20,10 @@ import kotlinx.coroutines.launch @HiltViewModel class OutboundListViewModel @Inject constructor( private val getOutboundUseCase: GetOutboundUseCase, + private val processOutboundUseCase: ProcessOutboundUseCase, private val updateOutboundQuantityUseCase: UpdateOutboundQuantityUseCase, - private val deleteOutboundUseCase: DeleteOutboundUseCase + private val deleteOutboundUseCase: DeleteOutboundUseCase, + private val deleteAllOutboundUseCase: DeleteAllOutboundUseCase ) : ViewModel() { private val _uiState = MutableStateFlow(OutboundListUiState()) val uiState: StateFlow = _uiState @@ -37,8 +42,10 @@ class OutboundListViewModel @Inject constructor( when (event) { is OutboundListUiEvent.LoadOutboundList -> loadOutboundList() is OutboundListUiEvent.RetryOutboundList -> loadOutboundList() + is OutboundListUiEvent.ProcessOutbound -> processOutBound() is OutboundListUiEvent.UpdateQuantity -> updateQuantity(event.outboundId, event.quantity) is OutboundListUiEvent.DeleteOutbound -> deleteOutbound(event.outboundId) + is OutboundListUiEvent.DeleteAllOutbound -> deleteAllOutbound() is OutboundListUiEvent.ClearUpdateError -> _uiState.update { it.copy(updateError = null) } is OutboundListUiEvent.ClearDeleteError -> _uiState.update { it.copy(deleteError = null) } } @@ -72,6 +79,28 @@ class OutboundListViewModel @Inject constructor( } } + private fun processOutBound() { + viewModelScope.launch { + _uiState.update { it.copy(outboundLoading = true, outboundError = null) } + + runCatching { processOutboundUseCase() } + .onSuccess { + _uiState.update { it.copy(isUpdating = false, isOrderSuccess = true) } + loadOutboundList() + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + isUpdating = false, + updateError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + } + Log.d("OutboundListViewModel", "submit: ${_uiState.value}") + } + } + private fun updateQuantity(outboundId: Long, newQuantity: Long) { viewModelScope.launch { _uiState.update { it.copy(isUpdating = true, updateError = null) } @@ -137,6 +166,28 @@ class OutboundListViewModel @Inject constructor( } } + private fun deleteAllOutbound() { + viewModelScope.launch { + _uiState.update { it.copy(isDeleting = true, deleteError = null) } + + runCatching { deleteAllOutboundUseCase() } + .onSuccess { + _uiState.update { it.copy(isDeleting = false) } + removeAllFromLocalList() + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + isUpdating = false, + updateError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + } + Log.d("OutboundListViewModel", "submit: ${_uiState.value}") + } + } + private fun removeFromLocalList(outboundId: Long) { _uiState.update { currentState -> val updatedList = currentState.outboundList.map { category -> @@ -157,4 +208,14 @@ class OutboundListViewModel @Inject constructor( currentState.copy(outboundList = updatedList) } } + + private fun removeAllFromLocalList() { + _uiState.update { currentState -> + currentState.copy(outboundList = emptyList()) + } + } + + fun clearSuccess() { + _uiState.update { it.copy(isOrderSuccess = false) } + } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt index 41a2f9c..24419cd 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt @@ -52,7 +52,8 @@ fun PartDetailBottomSheet( ) { val errorLabel = stringResource(R.string.common_error) val uiState by viewModel.uiState.collectAsStateWithLifecycle() - var showConfirmDialog by remember { mutableStateOf(false) } + var showOutboundDialog by remember { mutableStateOf(false) } + var showCartDialog by remember { mutableStateOf(false) } val context = LocalContext.current LaunchedEffect(Unit) { @@ -68,13 +69,21 @@ fun PartDetailBottomSheet( } // 성공 시 Toast 표시 후 다이얼로그 닫기 - LaunchedEffect(uiState.isSuccess) { - if (uiState.isSuccess) { + LaunchedEffect(uiState.isOutboundSuccess) { + if (uiState.isOutboundSuccess) { Toast.makeText(context, context.getString(R.string.outbound_toast_success), Toast.LENGTH_SHORT).show() } viewModel.clearSuccess() } + // 성공 시 Toast 표시 후 다이얼로그 닫기 + LaunchedEffect(uiState.isCartSuccess) { + if (uiState.isCartSuccess) { + Toast.makeText(context, context.getString(R.string.cart_toast_success), Toast.LENGTH_SHORT).show() + } + viewModel.clearSuccess() + } + // 실패 시 Toast 표시 LaunchedEffect(uiState.updateError) { uiState.updateError?.let { error -> @@ -191,7 +200,7 @@ fun PartDetailBottomSheet( contentDescription = null ) }, - onClick = { showConfirmDialog = true } + onClick = { showOutboundDialog = true } ) { Text(stringResource(R.string.part_add_delivery)) } Spacer(Modifier.width(8.dp)) CommonButton( @@ -199,20 +208,20 @@ fun PartDetailBottomSheet( variant = ButtonVariant.Primary, size = ButtonSize.Large, leadingIcon = { Icon(painterResource(R.drawable.cart), contentDescription = null) }, - onClick = {} // TODO: API 연동 + onClick = { showCartDialog = true } ) { Text(stringResource(R.string.part_add_cart)) } } } // 확인 다이얼로그 - if (showConfirmDialog) { + if (showOutboundDialog) { AlertDialog( - onDismissRequest = { showConfirmDialog = false }, + onDismissRequest = { showOutboundDialog = false }, text = { Text(stringResource(R.string.outbound_dialog_text)) }, confirmButton = { TextButton( onClick = { - showConfirmDialog = false + showOutboundDialog = false viewModel.onEvent( PartDetailUiEvent.AddToOutbound( partId = part.partId, @@ -226,7 +235,36 @@ fun PartDetailBottomSheet( }, dismissButton = { TextButton( - onClick = { showConfirmDialog = false } + onClick = { showOutboundDialog = false } + ) { + Text(stringResource(R.string.common_cancel)) + } + } + ) + } + + if (showCartDialog) { + AlertDialog( + onDismissRequest = { showCartDialog = false }, + text = { Text(stringResource(R.string.cart_dialog_text)) }, + confirmButton = { + TextButton( + onClick = { + showCartDialog = false + viewModel.onEvent( + PartDetailUiEvent.AddToCart( + partId = part.partId, + quantity = uiState.quantity + ) + ) + } + ) { + Text(stringResource(R.string.common_confirm)) + } + }, + dismissButton = { + TextButton( + onClick = { showCartDialog = false } ) { Text(stringResource(R.string.common_cancel)) } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt index 137ab66..b9ea49a 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt @@ -8,6 +8,7 @@ sealed interface PartDetailUiEvent { object DecreaseQuantity : PartDetailUiEvent data class SetQuantity(val quantity: Long) : PartDetailUiEvent data class AddToOutbound(val partId: Long, val quantity: Long) : PartDetailUiEvent + data class AddToCart(val partId: Long, val quantity: Long) : PartDetailUiEvent object ClearError : PartDetailUiEvent object Dismiss : PartDetailUiEvent } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiState.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiState.kt index dc500b2..ed51a5d 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiState.kt @@ -7,5 +7,6 @@ data class PartDetailUiState( val quantity: Long = 1, val isUpdating: Boolean = false, val updateError: String? = null, - val isSuccess: Boolean = false + val isOutboundSuccess: Boolean = false, + val isCartSuccess: Boolean = false ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt index d49e6c8..96addcb 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt @@ -4,6 +4,7 @@ import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.feature.cart.domain.usecase.AddCartUseCase import com.sampoom.android.feature.outbound.domain.usecase.AddOutboundUseCase import dagger.hilt.android.lifecycle.HiltViewModel import jakarta.inject.Inject @@ -14,7 +15,8 @@ import kotlinx.coroutines.launch @HiltViewModel class PartDetailViewModel @Inject constructor( - private val addOutboundUseCase: AddOutboundUseCase + private val addOutboundUseCase: AddOutboundUseCase, + private val addCartUseCase: AddCartUseCase ) : ViewModel() { private val _uiState = MutableStateFlow(PartDetailUiState()) val uiState: StateFlow = _uiState @@ -34,7 +36,8 @@ class PartDetailViewModel @Inject constructor( quantity = 1, isUpdating = false, updateError = null, - isSuccess = false + isOutboundSuccess = false, + isCartSuccess = false ) } } @@ -58,6 +61,13 @@ class PartDetailViewModel @Inject constructor( addToOutbound(part.partId, quantity) } } + is PartDetailUiEvent.AddToCart -> { + val part = _uiState.value.part + val quantity = _uiState.value.quantity + if (part != null) { + addToCart(part.partId, quantity) + } + } is PartDetailUiEvent.ClearError -> _uiState.update { it.copy(updateError = null) } is PartDetailUiEvent.Dismiss -> { _uiState.update { @@ -77,7 +87,28 @@ class PartDetailViewModel @Inject constructor( runCatching { addOutboundUseCase(partId, quantity) } .onSuccess { - _uiState.update { it.copy(isUpdating = false, isSuccess = true) } + _uiState.update { it.copy(isUpdating = false, isOutboundSuccess = true) } + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + isUpdating = false, + updateError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + } + Log.d("OutboundDetailViewModel", "submit: ${_uiState.value}") + } + } + + private fun addToCart(partId: Long, quantity: Long) { + viewModelScope.launch { + _uiState.update { it.copy(isUpdating = true, updateError = null) } + + runCatching { addCartUseCase(partId, quantity) } + .onSuccess { + _uiState.update { it.copy(isUpdating = false, isCartSuccess = true) } } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() @@ -93,6 +124,6 @@ class PartDetailViewModel @Inject constructor( } fun clearSuccess() { - _uiState.update { it.copy(isSuccess = false) } + _uiState.update { it.copy(isOutboundSuccess = false, isCartSuccess = false) } } } \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4e0fc5c..7faede2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -58,9 +58,25 @@ 출고목록 + 출고목록 비우기 출고목록이 없습니다. 출고 목록에 추가하시겠습니까? 출고 목록에 추가되었습니다 + 출고 처리하시겠습니까? + 출고목록을 비우시겠습니까? + 출고 처리되었습니다 + 부품 출고처리 + + + 장바구니 + 장바구니 비우기 + 장바구니 목록이 없습니다. + 장바구니 목록에 추가하시겠습니까? + 장바구니 목록에 추가되었습니다 + 장바구니에 추가하시겠습니까? + 장바구니를 비우시겠습니까? + 추가되었습니다 + 부품 주문 오류가 발생했습니다 From 324dfda72f0d5a1e2fd72ada3b51c355cc207095 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Sun, 19 Oct 2025 23:04:26 +0900 Subject: [PATCH 36/88] =?UTF-8?q?[FIX]=20runCatching=20Result=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EB=9E=98=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/auth/ui/LoginViewModel.kt | 7 +++- .../feature/auth/ui/SignUpViewModel.kt | 7 +++- .../feature/cart/data/remote/api/CartApi.kt | 2 +- .../android/feature/cart/di/CartModules.kt | 1 - .../cart/domain/usecase/AddCartUseCase.kt | 2 +- .../android/feature/cart/ui/CartListScreen.kt | 5 +-- .../feature/cart/ui/CartListViewModel.kt | 35 ++++++++++------- .../feature/outbound/ui/OutboundListScreen.kt | 18 --------- .../outbound/ui/OutboundListViewModel.kt | 39 +++++++++++-------- .../feature/part/ui/PartDetailViewModel.kt | 17 +++++--- .../feature/part/ui/PartListViewModel.kt | 7 +++- .../android/feature/part/ui/PartViewModel.kt | 13 ++++--- 12 files changed, 81 insertions(+), 72 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt index 83ba328..e2f404a 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt @@ -20,6 +20,11 @@ class LoginViewModel @Inject constructor( private val singIn: LoginUseCase, private val application: Application ) : ViewModel() { + + private companion object { + private const val TAG = "LoginViewModel" + } + private val _uiState = MutableStateFlow(LoginUiState()) val uiState: StateFlow = _uiState @@ -83,7 +88,7 @@ class LoginViewModel @Inject constructor( it.copy(loading = false, error = backendMessage ?: (throwable.message ?: errorLabel)) } } - Log.d("LoginViewModel", "submit: ${_uiState.value}") + Log.d(TAG, "submit: ${_uiState.value}") } fun consumeError() { diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt index 70e0f79..73d29b6 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt @@ -20,6 +20,11 @@ class SignUpViewModel @Inject constructor( private val singUp: SignUpUseCase, private val application: Application ) : ViewModel() { + + private companion object { + private const val TAG = "SignUpViewModel" + } + private val _state = MutableStateFlow(SignUpUiState()) val state: StateFlow = _state @@ -147,7 +152,7 @@ class SignUpViewModel @Inject constructor( it.copy(loading = false, error = backendMessage ?: (throwable.message ?: errorLabel)) } } - Log.d("SignUpViewModel", "submit: ${_state.value}") + Log.d(TAG, "submit: ${_state.value}") } fun consumeError() { diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt index ed96820..aafff14 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt @@ -32,7 +32,7 @@ interface CartApi { @Body body: UpdateCartRequestDto ): ApiSuccessResponse - // 징바구니 전체 비우기 + // 장바구니 전체 비우기 @DELETE("agency/1/cart/clear") suspend fun deleteAllCart(): ApiSuccessResponse } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/di/CartModules.kt b/app/src/main/java/com/sampoom/android/feature/cart/di/CartModules.kt index 83573bd..18dc1bd 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/di/CartModules.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/di/CartModules.kt @@ -10,7 +10,6 @@ import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import retrofit2.Retrofit import javax.inject.Singleton -import kotlin.jvm.java @Module @InstallIn(SingletonComponent::class) diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/AddCartUseCase.kt b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/AddCartUseCase.kt index b174a9e..753f6f6 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/AddCartUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/AddCartUseCase.kt @@ -1,7 +1,7 @@ package com.sampoom.android.feature.cart.domain.usecase import com.sampoom.android.feature.cart.domain.repository.CartRepository -import jakarta.inject.Inject +import javax.inject.Inject class AddCartUseCase @Inject constructor( private val repository: CartRepository diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt index 4496d46..b48d196 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt @@ -1,6 +1,5 @@ package com.sampoom.android.feature.cart.ui -import android.R.attr.onClick import android.widget.Toast import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -29,7 +28,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.shadow import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -47,7 +45,6 @@ import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.cart.domain.model.CartPart -import com.sampoom.android.feature.outbound.ui.OutboundListUiEvent import kotlin.collections.forEach @Composable @@ -208,7 +205,7 @@ fun CartListScreen( }, dismissButton = { TextButton( - onClick = { showConfirmDialog = false } + onClick = { showEmptyCartDialog = false } ) { Text(stringResource(R.string.common_cancel)) } diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt index 7f9f1db..1be0d4f 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt @@ -22,6 +22,11 @@ class CartListViewModel @Inject constructor( private val deleteCartUseCase: DeleteCartUseCase, private val deleteAllCartUseCase: DeleteAllCartUseCase ) : ViewModel() { + + private companion object { + private const val TAG = "CartListViewModel" + } + private val _uiState = MutableStateFlow(CartListUiState()) val uiState: StateFlow = _uiState @@ -72,16 +77,16 @@ class CartListViewModel @Inject constructor( } } - Log.d("CartListViewModel", "submit: ${_uiState.value}") + Log.d(TAG, "submit: ${_uiState.value}") } } // TODO() : 주문 생성 로직 private fun processOrder() { viewModelScope.launch { - _uiState.update { it.copy(cartLoading = true, cartError = null) } - -// runCatching { processCartUseCase() } +// _uiState.update { it.copy(cartLoading = true, cartError = null) } +// +// processCartUseCase() // .onSuccess { // _uiState.update { it.copy(isUpdating = false, isOrderSuccess = true) } // loadCartList() @@ -95,7 +100,7 @@ class CartListViewModel @Inject constructor( // ) // } // } - Log.d("OutboundListViewModel", "submit: ${_uiState.value}") + Log.d(TAG, "submit: ${_uiState.value}") } } @@ -103,7 +108,7 @@ class CartListViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(isUpdating = true, updateError = null) } - runCatching { updateCartQuantityUseCase(cartItemId, newQuantity) } + updateCartQuantityUseCase(cartItemId, newQuantity) .onSuccess { _uiState.update { it.copy(isUpdating = false) } updateLocalQuantity(cartItemId, newQuantity) @@ -117,7 +122,7 @@ class CartListViewModel @Inject constructor( ) } } - Log.d("CartListViewModel", "submit: ${_uiState.value}") + Log.d(TAG, "submit: ${_uiState.value}") } } @@ -146,7 +151,7 @@ class CartListViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(isDeleting = true, deleteError = null) } - runCatching { deleteCartUseCase(cartItemId) } + deleteCartUseCase(cartItemId) .onSuccess { _uiState.update { it.copy(isDeleting = false) } removeFromLocalList(cartItemId) @@ -155,12 +160,12 @@ class CartListViewModel @Inject constructor( val backendMessage = throwable.serverMessageOrNull() _uiState.update { it.copy( - isUpdating = false, - updateError = backendMessage ?: (throwable.message ?: errorLabel) + isDeleting = false, + deleteError = backendMessage ?: (throwable.message ?: errorLabel) ) } } - Log.d("CartListViewModel", "submit: ${_uiState.value}") + Log.d(TAG, "submit: ${_uiState.value}") } } @@ -168,7 +173,7 @@ class CartListViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(isDeleting = true, deleteError = null) } - runCatching { deleteAllCartUseCase() } + deleteAllCartUseCase() .onSuccess { _uiState.update { it.copy(isDeleting = false) } removeAllFromLocalList() @@ -177,12 +182,12 @@ class CartListViewModel @Inject constructor( val backendMessage = throwable.serverMessageOrNull() _uiState.update { it.copy( - isUpdating = false, - updateError = backendMessage ?: (throwable.message ?: errorLabel) + isDeleting = false, + deleteError = backendMessage ?: (throwable.message ?: errorLabel) ) } } - Log.d("CartListViewModel", "submit: ${_uiState.value}") + Log.d(TAG, "submit: ${_uiState.value}") } } diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt index fca0a3e..4323ec8 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt @@ -1,10 +1,6 @@ package com.sampoom.android.feature.outbound.ui -import android.util.Log.v -import android.view.RoundedCorner import android.widget.Toast -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -14,11 +10,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.AlertDialog import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults @@ -27,12 +19,8 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.OutlinedTextFieldDefaults import androidx.compose.material3.Text import androidx.compose.material3.TextButton -import androidx.compose.material3.TopAppBar -import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -41,16 +29,12 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.lifecycle.viewmodel.compose.viewModel import com.sampoom.android.R import com.sampoom.android.core.ui.component.ButtonSize import com.sampoom.android.core.ui.component.ButtonVariant @@ -58,12 +42,10 @@ import com.sampoom.android.core.ui.component.CommonButton import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent import com.sampoom.android.core.ui.theme.FailRed -import com.sampoom.android.core.ui.theme.Main500 import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.outbound.domain.model.OutboundPart -import com.sampoom.android.feature.part.ui.PartDetailUiEvent @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt index 115f049..921e8e3 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt @@ -1,7 +1,6 @@ package com.sampoom.android.feature.outbound.ui import android.util.Log -import android.util.Log.v import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sampoom.android.core.network.serverMessageOrNull @@ -11,11 +10,11 @@ import com.sampoom.android.feature.outbound.domain.usecase.GetOutboundUseCase import com.sampoom.android.feature.outbound.domain.usecase.ProcessOutboundUseCase import com.sampoom.android.feature.outbound.domain.usecase.UpdateOutboundQuantityUseCase import dagger.hilt.android.lifecycle.HiltViewModel -import jakarta.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import javax.inject.Inject @HiltViewModel class OutboundListViewModel @Inject constructor( @@ -25,6 +24,11 @@ class OutboundListViewModel @Inject constructor( private val deleteOutboundUseCase: DeleteOutboundUseCase, private val deleteAllOutboundUseCase: DeleteAllOutboundUseCase ) : ViewModel() { + + private companion object { + private const val TAG = "OutboundListViewModel" + } + private val _uiState = MutableStateFlow(OutboundListUiState()) val uiState: StateFlow = _uiState @@ -75,7 +79,7 @@ class OutboundListViewModel @Inject constructor( } } - Log.d("OutboundListViewModel", "submit: ${_uiState.value}") + Log.d(TAG, "submit: ${_uiState.value}") } } @@ -83,21 +87,22 @@ class OutboundListViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(outboundLoading = true, outboundError = null) } - runCatching { processOutboundUseCase() } + processOutboundUseCase() .onSuccess { - _uiState.update { it.copy(isUpdating = false, isOrderSuccess = true) } + _uiState.update { it.copy(outboundLoading = false, isUpdating = false, isOrderSuccess = true) } loadOutboundList() } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() _uiState.update { it.copy( + outboundLoading = false, isUpdating = false, - updateError = backendMessage ?: (throwable.message ?: errorLabel) + outboundError = backendMessage ?: (throwable.message ?: errorLabel) ) } } - Log.d("OutboundListViewModel", "submit: ${_uiState.value}") + Log.d(TAG, "submit: ${_uiState.value}") } } @@ -105,7 +110,7 @@ class OutboundListViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(isUpdating = true, updateError = null) } - runCatching { updateOutboundQuantityUseCase(outboundId, newQuantity) } + updateOutboundQuantityUseCase(outboundId, newQuantity) .onSuccess { _uiState.update { it.copy(isUpdating = false) } updateLocalQuantity(outboundId, newQuantity) @@ -119,7 +124,7 @@ class OutboundListViewModel @Inject constructor( ) } } - Log.d("OutboundListViewModel", "submit: ${_uiState.value}") + Log.d(TAG, "submit: ${_uiState.value}") } } @@ -148,7 +153,7 @@ class OutboundListViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(isDeleting = true, deleteError = null) } - runCatching { deleteOutboundUseCase(outboundId) } + deleteOutboundUseCase(outboundId) .onSuccess { _uiState.update { it.copy(isDeleting = false) } removeFromLocalList(outboundId) @@ -157,12 +162,12 @@ class OutboundListViewModel @Inject constructor( val backendMessage = throwable.serverMessageOrNull() _uiState.update { it.copy( - isUpdating = false, - updateError = backendMessage ?: (throwable.message ?: errorLabel) + isDeleting = false, + deleteError = backendMessage ?: (throwable.message ?: errorLabel) ) } } - Log.d("OutboundListViewModel", "submit: ${_uiState.value}") + Log.d(TAG, "submit: ${_uiState.value}") } } @@ -170,7 +175,7 @@ class OutboundListViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(isDeleting = true, deleteError = null) } - runCatching { deleteAllOutboundUseCase() } + deleteAllOutboundUseCase() .onSuccess { _uiState.update { it.copy(isDeleting = false) } removeAllFromLocalList() @@ -179,12 +184,12 @@ class OutboundListViewModel @Inject constructor( val backendMessage = throwable.serverMessageOrNull() _uiState.update { it.copy( - isUpdating = false, - updateError = backendMessage ?: (throwable.message ?: errorLabel) + isDeleting = false, + deleteError = backendMessage ?: (throwable.message ?: errorLabel) ) } } - Log.d("OutboundListViewModel", "submit: ${_uiState.value}") + Log.d(TAG, "submit: ${_uiState.value}") } } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt index 96addcb..d0c0c5c 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt @@ -7,17 +7,22 @@ import com.sampoom.android.core.network.serverMessageOrNull import com.sampoom.android.feature.cart.domain.usecase.AddCartUseCase import com.sampoom.android.feature.outbound.domain.usecase.AddOutboundUseCase import dagger.hilt.android.lifecycle.HiltViewModel -import jakarta.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import javax.inject.Inject @HiltViewModel class PartDetailViewModel @Inject constructor( private val addOutboundUseCase: AddOutboundUseCase, private val addCartUseCase: AddCartUseCase ) : ViewModel() { + + private companion object { + private const val TAG = "OutboundDetailViewModel" + } + private val _uiState = MutableStateFlow(PartDetailUiState()) val uiState: StateFlow = _uiState @@ -47,7 +52,7 @@ class PartDetailViewModel @Inject constructor( } is PartDetailUiEvent.DecreaseQuantity -> { val currentQuantity = _uiState.value.quantity - _uiState.update { it.copy(quantity = currentQuantity - 1) } + _uiState.update { it.copy(quantity = maxOf(1L, currentQuantity - 1)) } } is PartDetailUiEvent.SetQuantity -> { if (event.quantity > 0) { @@ -85,7 +90,7 @@ class PartDetailViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(isUpdating = true, updateError = null) } - runCatching { addOutboundUseCase(partId, quantity) } + addOutboundUseCase(partId, quantity) .onSuccess { _uiState.update { it.copy(isUpdating = false, isOutboundSuccess = true) } } @@ -98,7 +103,7 @@ class PartDetailViewModel @Inject constructor( ) } } - Log.d("OutboundDetailViewModel", "submit: ${_uiState.value}") + Log.d(TAG, "submit: ${_uiState.value}") } } @@ -106,7 +111,7 @@ class PartDetailViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(isUpdating = true, updateError = null) } - runCatching { addCartUseCase(partId, quantity) } + addCartUseCase(partId, quantity) .onSuccess { _uiState.update { it.copy(isUpdating = false, isCartSuccess = true) } } @@ -119,7 +124,7 @@ class PartDetailViewModel @Inject constructor( ) } } - Log.d("OutboundDetailViewModel", "submit: ${_uiState.value}") + Log.d(TAG, "submit: ${_uiState.value}") } } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt index 649431a..f582f31 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt @@ -18,6 +18,11 @@ class PartListViewModel @Inject constructor( private val getPartListUseCase: GetPartUseCase, savedStateHandle: SavedStateHandle ) : ViewModel() { + + private companion object { + private const val TAG = "PartListViewModel" + } + private val _uiState = MutableStateFlow(PartListUiState()) val uiState: StateFlow = _uiState @@ -68,7 +73,7 @@ class PartListViewModel @Inject constructor( ) } } - Log.d("PartListViewModel", "submit: ${_uiState.value}") + Log.d(TAG, "submit: ${_uiState.value}") } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt index 6bcf62a..b51315b 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt @@ -20,6 +20,11 @@ class PartViewModel @Inject constructor( private val getCategoryUseCase: GetCategoryUseCase, private val getGroupUseCase: GetGroupUseCase ) : ViewModel() { + + private companion object { + private const val TAG = "PartViewModel" + } + private val _uiState = MutableStateFlow(PartUiState()) val uiState: StateFlow = _uiState @@ -66,7 +71,7 @@ class PartViewModel @Inject constructor( ) } } - Log.d("PartViewModel", "submit: ${_uiState.value}") + Log.d(TAG, "submit: ${_uiState.value}") } } @@ -105,7 +110,7 @@ class PartViewModel @Inject constructor( ) } } - Log.d("PartViewModel", "submit: ${_uiState.value}") + Log.d(TAG, "submit: ${_uiState.value}") } } @@ -115,8 +120,4 @@ class PartViewModel @Inject constructor( loadGroup(selectedCategory.id) } } - -// fun refreshPart() { -// loadCategory() -// } } \ No newline at end of file From 1d90c189f44381203edadf34a7d91c753a3384e6 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Sun, 19 Oct 2025 23:12:04 +0900 Subject: [PATCH 37/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/outbound/ui/OutboundListViewModel.kt | 3 +-- .../java/com/sampoom/android/feature/part/ui/PartViewModel.kt | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt index 921e8e3..4fa3c09 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt @@ -89,7 +89,7 @@ class OutboundListViewModel @Inject constructor( processOutboundUseCase() .onSuccess { - _uiState.update { it.copy(outboundLoading = false, isUpdating = false, isOrderSuccess = true) } + _uiState.update { it.copy(outboundLoading = false, isOrderSuccess = true) } loadOutboundList() } .onFailure { throwable -> @@ -97,7 +97,6 @@ class OutboundListViewModel @Inject constructor( _uiState.update { it.copy( outboundLoading = false, - isUpdating = false, outboundError = backendMessage ?: (throwable.message ?: errorLabel) ) } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt index b51315b..2a87763 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt @@ -71,7 +71,7 @@ class PartViewModel @Inject constructor( ) } } - Log.d(TAG, "submit: ${_uiState.value}") + Log.d(TAG, "loadCategory: ${_uiState.value}") } } @@ -110,7 +110,7 @@ class PartViewModel @Inject constructor( ) } } - Log.d(TAG, "submit: ${_uiState.value}") + Log.d(TAG, "loadGroup: ${_uiState.value}") } } From d54ad6682a0fe1a5adda09367ac7256e28b95eb2 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Mon, 20 Oct 2025 20:03:33 +0900 Subject: [PATCH 38/88] =?UTF-8?q?[FEAT]=20=EC=A3=BC=EB=AC=B8=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=ED=99=94=EB=A9=B4,=20=EC=A3=BC=EB=AC=B8=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=EC=83=81=EC=84=B8=20=ED=99=94=EB=A9=B4=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/AppNavHost.kt | 32 ++- .../android/core/ui/component/StatusChip.kt | 37 +++ .../sampoom/android/core/util/FormatDate.kt | 11 + .../sampoom/android/core/util/OrderTitle.kt | 26 ++ .../feature/order/data/mapper/OrderMappers.kt | 15 + .../feature/order/data/remote/api/OrderApi.kt | 32 +++ .../feature/order/data/remote/dto/OrderDto.kt | 31 +++ .../data/repository/OrderRepositoryImpl.kt | 43 +++ .../android/feature/order/di/OrderModules.kt | 26 ++ .../feature/order/domain/model/Order.kt | 29 ++ .../feature/order/domain/model/OrderList.kt | 11 + .../feature/order/domain/model/OrderStatus.kt | 14 + .../domain/repository/OrderRepository.kt | 11 + .../domain/usecase/CancelOrderUseCase.kt | 10 + .../domain/usecase/CreateOrderUseCase.kt | 10 + .../domain/usecase/GetOrderDetailUseCase.kt | 10 + .../order/domain/usecase/GetOrderUseCase.kt | 10 + .../domain/usecase/ReceiveOrderUseCase.kt | 10 + .../feature/order/ui/OrderDetailScreen.kt | 262 ++++++++++++++++++ .../feature/order/ui/OrderDetailUiEvent.kt | 6 + .../feature/order/ui/OrderDetailUiState.kt | 9 + .../feature/order/ui/OrderDetailViewModel.kt | 77 +++++ .../feature/order/ui/OrderListScreen.kt | 181 ++++++++++++ .../feature/order/ui/OrderListUiEvent.kt | 6 + .../feature/order/ui/OrderListUiState.kt | 9 + .../feature/order/ui/OrderListViewModel.kt | 70 +++++ .../android/feature/part/ui/PartScreen.kt | 4 +- app/src/main/res/values/strings.xml | 16 ++ 28 files changed, 999 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/core/ui/component/StatusChip.kt create mode 100644 app/src/main/java/com/sampoom/android/core/util/FormatDate.kt create mode 100644 app/src/main/java/com/sampoom/android/core/util/OrderTitle.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/data/mapper/OrderMappers.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/di/OrderModules.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/domain/model/Order.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/domain/model/OrderList.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/domain/model/OrderStatus.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CancelOrderUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CreateOrderUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderDetailUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/domain/usecase/ReceiveOrderUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiEvent.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiState.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/ui/OrderListUiEvent.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/ui/OrderListUiState.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index fdf8411..d01162e 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -23,6 +23,9 @@ import com.sampoom.android.R import com.sampoom.android.feature.auth.ui.LoginScreen import com.sampoom.android.feature.auth.ui.SignUpScreen import com.sampoom.android.feature.cart.ui.CartListScreen +import com.sampoom.android.feature.order.domain.model.OrderList +import com.sampoom.android.feature.order.ui.OrderDetailScreen +import com.sampoom.android.feature.order.ui.OrderListScreen import com.sampoom.android.feature.outbound.ui.OutboundListScreen import com.sampoom.android.feature.part.ui.PartListScreen import com.sampoom.android.feature.part.ui.PartScreen @@ -41,6 +44,8 @@ const val ROUTE_ORDERS = "orders" const val ROUTE_PARTS = "parts" const val ROUTE_PART_LIST = "parts/{agencyId}/group/{groupId}" fun routePartList(agencyId: Long, groupId: Long): String = "parts/$agencyId/group/$groupId" +const val ROUTE_ORDER_DETAIL = "orders/{agencyId}/orders/{orderId}" +fun routeOrderDetail(agencyId: Long, orderId: Long): String = "orders/$agencyId/orders/$orderId" const val ROUTE_EMPLOYEE = "employee" const val ROUTE_SETTINGS = "settings" @@ -134,7 +139,26 @@ fun MainScreen( composable(ROUTE_DASHBOARD) { DashboardScreen() } composable(ROUTE_OUTBOUND) { OutboundListScreen() } composable(ROUTE_CART) { CartListScreen() } - composable(ROUTE_ORDERS) { OrderScreen() } + composable(ROUTE_ORDERS) { + OrderListScreen( + onNavigateOrderDetail = { order -> + navController.navigate(routeOrderDetail(1, order.orderId)) + } + ) + } + composable( + ROUTE_ORDER_DETAIL, + arguments = listOf( + navArgument("agencyId") { type = NavType.LongType }, + navArgument("orderId") { type = NavType.LongType } + ) + ) { + OrderDetailScreen( + onNavigateBack = { + navController.navigateUp() + } + ) + } } } } @@ -201,10 +225,4 @@ fun BottomNavigationBar(navController: NavHostController) { private fun DashboardScreen() { // 홈 화면 구현 Text("대시보드 화면") -} - -@Composable -private fun OrderScreen() { - // 프로필 화면 구현 - Text("Order 화면") } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/StatusChip.kt b/app/src/main/java/com/sampoom/android/core/ui/component/StatusChip.kt new file mode 100644 index 0000000..47f0272 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/ui/component/StatusChip.kt @@ -0,0 +1,37 @@ +package com.sampoom.android.core.ui.component + +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.sampoom.android.R +import com.sampoom.android.core.ui.theme.FailRed +import com.sampoom.android.core.ui.theme.SuccessGreen +import com.sampoom.android.core.ui.theme.WaitYellow +import com.sampoom.android.feature.order.domain.model.OrderStatus + +@Composable +fun StatusChip(status: OrderStatus) { + val (text, color) = when (status) { + OrderStatus.PENDING -> stringResource(R.string.order_status_pending) to WaitYellow + OrderStatus.COMPLETED -> stringResource(R.string.order_status_completed) to SuccessGreen + OrderStatus.CANCELED -> stringResource(R.string.order_status_canceled) to FailRed + } + + Surface( + shape = RoundedCornerShape(16.dp), + color = color.copy(alpha = 0.2F) + ) { + Text( + text = text, + modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp), + style = MaterialTheme.typography.bodySmall, + color = color + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt b/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt new file mode 100644 index 0000000..8fc7deb --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.core.util + +fun formatDate(dateString: String): String { + return try { + val inFmt = java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS", java.util.Locale.getDefault()) + val outFmt = java.text.SimpleDateFormat("yyyy-MM-dd", java.util.Locale.getDefault()) + outFmt.format(inFmt.parse(dateString) ?: java.util.Date()) + } catch (_: Exception) { + dateString + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/util/OrderTitle.kt b/app/src/main/java/com/sampoom/android/core/util/OrderTitle.kt new file mode 100644 index 0000000..d027df7 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/util/OrderTitle.kt @@ -0,0 +1,26 @@ +package com.sampoom.android.core.util + +import com.sampoom.android.feature.order.domain.model.Order +import com.sampoom.android.feature.order.domain.model.OrderPart + +fun buildOrderTitle(order: Order): String { + val flattened: List> = + order.items.flatMap { category -> + category.groups.flatMap { group -> + group.parts.map { part -> Triple(category.categoryName, group.groupName, part) } + } + } + + if (flattened.isEmpty()) return "-" + + val first = flattened.first() + val groupName = first.second + val part = first.third + val totalParts = flattened.size + + return if (totalParts == 1) { + "$groupName - ${part.name} ${part.quantity}EA" + } else { + "${part.name} - $groupName ${part.quantity}EA 외 ${totalParts - 1}건" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/mapper/OrderMappers.kt b/app/src/main/java/com/sampoom/android/feature/order/data/mapper/OrderMappers.kt new file mode 100644 index 0000000..fd25e78 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/data/mapper/OrderMappers.kt @@ -0,0 +1,15 @@ +package com.sampoom.android.feature.order.data.mapper + +import com.sampoom.android.feature.order.data.remote.dto.OrderCategoryDto +import com.sampoom.android.feature.order.data.remote.dto.OrderDto +import com.sampoom.android.feature.order.data.remote.dto.OrderGroupDto +import com.sampoom.android.feature.order.data.remote.dto.OrderPartDto +import com.sampoom.android.feature.order.domain.model.Order +import com.sampoom.android.feature.order.domain.model.OrderCategory +import com.sampoom.android.feature.order.domain.model.OrderGroup +import com.sampoom.android.feature.order.domain.model.OrderPart + +fun OrderDto.toModel(): Order = Order(orderId, orderNumber, createdAt, status, agencyName, items.map { it.toModel() }) +fun OrderCategoryDto.toModel(): OrderCategory = OrderCategory(categoryId, categoryName, groups.map { it.toModel() }) +fun OrderGroupDto.toModel(): OrderGroup = OrderGroup(groupId, groupName, parts.map { it.toModel() }) +fun OrderPartDto.toModel(): OrderPart = OrderPart(partId, code, name, quantity) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt b/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt new file mode 100644 index 0000000..d8fc9fc --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt @@ -0,0 +1,32 @@ +package com.sampoom.android.feature.order.data.remote.api + +import com.sampoom.android.core.network.ApiResponse +import com.sampoom.android.core.network.ApiSuccessResponse +import com.sampoom.android.feature.order.data.remote.dto.OrderDto +import retrofit2.http.DELETE +import retrofit2.http.GET +import retrofit2.http.PATCH +import retrofit2.http.POST +import retrofit2.http.Path + +interface OrderApi { + // 주문 목록 조회 + @GET("agency/1/orders") + suspend fun getOrderList(): ApiResponse> + + // 주문 생성 + @POST("agency/1/orders") + suspend fun createOrder(): ApiResponse> + + // 주문 입고 처리 + @PATCH("agency/1/orders/{orderId}/receive") + suspend fun receiveOrder(@Path("orderId") orderId: Long): ApiSuccessResponse + + // 주문 상세 조회 + @GET("agency/1/orders/{orderId}") + suspend fun getOrderDetail(@Path("orderId") orderId: Long): ApiResponse> + + // 주문 취소 + @DELETE("agency/1/orders/{orderId}") + suspend fun cancelOrder(@Path("orderId") orderId: Long): ApiSuccessResponse +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderDto.kt b/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderDto.kt new file mode 100644 index 0000000..50a9129 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderDto.kt @@ -0,0 +1,31 @@ +package com.sampoom.android.feature.order.data.remote.dto + +import com.sampoom.android.feature.order.domain.model.OrderStatus + +data class OrderDto( + val orderId: Long, + val orderNumber: String?, + val createdAt: String?, + val status: OrderStatus, + val agencyName: String?, + val items: List +) + +data class OrderCategoryDto( + val categoryId: Long, + val categoryName: String, + val groups: List +) + +data class OrderGroupDto( + val groupId: Long, + val groupName: String, + val parts: List +) + +data class OrderPartDto( + val partId: Long, + val code: String, + val name: String, + val quantity: Long +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt new file mode 100644 index 0000000..065eeca --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt @@ -0,0 +1,43 @@ +package com.sampoom.android.feature.order.data.repository + +import com.sampoom.android.feature.order.data.mapper.toModel +import com.sampoom.android.feature.order.data.remote.api.OrderApi +import com.sampoom.android.feature.order.domain.model.OrderList +import com.sampoom.android.feature.order.domain.repository.OrderRepository +import javax.inject.Inject + +class OrderRepositoryImpl @Inject constructor( + private val api: OrderApi +) : OrderRepository { + override suspend fun getOrderList(): OrderList { + val dto = api.getOrderList() + val orderItems = dto.data.map { it.toModel() } + return OrderList(items = orderItems) + } + + override suspend fun createOrder(): OrderList { + val dto = api.createOrder() + val orderItems = dto.data.map { it.toModel() } + return OrderList(items = orderItems) + } + + override suspend fun receiveOrder(orderId: Long): Result { + val dto = api.receiveOrder(orderId) + return runCatching { + if (!dto.success) throw Exception(dto.message) + } + } + + override suspend fun getOrderDetail(orderId: Long): OrderList { + val dto = api.getOrderDetail(orderId) + val orderItems = dto.data.map { it.toModel() } + return OrderList(items = orderItems) + } + + override suspend fun cancelOrder(orderId: Long): Result { + val dto = api.cancelOrder(orderId) + return runCatching { + if (!dto.success) throw Exception(dto.message) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/di/OrderModules.kt b/app/src/main/java/com/sampoom/android/feature/order/di/OrderModules.kt new file mode 100644 index 0000000..fe342bf --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/di/OrderModules.kt @@ -0,0 +1,26 @@ +package com.sampoom.android.feature.order.di + +import com.sampoom.android.feature.order.data.remote.api.OrderApi +import com.sampoom.android.feature.order.data.repository.OrderRepositoryImpl +import com.sampoom.android.feature.order.domain.repository.OrderRepository +import dagger.Binds +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import jakarta.inject.Singleton +import retrofit2.Retrofit + +@Module +@InstallIn(SingletonComponent::class) +abstract class OrderBindModule { + @Binds @Singleton + abstract fun bindOrderRepository(impl: OrderRepositoryImpl): OrderRepository +} + +@Module +@InstallIn(SingletonComponent::class) +object OrderModule { + @Provides @Singleton + fun provideOrderApi(retrofit: Retrofit): OrderApi = retrofit.create(OrderApi::class.java) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/model/Order.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/model/Order.kt new file mode 100644 index 0000000..90da7f8 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/model/Order.kt @@ -0,0 +1,29 @@ +package com.sampoom.android.feature.order.domain.model + +data class Order( + val orderId: Long, + val orderNumber: String?, + val createdAt: String?, + val status: OrderStatus, + val agencyName: String?, + val items: List +) + +data class OrderCategory( + val categoryId: Long, + val categoryName: String, + val groups: List +) + +data class OrderGroup( + val groupId: Long, + val groupName: String, + val parts: List +) + +data class OrderPart( + val partId: Long, + val code: String, + val name: String, + val quantity: Long +) diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/model/OrderList.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/model/OrderList.kt new file mode 100644 index 0000000..94d1431 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/model/OrderList.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.order.domain.model + +data class OrderList( + val items: List, + val totalCount: Int = items.size, + val isEmpty: Boolean = items.isEmpty() +) { + companion object Companion { + fun empty() = OrderList(emptyList()) + } +} diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/model/OrderStatus.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/model/OrderStatus.kt new file mode 100644 index 0000000..4e31967 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/model/OrderStatus.kt @@ -0,0 +1,14 @@ +package com.sampoom.android.feature.order.domain.model + +enum class OrderStatus { + PENDING, COMPLETED, CANCELED; + + companion object { + fun from(raw: String?): OrderStatus = when (raw?.uppercase()) { + "PENDING" -> PENDING + "COMPLETED" -> COMPLETED + "CANCELED" -> CANCELED + else -> PENDING + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt new file mode 100644 index 0000000..871b70a --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.order.domain.repository + +import com.sampoom.android.feature.order.domain.model.OrderList + +interface OrderRepository { + suspend fun getOrderList(): OrderList + suspend fun createOrder(): OrderList + suspend fun receiveOrder(orderId: Long): Result + suspend fun getOrderDetail(orderId: Long): OrderList + suspend fun cancelOrder(orderId: Long): Result +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CancelOrderUseCase.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CancelOrderUseCase.kt new file mode 100644 index 0000000..e3e8f86 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CancelOrderUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.order.domain.usecase + +import com.sampoom.android.feature.order.domain.repository.OrderRepository +import javax.inject.Inject + +class CancelOrderUseCase @Inject constructor( + private val repository: OrderRepository +){ + suspend operator fun invoke(orderId: Long) = repository.cancelOrder(orderId) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CreateOrderUseCase.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CreateOrderUseCase.kt new file mode 100644 index 0000000..c26aafe --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CreateOrderUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.order.domain.usecase + +import com.sampoom.android.feature.order.domain.repository.OrderRepository +import javax.inject.Inject + +class CreateOrderUseCase @Inject constructor( + private val repository: OrderRepository +){ + suspend operator fun invoke() = repository.createOrder() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderDetailUseCase.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderDetailUseCase.kt new file mode 100644 index 0000000..1898e1b --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderDetailUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.order.domain.usecase + +import com.sampoom.android.feature.order.domain.repository.OrderRepository +import javax.inject.Inject + +class GetOrderDetailUseCase @Inject constructor( + private val repository: OrderRepository +) { + suspend operator fun invoke(orderId: Long) = repository.getOrderDetail(orderId) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderUseCase.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderUseCase.kt new file mode 100644 index 0000000..ad20ec3 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.order.domain.usecase + +import com.sampoom.android.feature.order.domain.repository.OrderRepository +import javax.inject.Inject + +class GetOrderUseCase @Inject constructor( + private val repository: OrderRepository +){ + suspend operator fun invoke() = repository.getOrderList() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/ReceiveOrderUseCase.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/ReceiveOrderUseCase.kt new file mode 100644 index 0000000..76ce9b1 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/ReceiveOrderUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.order.domain.usecase + +import com.sampoom.android.feature.order.domain.repository.OrderRepository +import javax.inject.Inject + +class ReceiveOrderUseCase @Inject constructor( + private val repository: OrderRepository +) { + suspend operator fun invoke(orderId: Long) = repository.receiveOrder(orderId) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt new file mode 100644 index 0000000..8c8e5ba --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt @@ -0,0 +1,262 @@ +package com.sampoom.android.feature.order.ui + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.sampoom.android.R +import com.sampoom.android.core.ui.component.EmptyContent +import com.sampoom.android.core.ui.component.ErrorContent +import com.sampoom.android.core.ui.component.StatusChip +import com.sampoom.android.core.ui.theme.FailRed +import com.sampoom.android.core.ui.theme.SuccessGreen +import com.sampoom.android.core.ui.theme.WaitYellow +import com.sampoom.android.core.ui.theme.backgroundCardColor +import com.sampoom.android.core.ui.theme.textColor +import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.feature.order.domain.model.Order +import com.sampoom.android.feature.order.domain.model.OrderPart +import com.sampoom.android.feature.order.domain.model.OrderStatus + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun OrderDetailScreen( + onNavigateBack: () -> Unit = {}, + viewModel: OrderDetailViewModel = hiltViewModel() +) { + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + + Column(Modifier.fillMaxSize()) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 4.dp), + horizontalArrangement = Arrangement.Start, + verticalAlignment = Alignment.CenterVertically + ) { + IconButton(onClick = onNavigateBack) { + Icon( + painter = painterResource(R.drawable.ic_arrow_back), + contentDescription = stringResource(R.string.nav_back) + ) + } + Text( + modifier = Modifier + .padding(vertical = 16.dp), + text = stringResource(R.string.order_detail_title), + style = MaterialTheme.typography.titleLarge, + color = textColor() + ) + } + + when { + uiState.orderDetailLoading -> { + Box( + modifier = Modifier + .fillMaxWidth() + .height(200.dp), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + + uiState.orderDetailError != null -> { + ErrorContent( + onRetry = { viewModel.onEvent(OrderDetailUiEvent.RetryOrder) }, + modifier = Modifier.height(200.dp).fillMaxWidth() + ) + } + + uiState.orderDetail.isEmpty() -> { + EmptyContent( + message = stringResource(R.string.order_empty_list), + modifier = Modifier.height(200.dp).fillMaxWidth() + ) + } + + else -> { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + uiState.orderDetail.forEach { order -> + item { + OrderInfoCard(order = order) + } + item { + Text( + text = stringResource(R.string.order_detail_order_items_title), + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold, + color = textColor() + ) + } + order.items.forEach { category -> + category.groups.forEach { group -> + item { + OrderSection( + categoryName = category.categoryName, + groupName = group.groupName, + parts = group.parts + ) + } + } + } + } + } + } + } + } +} + +@Composable +private fun OrderInfoCard(order: Order) { + Card( + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors(containerColor = backgroundCardColor()) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { + OrderInfoRow( + label = stringResource(R.string.order_detail_order_number), + value = order.orderNumber ?: stringResource(R.string.common_slash) + ) + OrderInfoRow( + label = stringResource(R.string.order_detail_order_date), + value = order.createdAt ?: stringResource(R.string.common_slash) + ) + OrderInfoRow( + label = stringResource(R.string.order_detail_order_agency), + value = order.agencyName ?: stringResource(R.string.common_slash) + ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = stringResource(R.string.order_detail_order_status), + style = MaterialTheme.typography.bodyMedium, + color = textSecondaryColor() + ) + + StatusChip(status = order.status) + } + } + } +} + +@Composable +private fun OrderInfoRow( + label: String, + value: String +) { + Row( + modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = label, + style = MaterialTheme.typography.bodyMedium, + color = textSecondaryColor() + ) + Text( + text = value, + style = MaterialTheme.typography.bodyMedium, + color = textColor() + ) + } +} + +@Composable +private fun OrderSection( + categoryName: String, + groupName: String, + parts: List +) { + Column( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + text = "$categoryName > $groupName", + style = MaterialTheme.typography.titleMedium, + color = textColor() + ) + + parts.forEach { part -> + OrderPartItem(part = part) + } + } +} + +@Composable +private fun OrderPartItem( + part: OrderPart +) { + Card( + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors(containerColor = backgroundCardColor()) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier.weight(1F) + ) { + Text( + text = part.name, + style = MaterialTheme.typography.titleMedium, + color = textColor() + ) + Text( + text = part.code, + style = MaterialTheme.typography.bodySmall, + color = textSecondaryColor() + ) + } + + Text( + text = part.quantity.toString(), + style = MaterialTheme.typography.titleMedium, + color = textColor() + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiEvent.kt new file mode 100644 index 0000000..2caa7c4 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiEvent.kt @@ -0,0 +1,6 @@ +package com.sampoom.android.feature.order.ui + +sealed interface OrderDetailUiEvent { + object LoadOrder : OrderDetailUiEvent + object RetryOrder : OrderDetailUiEvent +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiState.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiState.kt new file mode 100644 index 0000000..6fdbede --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiState.kt @@ -0,0 +1,9 @@ +package com.sampoom.android.feature.order.ui + +import com.sampoom.android.feature.order.domain.model.Order + +data class OrderDetailUiState( + val orderDetail: List = emptyList(), + val orderDetailLoading: Boolean = false, + val orderDetailError: String? = null +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt new file mode 100644 index 0000000..e604071 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt @@ -0,0 +1,77 @@ +package com.sampoom.android.feature.order.ui + +import android.util.Log +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.feature.order.domain.usecase.GetOrderDetailUseCase +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class OrderDetailViewModel @Inject constructor( + private val getOrderDetailUseCase: GetOrderDetailUseCase, + savedStateHandle: SavedStateHandle +) : ViewModel() { + + private companion object { + private const val TAG = "OrderDetailViewModel" + } + + private val _uiState = MutableStateFlow(OrderDetailUiState()) + val uiState: StateFlow = _uiState + + // Navigation 인자 로드 + private val agencyId: Long = savedStateHandle.get("agencyId") ?: 0L + private val orderId: Long = savedStateHandle.get("orderId") ?: 0L + + private var errorLabel: String = "" + + fun bindLabel(error: String) { + errorLabel = error + } + + init { + if (orderId > 0L) loadOrderDetail(orderId) + else _uiState.update { it.copy(orderDetailError = errorLabel) } + } + + fun onEvent(event: OrderDetailUiEvent) { + when (event) { + is OrderDetailUiEvent.LoadOrder -> loadOrderDetail(orderId) + is OrderDetailUiEvent.RetryOrder -> loadOrderDetail(orderId) + } + } + + private fun loadOrderDetail(orderId: Long) { + viewModelScope.launch { + _uiState.update { it.copy(orderDetailLoading = true, orderDetailError = null) } + + runCatching { getOrderDetailUseCase(orderId) } + .onSuccess { orderList -> + _uiState.update { + it.copy( + orderDetail = orderList.items, + orderDetailLoading = false, + orderDetailError = null + ) + } + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + orderDetailLoading = false, + orderDetailError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + } + Log.d(TAG, "submit: ${_uiState.value}") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt new file mode 100644 index 0000000..8e4d528 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt @@ -0,0 +1,181 @@ +package com.sampoom.android.feature.order.ui + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.sampoom.android.R +import com.sampoom.android.core.ui.component.EmptyContent +import com.sampoom.android.core.ui.component.ErrorContent +import com.sampoom.android.core.ui.component.StatusChip +import com.sampoom.android.core.ui.theme.backgroundCardColor +import com.sampoom.android.core.ui.theme.textColor +import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.core.util.buildOrderTitle +import com.sampoom.android.core.util.formatDate +import com.sampoom.android.feature.order.domain.model.Order +import com.sampoom.android.feature.order.domain.model.OrderPart + +@Composable +fun OrderListScreen( + onNavigateOrderDetail: (Order) -> Unit, + viewModel: OrderListViewModel = hiltViewModel() +) { + val errorLabel = stringResource(R.string.common_error) + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + val listState = rememberSaveable(saver = LazyListState.Saver) { LazyListState() } + + LaunchedEffect(errorLabel) { + viewModel.bindLabel(errorLabel) + viewModel.onEvent(OrderListUiEvent.LoadOrderList) + } + + Column(Modifier.fillMaxSize()) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + modifier = Modifier + .padding(vertical = 16.dp), + text = stringResource(R.string.order_title), + style = MaterialTheme.typography.titleLarge, + color = textColor() + ) + } + + when { + uiState.orderLoading -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + + uiState.orderError != null -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + ErrorContent( + onRetry = { viewModel.onEvent(OrderListUiEvent.RetryOrderList) }, + modifier = Modifier.height(200.dp) + ) + } + } + + uiState.orderList.isEmpty() -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + EmptyContent( + message = stringResource(R.string.order_empty_list), + modifier = Modifier.height(200.dp) + ) + } + } + + else -> { + LazyColumn( + state = listState, + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + uiState.orderList.forEach { order -> + item { + OrderItem( + order = order, + onClick = { onNavigateOrderDetail(order) } + ) + } + } + item { Spacer(Modifier.height(100.dp)) } + } + } + } + } +} + +@Composable +private fun OrderItem( + order: Order, + onClick: () -> Unit +) { + Card( + onClick = { onClick() }, + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors(containerColor = backgroundCardColor()) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier + .weight(1f) + ) { + Text( + text = buildOrderTitle(order), + style = MaterialTheme.typography.bodyMedium, + maxLines = 1 + ) + Spacer(Modifier.height(4.dp)) + Text( + text = order.agencyName ?: stringResource(R.string.common_slash), + style = MaterialTheme.typography.labelMedium, + color = textSecondaryColor() + ) + } + + Spacer(Modifier.width(12.dp)) + + Column(horizontalAlignment = Alignment.End) { + Text( + text = order.createdAt?.let { formatDate(it) } ?: stringResource(R.string.common_slash), + style = MaterialTheme.typography.labelMedium, + color = textSecondaryColor() + ) + Spacer(Modifier.height(6.dp)) + StatusChip(status = order.status) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListUiEvent.kt new file mode 100644 index 0000000..dfb3e8c --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListUiEvent.kt @@ -0,0 +1,6 @@ +package com.sampoom.android.feature.order.ui + +sealed interface OrderListUiEvent { + object LoadOrderList : OrderListUiEvent + object RetryOrderList : OrderListUiEvent +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListUiState.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListUiState.kt new file mode 100644 index 0000000..8e7e25b --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListUiState.kt @@ -0,0 +1,9 @@ +package com.sampoom.android.feature.order.ui + +import com.sampoom.android.feature.order.domain.model.Order + +data class OrderListUiState( + val orderList: List = emptyList(), + val orderLoading: Boolean = false, + val orderError: String? = null +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt new file mode 100644 index 0000000..a5fcf74 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt @@ -0,0 +1,70 @@ +package com.sampoom.android.feature.order.ui + +import android.util.Log +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.feature.order.domain.usecase.GetOrderUseCase +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class OrderListViewModel @Inject constructor( + private val getOrderListUseCase: GetOrderUseCase +) : ViewModel() { + + private companion object { + private const val TAG = "OrderListViewModel" + } + + private val _uiState = MutableStateFlow(OrderListUiState()) + val uiState: StateFlow = _uiState + + private var errorLabel: String = "" + + fun bindLabel(error: String) { + errorLabel = error + } + + init { + loadOrderList() + } + + fun onEvent(event: OrderListUiEvent) { + when (event) { + is OrderListUiEvent.LoadOrderList -> loadOrderList() + is OrderListUiEvent.RetryOrderList -> loadOrderList() + } + } + + private fun loadOrderList() { + viewModelScope.launch { + _uiState.update { it.copy(orderLoading = true, orderError = null) } + + runCatching { getOrderListUseCase() } + .onSuccess { orderList -> + _uiState.update { + it.copy( + orderList = orderList.items, + orderLoading = false, + orderError = null + ) + } + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + orderLoading = false, + orderError = backendMessage ?: (throwable.message ?: errorLabel ) + ) + } + } + Log.d(TAG, "submit: ${_uiState.value}") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index 97ae617..3585da3 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -116,14 +116,14 @@ fun PartScreen( uiState.categoryError != null -> { ErrorContent( onRetry = { viewModel.onEvent(PartUiEvent.RetryCategories) }, - modifier = Modifier.height(200.dp) + modifier = Modifier.height(200.dp).fillMaxWidth() ) } uiState.categoryList.isEmpty() -> { EmptyContent( message = stringResource(R.string.part_empty_category), - modifier = Modifier.height(200.dp) + modifier = Modifier.height(200.dp).fillMaxWidth() ) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7faede2..52953bd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -78,6 +78,21 @@ 추가되었습니다 부품 주문 + + 주문관리 + 주문관리 목록이 없습니다. + 주문정보 + 주문번호 + 주문일자 + 대리점 + 주문상태 + 주문상품 + + + 승인대기 + 배송완료 + 주문실패 + 오류가 발생했습니다 다시 시도 @@ -87,6 +102,7 @@ 삭제 상세 보기 EA + - 이메일을 입력해주세요 From 2d38e1fb03813471023860a4e1fa9b289d029064 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Mon, 20 Oct 2025 20:19:10 +0900 Subject: [PATCH 39/88] =?UTF-8?q?[FIX]=20Navigation=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/AppNavHost.kt | 28 +++++++-------- .../feature/order/ui/OrderDetailScreen.kt | 35 ++++++++----------- 2 files changed, 28 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index d01162e..4531182 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -118,6 +118,19 @@ fun AppNavHost() { } ) } + composable( + ROUTE_ORDER_DETAIL, + arguments = listOf( + navArgument("agencyId") { type = NavType.LongType }, + navArgument("orderId") { type = NavType.LongType } + ) + ) { + OrderDetailScreen( + onNavigateBack = { + navController.navigateUp() + } + ) + } } } @@ -142,20 +155,7 @@ fun MainScreen( composable(ROUTE_ORDERS) { OrderListScreen( onNavigateOrderDetail = { order -> - navController.navigate(routeOrderDetail(1, order.orderId)) - } - ) - } - composable( - ROUTE_ORDER_DETAIL, - arguments = listOf( - navArgument("agencyId") { type = NavType.LongType }, - navArgument("orderId") { type = NavType.LongType } - ) - ) { - OrderDetailScreen( - onNavigateBack = { - navController.navigateUp() + parentNavController.navigate(routeOrderDetail(1, order.orderId)) } ) } diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt index 8c8e5ba..7c0606d 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt @@ -53,29 +53,21 @@ fun OrderDetailScreen( ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() - Column(Modifier.fillMaxSize()) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 4.dp), - horizontalArrangement = Arrangement.Start, - verticalAlignment = Alignment.CenterVertically - ) { - IconButton(onClick = onNavigateBack) { - Icon( - painter = painterResource(R.drawable.ic_arrow_back), - contentDescription = stringResource(R.string.nav_back) - ) - } - Text( - modifier = Modifier - .padding(vertical = 16.dp), - text = stringResource(R.string.order_detail_title), - style = MaterialTheme.typography.titleLarge, - color = textColor() + Scaffold( + topBar = { + TopAppBar( + title = { Text(stringResource(R.string.order_detail_title)) }, + navigationIcon = { + IconButton(onClick = onNavigateBack) { + Icon( + painter = painterResource(R.drawable.ic_arrow_back), + contentDescription = stringResource(R.string.nav_back) + ) + } + } ) } - + ) { innerPadding -> when { uiState.orderDetailLoading -> { Box( @@ -106,6 +98,7 @@ fun OrderDetailScreen( LazyColumn( modifier = Modifier .fillMaxSize() + .padding(innerPadding) .padding(horizontal = 16.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { From f3c63992bc0394cea2f32f82fd3f9c7a3c2d9f20 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Tue, 21 Oct 2025 11:04:20 +0900 Subject: [PATCH 40/88] =?UTF-8?q?[FEAT]=20=EC=A3=BC=EB=AC=B8=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B5=AC=ED=98=84,=20=EC=A3=BC=EB=AC=B8=20?= =?UTF-8?q?=EC=B7=A8=EC=86=8C,=20=EC=9E=85=EA=B3=A0=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/core/network/ErrorHandling.kt | 2 + .../data/repository/CartRepositoryImpl.kt | 8 +- .../android/feature/cart/ui/CartListScreen.kt | 20 +- .../feature/cart/ui/CartListUiEvent.kt | 1 + .../feature/cart/ui/CartListUiState.kt | 5 +- .../feature/cart/ui/CartListViewModel.kt | 43 ++- .../data/repository/OrderRepositoryImpl.kt | 4 +- .../feature/order/ui/OrderDetailContent.kt | 188 ++++++++++++ .../feature/order/ui/OrderDetailScreen.kt | 274 +++++++----------- .../feature/order/ui/OrderDetailUiEvent.kt | 3 + .../feature/order/ui/OrderDetailUiState.kt | 6 +- .../feature/order/ui/OrderDetailViewModel.kt | 83 +++++- .../order/ui/OrderResultBottomSheet.kt | 168 +++++++++++ .../data/repository/OutboundRepositoryImpl.kt | 10 +- app/src/main/res/drawable/ic_check_circle.xml | 5 + app/src/main/res/values/strings.xml | 10 +- 16 files changed, 608 insertions(+), 222 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailContent.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt create mode 100644 app/src/main/res/drawable/ic_check_circle.xml diff --git a/app/src/main/java/com/sampoom/android/core/network/ErrorHandling.kt b/app/src/main/java/com/sampoom/android/core/network/ErrorHandling.kt index 23d3ae5..e0a43ca 100644 --- a/app/src/main/java/com/sampoom/android/core/network/ErrorHandling.kt +++ b/app/src/main/java/com/sampoom/android/core/network/ErrorHandling.kt @@ -1,5 +1,6 @@ package com.sampoom.android.core.network +import android.util.Log import com.google.gson.Gson import com.google.gson.JsonSyntaxException import retrofit2.HttpException @@ -12,6 +13,7 @@ data class ApiErrorResponse( fun Throwable.serverMessageOrNull(): String? { if (this is HttpException) { val errorBody = response()?.errorBody()?.string() ?: return null + Log.d("ErrorHandling", "Error body: $errorBody") return try { Gson().fromJson(errorBody, ApiErrorResponse::class.java).message } catch (_: JsonSyntaxException) { diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt index 70021a1..87cf282 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt @@ -21,22 +21,22 @@ class CartRepositoryImpl @Inject constructor( partId: Long, quantity: Long ): Result { - val dto = api.addCart(AddCartRequestDto(partId, quantity)) return runCatching { + val dto = api.addCart(AddCartRequestDto(partId, quantity)) if (!dto.success) throw Exception(dto.message) } } override suspend fun deleteCart(cartItemId: Long): Result { - val dto = api.deleteCart(cartItemId) return runCatching { + val dto = api.deleteCart(cartItemId) if (!dto.success) throw Exception(dto.message) } } override suspend fun deleteAllCart(): Result { - val dto = api.deleteAllCart() return runCatching { + val dto = api.deleteAllCart() if (!dto.success) throw Exception(dto.message) } } @@ -45,8 +45,8 @@ class CartRepositoryImpl @Inject constructor( cartItemId: Long, quantity: Long ): Result { - val dto = api.updateCart(cartItemId, UpdateCartRequestDto(quantity)) return runCatching { + val dto = api.updateCart(cartItemId, UpdateCartRequestDto(quantity)) if (!dto.success) throw Exception(dto.message) } } diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt index b48d196..5c6ad52 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt @@ -45,6 +45,7 @@ import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.cart.domain.model.CartPart +import com.sampoom.android.feature.order.ui.OrderResultBottomSheet import kotlin.collections.forEach @Composable @@ -55,26 +56,17 @@ fun CartListScreen( val uiState by viewModel.uiState.collectAsStateWithLifecycle() var showEmptyCartDialog by remember { mutableStateOf(false) } var showConfirmDialog by remember { mutableStateOf(false) } - val context = LocalContext.current - - LaunchedEffect(Unit) { - viewModel.clearSuccess() - } LaunchedEffect(errorLabel) { viewModel.bindLabel(errorLabel) viewModel.onEvent(CartListUiEvent.LoadCartList) } - LaunchedEffect(uiState.isOrderSuccess) { - if (uiState.isOrderSuccess) { - Toast.makeText( - context, - context.getString(R.string.cart_toast_order_text), - Toast.LENGTH_SHORT - ).show() - } - viewModel.clearSuccess() + uiState.processedOrder?.let { orders -> + OrderResultBottomSheet( + order = orders, + onDismiss = { viewModel.onEvent(CartListUiEvent.DismissOrderResult)} + ) } Column(Modifier.fillMaxSize()) { diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiEvent.kt index f96cb48..15682c9 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiEvent.kt @@ -9,4 +9,5 @@ sealed interface CartListUiEvent { object DeleteAllCart : CartListUiEvent object ClearUpdateError : CartListUiEvent object ClearDeleteError : CartListUiEvent + object DismissOrderResult : CartListUiEvent } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt index d6ae356..d005b17 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt @@ -1,6 +1,7 @@ package com.sampoom.android.feature.cart.ui import com.sampoom.android.feature.cart.domain.model.Cart +import com.sampoom.android.feature.order.domain.model.Order data class CartListUiState( val cartList: List = emptyList(), @@ -11,5 +12,7 @@ data class CartListUiState( val updateError: String? = null, val isDeleting: Boolean = false, val deleteError: String? = null, - val isOrderSuccess: Boolean = false + val isProcessing: Boolean = false, + val processError: String? = null, + val processedOrder: List? = null ) diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt index 1be0d4f..4f6d7a1 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt @@ -1,5 +1,6 @@ package com.sampoom.android.feature.cart.ui +import android.R.attr.order import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -8,6 +9,7 @@ import com.sampoom.android.feature.cart.domain.usecase.DeleteAllCartUseCase import com.sampoom.android.feature.cart.domain.usecase.DeleteCartUseCase import com.sampoom.android.feature.cart.domain.usecase.GetCartUseCase import com.sampoom.android.feature.cart.domain.usecase.UpdateCartQuantityUseCase +import com.sampoom.android.feature.order.domain.usecase.CreateOrderUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -20,7 +22,8 @@ class CartListViewModel @Inject constructor( private val getCartListUseCase: GetCartUseCase, private val updateCartQuantityUseCase: UpdateCartQuantityUseCase, private val deleteCartUseCase: DeleteCartUseCase, - private val deleteAllCartUseCase: DeleteAllCartUseCase + private val deleteAllCartUseCase: DeleteAllCartUseCase, + private val createOrderUseCase: CreateOrderUseCase ) : ViewModel() { private companion object { @@ -50,6 +53,7 @@ class CartListViewModel @Inject constructor( is CartListUiEvent.DeleteAllCart -> deleteAllCart() is CartListUiEvent.ClearUpdateError -> _uiState.update { it.copy(updateError = null) } is CartListUiEvent.ClearDeleteError -> _uiState.update { it.copy(deleteError = null) } + is CartListUiEvent.DismissOrderResult -> _uiState.update { it.copy(processedOrder = null) } } } @@ -81,25 +85,24 @@ class CartListViewModel @Inject constructor( } } - // TODO() : 주문 생성 로직 private fun processOrder() { viewModelScope.launch { -// _uiState.update { it.copy(cartLoading = true, cartError = null) } -// -// processCartUseCase() -// .onSuccess { -// _uiState.update { it.copy(isUpdating = false, isOrderSuccess = true) } -// loadCartList() -// } -// .onFailure { throwable -> -// val backendMessage = throwable.serverMessageOrNull() -// _uiState.update { -// it.copy( -// isUpdating = false, -// updateError = backendMessage ?: (throwable.message ?: errorLabel) -// ) -// } -// } + _uiState.update { it.copy(isProcessing = true, processError = null) } + + runCatching { createOrderUseCase() } + .onSuccess { orderList -> + _uiState.update { it.copy(isProcessing = false, processedOrder = orderList.items) } + loadCartList() + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + isProcessing = false, + processError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + } Log.d(TAG, "submit: ${_uiState.value}") } } @@ -217,8 +220,4 @@ class CartListViewModel @Inject constructor( currentState.copy(cartList = emptyList()) } } - - fun clearSuccess() { - _uiState.update { it.copy(isOrderSuccess = false) } - } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt index 065eeca..16a74e1 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt @@ -22,8 +22,8 @@ class OrderRepositoryImpl @Inject constructor( } override suspend fun receiveOrder(orderId: Long): Result { - val dto = api.receiveOrder(orderId) return runCatching { + val dto = api.receiveOrder(orderId) if (!dto.success) throw Exception(dto.message) } } @@ -35,8 +35,8 @@ class OrderRepositoryImpl @Inject constructor( } override suspend fun cancelOrder(orderId: Long): Result { - val dto = api.cancelOrder(orderId) return runCatching { + val dto = api.cancelOrder(orderId) if (!dto.success) throw Exception(dto.message) } } diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailContent.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailContent.kt new file mode 100644 index 0000000..f30e900 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailContent.kt @@ -0,0 +1,188 @@ +package com.sampoom.android.feature.order.ui + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import com.sampoom.android.R +import com.sampoom.android.core.ui.component.StatusChip +import com.sampoom.android.core.ui.theme.backgroundCardColor +import com.sampoom.android.core.ui.theme.textColor +import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.feature.order.domain.model.Order +import com.sampoom.android.feature.order.domain.model.OrderPart +import kotlin.collections.forEach + +@Composable +fun OrderDetailContent( + order: List, + modifier: Modifier = Modifier +) { + LazyColumn( + modifier = modifier + .fillMaxSize() + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + order.forEach { order -> + item { + OrderInfoCard(order = order) + } + item { + Text( + text = stringResource(R.string.order_detail_order_items_title), + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold, + color = textColor() + ) + } + order.items.forEach { category -> + category.groups.forEach { group -> + item { + OrderSection( + categoryName = category.categoryName, + groupName = group.groupName, + parts = group.parts + ) + } + } + } + } + } +} + + +@Composable +private fun OrderInfoCard(order: Order) { + Card( + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors(containerColor = backgroundCardColor()) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { + OrderInfoRow( + label = stringResource(R.string.order_detail_order_number), + value = order.orderNumber ?: stringResource(R.string.common_slash) + ) + OrderInfoRow( + label = stringResource(R.string.order_detail_order_date), + value = order.createdAt ?: stringResource(R.string.common_slash) + ) + OrderInfoRow( + label = stringResource(R.string.order_detail_order_agency), + value = order.agencyName ?: stringResource(R.string.common_slash) + ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = stringResource(R.string.order_detail_order_status), + style = MaterialTheme.typography.bodyMedium, + color = textSecondaryColor() + ) + + StatusChip(status = order.status) + } + } + } +} + +@Composable +private fun OrderInfoRow( + label: String, + value: String +) { + Row( + modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = label, + style = MaterialTheme.typography.bodyMedium, + color = textSecondaryColor() + ) + Text( + text = value, + style = MaterialTheme.typography.bodyMedium, + color = textColor() + ) + } +} + +@Composable +private fun OrderSection( + categoryName: String, + groupName: String, + parts: List +) { + Column( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + text = "$categoryName > $groupName", + style = MaterialTheme.typography.titleMedium, + color = textColor() + ) + + parts.forEach { part -> + OrderPartItem(part = part) + } + } +} + +@Composable +private fun OrderPartItem( + part: OrderPart +) { + Card( + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors(containerColor = backgroundCardColor()) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier.weight(1F) + ) { + Text( + text = part.name, + style = MaterialTheme.typography.titleMedium, + color = textColor() + ) + Text( + text = part.code, + style = MaterialTheme.typography.bodySmall, + color = textSecondaryColor() + ) + } + + Text( + text = part.quantity.toString(), + style = MaterialTheme.typography.titleMedium, + color = textColor() + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt index 7c0606d..900ed05 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt @@ -1,49 +1,42 @@ package com.sampoom.android.feature.order.ui -import androidx.compose.foundation.layout.Arrangement +import android.widget.Toast import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults +import androidx.compose.foundation.layout.width +import androidx.compose.material3.AlertDialog import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold -import androidx.compose.material3.Surface import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.sampoom.android.R +import com.sampoom.android.core.ui.component.ButtonVariant +import com.sampoom.android.core.ui.component.CommonButton import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent -import com.sampoom.android.core.ui.component.StatusChip -import com.sampoom.android.core.ui.theme.FailRed -import com.sampoom.android.core.ui.theme.SuccessGreen -import com.sampoom.android.core.ui.theme.WaitYellow -import com.sampoom.android.core.ui.theme.backgroundCardColor -import com.sampoom.android.core.ui.theme.textColor -import com.sampoom.android.core.ui.theme.textSecondaryColor -import com.sampoom.android.feature.order.domain.model.Order -import com.sampoom.android.feature.order.domain.model.OrderPart -import com.sampoom.android.feature.order.domain.model.OrderStatus +import com.sampoom.android.core.ui.component.ErrorContent @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -52,6 +45,35 @@ fun OrderDetailScreen( viewModel: OrderDetailViewModel = hiltViewModel() ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() + var showCancelOrderDialog by remember { mutableStateOf(false) } + var showReceiveOrderDialog by remember { mutableStateOf(false) } + val context = LocalContext.current + + // 성공 시 Toast 표시 후 다이얼로그 닫기 + LaunchedEffect(uiState.isProcessingCancelSuccess) { + if (uiState.isProcessingCancelSuccess) { + Toast.makeText(context, context.getString(R.string.order_detail_toast_order_cancel), Toast.LENGTH_SHORT).show() + } + viewModel.clearSuccess() + viewModel.onEvent(OrderDetailUiEvent.LoadOrder) + } + + // 성공 시 Toast 표시 후 다이얼로그 닫기 + LaunchedEffect(uiState.isProcessingReceiveSuccess) { + if (uiState.isProcessingReceiveSuccess) { + Toast.makeText(context, context.getString(R.string.order_detail_toast_order_receive), Toast.LENGTH_SHORT).show() + } + viewModel.clearSuccess() + viewModel.onEvent(OrderDetailUiEvent.LoadOrder) + } + + // 실패 시 Toast 표시 + LaunchedEffect(uiState.isProcessingError) { + uiState.isProcessingError?.let { error -> + Toast.makeText(context, error, Toast.LENGTH_LONG).show() + viewModel.onEvent(OrderDetailUiEvent.ClearError) + } + } Scaffold( topBar = { @@ -66,6 +88,26 @@ fun OrderDetailScreen( } } ) + }, + bottomBar = { + Row( + modifier = Modifier.fillMaxWidth().padding(16.dp) + ) { + CommonButton( + modifier = Modifier.weight(1f), + variant = ButtonVariant.Error, + onClick = { showCancelOrderDialog = true } + ) { + Text(stringResource(R.string.order_detail_order_cancel)) + } + Spacer(Modifier.width(16.dp)) + CommonButton( + modifier = Modifier.weight(1f), + onClick = { showReceiveOrderDialog = true } + ) { + Text(stringResource(R.string.order_detail_order_receive)) + } + } } ) { innerPadding -> when { @@ -95,161 +137,59 @@ fun OrderDetailScreen( } else -> { - LazyColumn( - modifier = Modifier - .fillMaxSize() - .padding(innerPadding) - .padding(horizontal = 16.dp), - verticalArrangement = Arrangement.spacedBy(16.dp) - ) { - uiState.orderDetail.forEach { order -> - item { - OrderInfoCard(order = order) - } - item { - Text( - text = stringResource(R.string.order_detail_order_items_title), - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold, - color = textColor() - ) - } - order.items.forEach { category -> - category.groups.forEach { group -> - item { - OrderSection( - categoryName = category.categoryName, - groupName = group.groupName, - parts = group.parts - ) - } - } - } - } - } - } - } - } -} - -@Composable -private fun OrderInfoCard(order: Order) { - Card( - modifier = Modifier.fillMaxWidth(), - colors = CardDefaults.cardColors(containerColor = backgroundCardColor()) - ) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp) - ) { - OrderInfoRow( - label = stringResource(R.string.order_detail_order_number), - value = order.orderNumber ?: stringResource(R.string.common_slash) - ) - OrderInfoRow( - label = stringResource(R.string.order_detail_order_date), - value = order.createdAt ?: stringResource(R.string.common_slash) - ) - OrderInfoRow( - label = stringResource(R.string.order_detail_order_agency), - value = order.agencyName ?: stringResource(R.string.common_slash) - ) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = stringResource(R.string.order_detail_order_status), - style = MaterialTheme.typography.bodyMedium, - color = textSecondaryColor() + OrderDetailContent( + order = uiState.orderDetail, + modifier = Modifier.padding(innerPadding) ) - - StatusChip(status = order.status) } } } -} -@Composable -private fun OrderInfoRow( - label: String, - value: String -) { - Row( - modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp), - horizontalArrangement = Arrangement.SpaceBetween - ) { - Text( - text = label, - style = MaterialTheme.typography.bodyMedium, - color = textSecondaryColor() - ) - Text( - text = value, - style = MaterialTheme.typography.bodyMedium, - color = textColor() + if (showCancelOrderDialog) { + AlertDialog( + onDismissRequest = { showCancelOrderDialog = false }, + text = { Text(stringResource(R.string.order_detail_dialog_order_cancel)) }, + confirmButton = { + TextButton( + onClick = { + showCancelOrderDialog = false + viewModel.onEvent(OrderDetailUiEvent.CancelOrder) + } + ) { + Text(stringResource(R.string.common_confirm)) + } + }, + dismissButton = { + TextButton( + onClick = { showCancelOrderDialog = false } + ) { + Text(stringResource(R.string.common_cancel)) + } + } ) } -} - -@Composable -private fun OrderSection( - categoryName: String, - groupName: String, - parts: List -) { - Column( - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - Text( - text = "$categoryName > $groupName", - style = MaterialTheme.typography.titleMedium, - color = textColor() - ) - parts.forEach { part -> - OrderPartItem(part = part) - } - } -} - -@Composable -private fun OrderPartItem( - part: OrderPart -) { - Card( - modifier = Modifier.fillMaxWidth(), - colors = CardDefaults.cardColors(containerColor = backgroundCardColor()) - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Column( - modifier = Modifier.weight(1F) - ) { - Text( - text = part.name, - style = MaterialTheme.typography.titleMedium, - color = textColor() - ) - Text( - text = part.code, - style = MaterialTheme.typography.bodySmall, - color = textSecondaryColor() - ) + if (showReceiveOrderDialog) { + AlertDialog( + onDismissRequest = { showReceiveOrderDialog = false }, + text = { Text(stringResource(R.string.order_detail_dialog_order_receive)) }, + confirmButton = { + TextButton( + onClick = { + showReceiveOrderDialog = false + viewModel.onEvent(OrderDetailUiEvent.ReceiveOrder) + } + ) { + Text(stringResource(R.string.common_confirm)) + } + }, + dismissButton = { + TextButton( + onClick = { showReceiveOrderDialog = false } + ) { + Text(stringResource(R.string.common_cancel)) + } } - - Text( - text = part.quantity.toString(), - style = MaterialTheme.typography.titleMedium, - color = textColor() - ) - } + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiEvent.kt index 2caa7c4..90e3fb5 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiEvent.kt @@ -3,4 +3,7 @@ package com.sampoom.android.feature.order.ui sealed interface OrderDetailUiEvent { object LoadOrder : OrderDetailUiEvent object RetryOrder : OrderDetailUiEvent + object ReceiveOrder : OrderDetailUiEvent + object CancelOrder : OrderDetailUiEvent + object ClearError : OrderDetailUiEvent } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiState.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiState.kt index 6fdbede..fd4a4a7 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiState.kt @@ -5,5 +5,9 @@ import com.sampoom.android.feature.order.domain.model.Order data class OrderDetailUiState( val orderDetail: List = emptyList(), val orderDetailLoading: Boolean = false, - val orderDetailError: String? = null + val orderDetailError: String? = null, + val isProcessing: Boolean = false, + val isProcessingCancelSuccess: Boolean = false, + val isProcessingReceiveSuccess: Boolean = false, + val isProcessingError: String? = null ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt index e604071..648142e 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt @@ -5,7 +5,9 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.feature.order.domain.usecase.CancelOrderUseCase import com.sampoom.android.feature.order.domain.usecase.GetOrderDetailUseCase +import com.sampoom.android.feature.order.domain.usecase.ReceiveOrderUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -16,6 +18,8 @@ import javax.inject.Inject @HiltViewModel class OrderDetailViewModel @Inject constructor( private val getOrderDetailUseCase: GetOrderDetailUseCase, + private val cancelOrderUseCase: CancelOrderUseCase, + private val receiveOrderUseCase: ReceiveOrderUseCase, savedStateHandle: SavedStateHandle ) : ViewModel() { @@ -28,7 +32,17 @@ class OrderDetailViewModel @Inject constructor( // Navigation 인자 로드 private val agencyId: Long = savedStateHandle.get("agencyId") ?: 0L - private val orderId: Long = savedStateHandle.get("orderId") ?: 0L + private val navOrderId: Long = savedStateHandle.get("orderId") ?: 0L + + private var apiOrderId: Long? = null + + fun setOrderIdFromApi(orderId: Long) { + apiOrderId = orderId + } + + private fun getOrderId(): Long { + return apiOrderId ?: navOrderId + } private var errorLabel: String = "" @@ -37,14 +51,17 @@ class OrderDetailViewModel @Inject constructor( } init { - if (orderId > 0L) loadOrderDetail(orderId) + if (getOrderId() > 0L) loadOrderDetail(getOrderId()) else _uiState.update { it.copy(orderDetailError = errorLabel) } } fun onEvent(event: OrderDetailUiEvent) { when (event) { - is OrderDetailUiEvent.LoadOrder -> loadOrderDetail(orderId) - is OrderDetailUiEvent.RetryOrder -> loadOrderDetail(orderId) + is OrderDetailUiEvent.LoadOrder -> loadOrderDetail(getOrderId()) + is OrderDetailUiEvent.RetryOrder -> loadOrderDetail(getOrderId()) + is OrderDetailUiEvent.CancelOrder -> cancelOrder(getOrderId()) + is OrderDetailUiEvent.ReceiveOrder -> receiveOrder(getOrderId()) + is OrderDetailUiEvent.ClearError -> _uiState.update { it.copy(isProcessingError = null) } } } @@ -74,4 +91,62 @@ class OrderDetailViewModel @Inject constructor( Log.d(TAG, "submit: ${_uiState.value}") } } + + private fun cancelOrder(orderId: Long) { + viewModelScope.launch { + _uiState.update { it.copy(isProcessing = true, isProcessingError = null) } + + cancelOrderUseCase(orderId) + .onSuccess { + _uiState.update { + it.copy( + isProcessing = false, + isProcessingCancelSuccess = true, + isProcessingError = null + ) + } + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + isProcessing = false, + isProcessingError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + } + Log.d(TAG, "submit: ${_uiState.value}") + } + } + + private fun receiveOrder(orderId: Long) { + viewModelScope.launch { + _uiState.update { it.copy(isProcessing = true, isProcessingError = null) } + + receiveOrderUseCase(orderId) + .onSuccess { + _uiState.update { + it.copy( + isProcessing = false, + isProcessingReceiveSuccess = true, + isProcessingError = null + ) + } + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + isProcessing = false, + isProcessingError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + } + Log.d(TAG, "submit: ${_uiState.value}") + } + } + + fun clearSuccess() { + _uiState.update { it.copy(isProcessingCancelSuccess = false, isProcessingReceiveSuccess = false) } + } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt new file mode 100644 index 0000000..eb2152c --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt @@ -0,0 +1,168 @@ +package com.sampoom.android.feature.order.ui + +import android.widget.Toast +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.sampoom.android.R +import com.sampoom.android.core.ui.component.ButtonVariant +import com.sampoom.android.core.ui.component.CommonButton +import com.sampoom.android.core.ui.theme.SuccessGreen +import com.sampoom.android.core.ui.theme.textColor +import com.sampoom.android.feature.order.domain.model.Order + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun OrderResultBottomSheet( + order: List, + onDismiss: () -> Unit, + viewModel: OrderDetailViewModel = hiltViewModel() +) { + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + val sheetState = rememberModalBottomSheetState( + skipPartiallyExpanded = true + ) + var showCancelOrderDialog by remember { mutableStateOf(false) } + val context = LocalContext.current + + LaunchedEffect(order) { + if (order.isNotEmpty()) viewModel.setOrderIdFromApi(order.first().orderId) + } + + // 성공 시 Toast 표시 후 다이얼로그 닫기 + LaunchedEffect(uiState.isProcessingCancelSuccess) { + if (uiState.isProcessingCancelSuccess) { + Toast.makeText(context, context.getString(R.string.order_detail_toast_order_cancel), Toast.LENGTH_SHORT).show() + } + viewModel.clearSuccess() + viewModel.onEvent(OrderDetailUiEvent.LoadOrder) + } + + // 실패 시 Toast 표시 + LaunchedEffect(uiState.isProcessingError) { + uiState.isProcessingError?.let { error -> + Toast.makeText(context, error, Toast.LENGTH_LONG).show() + viewModel.onEvent(OrderDetailUiEvent.ClearError) + } + } + + ModalBottomSheet( + onDismissRequest = onDismiss, + sheetState = sheetState + ) { + Column( + modifier = Modifier + .fillMaxHeight(0.9f) + ) { + // 주문 완료 헤더 + OrderCompleteHeader() + + Spacer(modifier = Modifier.height(16.dp)) + + // OrderDetailContent 재사용 + OrderDetailContent( + order = order, + modifier = Modifier.weight(1f) + ) + + // 하단 고정 버튼들 + Spacer(modifier = Modifier.height(16.dp)) + + Row( + modifier = Modifier.fillMaxWidth().padding(16.dp) + ) { + CommonButton( + modifier = Modifier.weight(1f), + variant = ButtonVariant.Error, + onClick = { showCancelOrderDialog = true } + ) { + Text(stringResource(R.string.order_detail_order_cancel)) + } + } + + // 하단 여백 + Spacer(modifier = Modifier.height(16.dp)) + } + } + + if (showCancelOrderDialog) { + AlertDialog( + onDismissRequest = { showCancelOrderDialog = false }, + text = { Text(stringResource(R.string.order_detail_dialog_order_cancel)) }, + confirmButton = { + TextButton( + onClick = { + showCancelOrderDialog = false + viewModel.onEvent(OrderDetailUiEvent.CancelOrder) + } + ) { + Text(stringResource(R.string.common_confirm)) + } + }, + dismissButton = { + TextButton( + onClick = { showCancelOrderDialog = false } + ) { + Text(stringResource(R.string.common_cancel)) + } + } + ) + } +} + +@Composable +private fun OrderCompleteHeader() { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 16.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + painter = painterResource(id = R.drawable.ic_check_circle), + contentDescription = stringResource(R.string.common_confirm), + tint = SuccessGreen, + modifier = Modifier.size(20.dp) + ) + + Spacer(modifier = Modifier.width(8.dp)) + + Text( + text = stringResource(R.string.cart_toast_order_text), + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold, + color = textColor() + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt index 1139cf5..55c3f6f 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt @@ -18,8 +18,8 @@ class OutboundRepositoryImpl @Inject constructor( } override suspend fun processOutbound(): Result { - val dto = api.processOutbound() return runCatching { + val dto = api.processOutbound() if (!dto.success) throw Exception(dto.message) } } @@ -28,22 +28,22 @@ class OutboundRepositoryImpl @Inject constructor( partId: Long, quantity: Long ): Result { - val dto = api.addOutbound(AddOutboundRequestDto(partId, quantity)) return runCatching { + val dto = api.addOutbound(AddOutboundRequestDto(partId, quantity)) if (!dto.success) throw Exception(dto.message) } } override suspend fun deleteOutbound(outboundId: Long): Result { - val dto = api.deleteOutbound(outboundId) return runCatching { + val dto = api.deleteOutbound(outboundId) if (!dto.success) throw Exception(dto.message) } } override suspend fun deleteAllOutbound(): Result { - val dto = api.deleteAllOutbound() return runCatching { + val dto = api.deleteAllOutbound() if (!dto.success) throw Exception(dto.message) } } @@ -52,8 +52,8 @@ class OutboundRepositoryImpl @Inject constructor( outboundId: Long, quantity: Long ): Result { - val dto = api.updateOutbound(outboundId, UpdateOutboundRequestDto(quantity)) return runCatching { + val dto = api.updateOutbound(outboundId, UpdateOutboundRequestDto(quantity)) if (!dto.success) throw Exception(dto.message) } } diff --git a/app/src/main/res/drawable/ic_check_circle.xml b/app/src/main/res/drawable/ic_check_circle.xml new file mode 100644 index 0000000..7f747c6 --- /dev/null +++ b/app/src/main/res/drawable/ic_check_circle.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 52953bd..dbc472d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -73,9 +73,9 @@ 장바구니 목록이 없습니다. 장바구니 목록에 추가하시겠습니까? 장바구니 목록에 추가되었습니다 - 장바구니에 추가하시겠습니까? + 장바구니 목륵의 상품을 주문하시겠습니까? 장바구니를 비우시겠습니까? - 추가되었습니다 + 주문이 완료되었습니다 부품 주문 @@ -87,6 +87,12 @@ 대리점 주문상태 주문상품 + 주문취소 + 주문 취소처리하시겠습니까? + 주문 취소처리되었습니다 + 입고처리 + 입고 처리하시겠습니까? + 입고 처리되었습니다 승인대기 From 9430d1f6227836ed5514f7150552bd1f39e6c493 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Tue, 21 Oct 2025 11:07:03 +0900 Subject: [PATCH 41/88] =?UTF-8?q?[REFAC]=20=EB=AF=B8=EC=82=AC=EC=9A=A9=20I?= =?UTF-8?q?mport=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sampoom/android/feature/cart/ui/CartListScreen.kt | 2 -- .../com/sampoom/android/feature/cart/ui/CartListViewModel.kt | 1 - .../com/sampoom/android/feature/order/ui/OrderDetailScreen.kt | 1 - .../com/sampoom/android/feature/order/ui/OrderListScreen.kt | 3 --- .../sampoom/android/feature/part/ui/PartDetailBottomSheet.kt | 2 -- .../java/com/sampoom/android/feature/part/ui/PartListScreen.kt | 1 - 6 files changed, 10 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt index 5c6ad52..52e1333 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt @@ -1,6 +1,5 @@ package com.sampoom.android.feature.cart.ui -import android.widget.Toast import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -28,7 +27,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt index 4f6d7a1..ff30e54 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt @@ -1,6 +1,5 @@ package com.sampoom.android.feature.cart.ui -import android.R.attr.order import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt index 900ed05..4a2e811 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt @@ -36,7 +36,6 @@ import com.sampoom.android.core.ui.component.ButtonVariant import com.sampoom.android.core.ui.component.CommonButton import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent -import com.sampoom.android.core.ui.component.ErrorContent @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt index 8e4d528..ae9420f 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt @@ -12,7 +12,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.CircularProgressIndicator @@ -25,7 +24,6 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -39,7 +37,6 @@ import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.core.util.buildOrderTitle import com.sampoom.android.core.util.formatDate import com.sampoom.android.feature.order.domain.model.Order -import com.sampoom.android.feature.order.domain.model.OrderPart @Composable fun OrderListScreen( diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt index 24419cd..540c120 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt @@ -31,7 +31,6 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -42,7 +41,6 @@ import com.sampoom.android.core.ui.component.CommonButton import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.part.domain.model.Part -import kotlinx.coroutines.delay @Composable fun PartDetailBottomSheet( diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt index 17f7c76..8aa2fae 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt @@ -45,7 +45,6 @@ import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.part.domain.model.Part -import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @Composable From 1b4b94b4fd22dfe6de15667a3ffcb39a072eb5e4 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Tue, 21 Oct 2025 12:08:15 +0900 Subject: [PATCH 42/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/AppNavHost.kt | 3 +- .../sampoom/android/core/util/FormatDate.kt | 31 ++++++-- .../sampoom/android/core/util/OrderTitle.kt | 2 +- .../feature/cart/data/remote/api/CartApi.kt | 1 + .../data/repository/CartRepositoryImpl.kt | 30 +++++++- .../feature/cart/ui/CartListViewModel.kt | 37 ++++----- .../feature/order/data/remote/api/OrderApi.kt | 1 + .../data/repository/OrderRepositoryImpl.kt | 15 +++- .../android/feature/order/di/OrderModules.kt | 2 +- .../feature/order/domain/model/OrderStatus.kt | 4 +- .../feature/order/ui/OrderDetailScreen.kt | 25 ++++-- .../feature/order/ui/OrderDetailViewModel.kt | 36 +++++---- .../feature/order/ui/OrderListScreen.kt | 14 ++-- .../feature/order/ui/OrderListViewModel.kt | 36 +++++---- .../order/ui/OrderResultBottomSheet.kt | 11 ++- .../outbound/data/remote/api/OutboundApi.kt | 1 + .../data/repository/OutboundRepositoryImpl.kt | 36 +++++++-- .../feature/outbound/ui/OutboundListScreen.kt | 2 +- .../outbound/ui/OutboundListViewModel.kt | 37 ++++----- .../feature/part/data/remote/api/PartApi.kt | 1 + .../feature/part/ui/PartDetailBottomSheet.kt | 4 +- .../feature/part/ui/PartListViewModel.kt | 36 +++++---- .../android/feature/part/ui/PartViewModel.kt | 77 ++++++++++--------- app/src/main/res/values/strings.xml | 2 +- 24 files changed, 277 insertions(+), 167 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 4531182..d243585 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -23,7 +23,6 @@ import com.sampoom.android.R import com.sampoom.android.feature.auth.ui.LoginScreen import com.sampoom.android.feature.auth.ui.SignUpScreen import com.sampoom.android.feature.cart.ui.CartListScreen -import com.sampoom.android.feature.order.domain.model.OrderList import com.sampoom.android.feature.order.ui.OrderDetailScreen import com.sampoom.android.feature.order.ui.OrderListScreen import com.sampoom.android.feature.outbound.ui.OutboundListScreen @@ -101,6 +100,7 @@ fun AppNavHost() { navController.navigateUp() }, onNavigatePartList = { group -> + // TODO: 실제 사용자의 agencyId 사용 navController.navigate(routePartList(1, group.id)) } ) @@ -155,6 +155,7 @@ fun MainScreen( composable(ROUTE_ORDERS) { OrderListScreen( onNavigateOrderDetail = { order -> + // TODO: 실제 사용자의 agencyId 사용 parentNavController.navigate(routeOrderDetail(1, order.orderId)) } ) diff --git a/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt b/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt index 8fc7deb..272d9e4 100644 --- a/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt +++ b/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt @@ -1,11 +1,28 @@ package com.sampoom.android.core.util +import android.os.Build +import androidx.annotation.RequiresApi +import java.time.format.DateTimeFormatter + +@RequiresApi(Build.VERSION_CODES.O) fun formatDate(dateString: String): String { - return try { - val inFmt = java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS", java.util.Locale.getDefault()) - val outFmt = java.text.SimpleDateFormat("yyyy-MM-dd", java.util.Locale.getDefault()) - outFmt.format(inFmt.parse(dateString) ?: java.util.Date()) - } catch (_: Exception) { - dateString - } + return runCatching { + val out = DateTimeFormatter.ISO_LOCAL_DATE + val hasOffset = + dateString.endsWith("Z") || dateString.contains('+') || dateString.contains('-') + .and(dateString.count { it == ':' } >= 3) + val date = if (hasOffset) { + val inFmt = java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME + java.time.OffsetDateTime.parse(dateString, inFmt).toLocalDate() + } else { + val inFmt = java.time.format.DateTimeFormatterBuilder() + .appendPattern("yyyy-MM-dd'T'HH:mm:ss") + .optionalStart() + .appendFraction(java.time.temporal.ChronoField.NANO_OF_SECOND, 0, 6, true) + .optionalEnd() + .toFormatter(java.util.Locale.ROOT) + java.time.LocalDateTime.parse(dateString, inFmt).toLocalDate() + } + date.format(out) + }.getOrElse { dateString } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/util/OrderTitle.kt b/app/src/main/java/com/sampoom/android/core/util/OrderTitle.kt index d027df7..631540a 100644 --- a/app/src/main/java/com/sampoom/android/core/util/OrderTitle.kt +++ b/app/src/main/java/com/sampoom/android/core/util/OrderTitle.kt @@ -21,6 +21,6 @@ fun buildOrderTitle(order: Order): String { return if (totalParts == 1) { "$groupName - ${part.name} ${part.quantity}EA" } else { - "${part.name} - $groupName ${part.quantity}EA 외 ${totalParts - 1}건" + "$groupName - ${part.name} ${part.quantity}EA 외 ${totalParts - 1}건" } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt index aafff14..06bacec 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt @@ -12,6 +12,7 @@ import retrofit2.http.POST import retrofit2.http.PUT import retrofit2.http.Path +// TODO: AgencyId 동적 주입 interface CartApi { // 장바구니 목록 조회 @GET("agency/1/cart") diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt index 87cf282..ddc5d07 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt @@ -6,7 +6,9 @@ import com.sampoom.android.feature.cart.data.remote.dto.AddCartRequestDto import com.sampoom.android.feature.cart.data.remote.dto.UpdateCartRequestDto import com.sampoom.android.feature.cart.domain.model.CartList import com.sampoom.android.feature.cart.domain.repository.CartRepository +import kotlinx.coroutines.CancellationException import javax.inject.Inject +import kotlin.Result class CartRepositoryImpl @Inject constructor( private val api: CartApi @@ -21,23 +23,38 @@ class CartRepositoryImpl @Inject constructor( partId: Long, quantity: Long ): Result { - return runCatching { + return try { val dto = api.addCart(AddCartRequestDto(partId, quantity)) if (!dto.success) throw Exception(dto.message) + Result.success(Unit) + } catch (ce: CancellationException) { + throw ce + } catch (t : Throwable) { + Result.failure(t) } } override suspend fun deleteCart(cartItemId: Long): Result { - return runCatching { + return try { val dto = api.deleteCart(cartItemId) if (!dto.success) throw Exception(dto.message) + Result.success(Unit) + } catch (ce: CancellationException) { + throw ce + } catch (t : Throwable) { + Result.failure(t) } } override suspend fun deleteAllCart(): Result { - return runCatching { + return try { val dto = api.deleteAllCart() if (!dto.success) throw Exception(dto.message) + Result.success(Unit) + } catch (ce: CancellationException) { + throw ce + } catch (t : Throwable) { + Result.failure(t) } } @@ -45,9 +62,14 @@ class CartRepositoryImpl @Inject constructor( cartItemId: Long, quantity: Long ): Result { - return runCatching { + return try { val dto = api.updateCart(cartItemId, UpdateCartRequestDto(quantity)) if (!dto.success) throw Exception(dto.message) + Result.success(Unit) + } catch (ce: CancellationException) { + throw ce + } catch (t : Throwable) { + Result.failure(t) } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt index ff30e54..80506ab 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt @@ -10,6 +10,7 @@ import com.sampoom.android.feature.cart.domain.usecase.GetCartUseCase import com.sampoom.android.feature.cart.domain.usecase.UpdateCartQuantityUseCase import com.sampoom.android.feature.order.domain.usecase.CreateOrderUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update @@ -60,26 +61,26 @@ class CartListViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(cartLoading = true, cartError = null) } - runCatching { getCartListUseCase() } - .onSuccess { cartList -> - _uiState.update { - it.copy( - cartList = cartList.items, - cartLoading = false, - cartError = null - ) - } + try { + val cartList = getCartListUseCase() + _uiState.update { + it.copy( + cartList = cartList.items, + cartLoading = false, + cartError = null + ) } - .onFailure { throwable -> - val backendMessage = throwable.serverMessageOrNull() - _uiState.update { - it.copy( - cartLoading = false, - cartError = backendMessage ?: (throwable.message ?: errorLabel) - ) - } - + } catch (ce: CancellationException) { + throw ce + } catch (throwable: Throwable) { + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + cartLoading = false, + cartError = backendMessage ?: (throwable.message ?: errorLabel) + ) } + } Log.d(TAG, "submit: ${_uiState.value}") } } diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt b/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt index d8fc9fc..6785d0c 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt @@ -9,6 +9,7 @@ import retrofit2.http.PATCH import retrofit2.http.POST import retrofit2.http.Path +// TODO: AgencyId 동적 주입 interface OrderApi { // 주문 목록 조회 @GET("agency/1/orders") diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt index 16a74e1..f43065a 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt @@ -5,6 +5,7 @@ import com.sampoom.android.feature.order.data.remote.api.OrderApi import com.sampoom.android.feature.order.domain.model.OrderList import com.sampoom.android.feature.order.domain.repository.OrderRepository import javax.inject.Inject +import kotlin.coroutines.cancellation.CancellationException class OrderRepositoryImpl @Inject constructor( private val api: OrderApi @@ -22,9 +23,14 @@ class OrderRepositoryImpl @Inject constructor( } override suspend fun receiveOrder(orderId: Long): Result { - return runCatching { + return try { val dto = api.receiveOrder(orderId) if (!dto.success) throw Exception(dto.message) + Result.success(Unit) + } catch (ce : CancellationException) { + throw ce + } catch (t : Throwable) { + Result.failure(t) } } @@ -35,9 +41,14 @@ class OrderRepositoryImpl @Inject constructor( } override suspend fun cancelOrder(orderId: Long): Result { - return runCatching { + return try { val dto = api.cancelOrder(orderId) if (!dto.success) throw Exception(dto.message) + Result.success(Unit) + } catch (ce : CancellationException) { + throw ce + } catch (t : Throwable) { + Result.failure(t) } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/di/OrderModules.kt b/app/src/main/java/com/sampoom/android/feature/order/di/OrderModules.kt index fe342bf..c17f4fb 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/di/OrderModules.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/di/OrderModules.kt @@ -8,8 +8,8 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent -import jakarta.inject.Singleton import retrofit2.Retrofit +import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/model/OrderStatus.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/model/OrderStatus.kt index 4e31967..211339b 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/model/OrderStatus.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/model/OrderStatus.kt @@ -1,10 +1,12 @@ package com.sampoom.android.feature.order.domain.model +import java.util.Locale + enum class OrderStatus { PENDING, COMPLETED, CANCELED; companion object { - fun from(raw: String?): OrderStatus = when (raw?.uppercase()) { + fun from(raw: String?): OrderStatus = when (raw?.uppercase(Locale.ROOT)) { "PENDING" -> PENDING "COMPLETED" -> COMPLETED "CANCELED" -> CANCELED diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt index 4a2e811..7f7b5a3 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt @@ -36,6 +36,7 @@ import com.sampoom.android.core.ui.component.ButtonVariant import com.sampoom.android.core.ui.component.CommonButton import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent +import com.sampoom.android.feature.order.domain.model.OrderStatus @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -52,18 +53,18 @@ fun OrderDetailScreen( LaunchedEffect(uiState.isProcessingCancelSuccess) { if (uiState.isProcessingCancelSuccess) { Toast.makeText(context, context.getString(R.string.order_detail_toast_order_cancel), Toast.LENGTH_SHORT).show() + viewModel.clearSuccess() + viewModel.onEvent(OrderDetailUiEvent.LoadOrder) } - viewModel.clearSuccess() - viewModel.onEvent(OrderDetailUiEvent.LoadOrder) } // 성공 시 Toast 표시 후 다이얼로그 닫기 LaunchedEffect(uiState.isProcessingReceiveSuccess) { if (uiState.isProcessingReceiveSuccess) { Toast.makeText(context, context.getString(R.string.order_detail_toast_order_receive), Toast.LENGTH_SHORT).show() + viewModel.clearSuccess() + viewModel.onEvent(OrderDetailUiEvent.LoadOrder) } - viewModel.clearSuccess() - viewModel.onEvent(OrderDetailUiEvent.LoadOrder) } // 실패 시 Toast 표시 @@ -90,11 +91,15 @@ fun OrderDetailScreen( }, bottomBar = { Row( - modifier = Modifier.fillMaxWidth().padding(16.dp) + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) ) { CommonButton( modifier = Modifier.weight(1f), variant = ButtonVariant.Error, + enabled = uiState.orderDetail.firstOrNull()?.status != OrderStatus.COMPLETED && + uiState.orderDetail.firstOrNull()?.status != OrderStatus.CANCELED, onClick = { showCancelOrderDialog = true } ) { Text(stringResource(R.string.order_detail_order_cancel)) @@ -102,6 +107,8 @@ fun OrderDetailScreen( Spacer(Modifier.width(16.dp)) CommonButton( modifier = Modifier.weight(1f), + enabled = uiState.orderDetail.firstOrNull()?.status != OrderStatus.PENDING && + uiState.orderDetail.firstOrNull()?.status != OrderStatus.CANCELED, onClick = { showReceiveOrderDialog = true } ) { Text(stringResource(R.string.order_detail_order_receive)) @@ -124,14 +131,18 @@ fun OrderDetailScreen( uiState.orderDetailError != null -> { ErrorContent( onRetry = { viewModel.onEvent(OrderDetailUiEvent.RetryOrder) }, - modifier = Modifier.height(200.dp).fillMaxWidth() + modifier = Modifier + .height(200.dp) + .fillMaxWidth() ) } uiState.orderDetail.isEmpty() -> { EmptyContent( message = stringResource(R.string.order_empty_list), - modifier = Modifier.height(200.dp).fillMaxWidth() + modifier = Modifier + .height(200.dp) + .fillMaxWidth() ) } diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt index 648142e..a0bd0af 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt @@ -9,6 +9,7 @@ import com.sampoom.android.feature.order.domain.usecase.CancelOrderUseCase import com.sampoom.android.feature.order.domain.usecase.GetOrderDetailUseCase import com.sampoom.android.feature.order.domain.usecase.ReceiveOrderUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update @@ -69,25 +70,26 @@ class OrderDetailViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(orderDetailLoading = true, orderDetailError = null) } - runCatching { getOrderDetailUseCase(orderId) } - .onSuccess { orderList -> - _uiState.update { - it.copy( - orderDetail = orderList.items, - orderDetailLoading = false, - orderDetailError = null - ) - } + try { + val orderList = getOrderDetailUseCase(orderId) + _uiState.update { + it.copy( + orderDetail = orderList.items, + orderDetailLoading = false, + orderDetailError = null + ) } - .onFailure { throwable -> - val backendMessage = throwable.serverMessageOrNull() - _uiState.update { - it.copy( - orderDetailLoading = false, - orderDetailError = backendMessage ?: (throwable.message ?: errorLabel) - ) - } + } catch (ce : CancellationException) { + throw ce + } catch (throwable : Throwable) { + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + orderDetailLoading = false, + orderDetailError = backendMessage ?: (throwable.message ?: errorLabel) + ) } + } Log.d(TAG, "submit: ${_uiState.value}") } } diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt index ae9420f..3b38ff8 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt @@ -1,5 +1,6 @@ package com.sampoom.android.feature.order.ui +import android.R.attr.order import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -12,6 +13,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.items import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.CircularProgressIndicator @@ -114,13 +116,11 @@ fun OrderListScreen( .padding(horizontal = 16.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { - uiState.orderList.forEach { order -> - item { - OrderItem( - order = order, - onClick = { onNavigateOrderDetail(order) } - ) - } + items(uiState.orderList) { order -> + OrderItem( + order = order, + onClick = { onNavigateOrderDetail(order) } + ) } item { Spacer(Modifier.height(100.dp)) } } diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt index a5fcf74..a9cd392 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.viewModelScope import com.sampoom.android.core.network.serverMessageOrNull import com.sampoom.android.feature.order.domain.usecase.GetOrderUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update @@ -45,25 +46,26 @@ class OrderListViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(orderLoading = true, orderError = null) } - runCatching { getOrderListUseCase() } - .onSuccess { orderList -> - _uiState.update { - it.copy( - orderList = orderList.items, - orderLoading = false, - orderError = null - ) - } + try { + val orderList = getOrderListUseCase() + _uiState.update { + it.copy( + orderList = orderList.items, + orderLoading = false, + orderError = null + ) } - .onFailure { throwable -> - val backendMessage = throwable.serverMessageOrNull() - _uiState.update { - it.copy( - orderLoading = false, - orderError = backendMessage ?: (throwable.message ?: errorLabel ) - ) - } + } catch (ce: CancellationException) { + throw ce + } catch (throwable: Throwable) { + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + orderLoading = false, + orderError = backendMessage ?: (throwable.message ?: errorLabel ) + ) } + } Log.d(TAG, "submit: ${_uiState.value}") } } diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt index eb2152c..b125c62 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt @@ -40,6 +40,7 @@ import com.sampoom.android.core.ui.component.CommonButton import com.sampoom.android.core.ui.theme.SuccessGreen import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.feature.order.domain.model.Order +import com.sampoom.android.feature.order.domain.model.OrderStatus @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -63,9 +64,9 @@ fun OrderResultBottomSheet( LaunchedEffect(uiState.isProcessingCancelSuccess) { if (uiState.isProcessingCancelSuccess) { Toast.makeText(context, context.getString(R.string.order_detail_toast_order_cancel), Toast.LENGTH_SHORT).show() + viewModel.clearSuccess() + viewModel.onEvent(OrderDetailUiEvent.LoadOrder) } - viewModel.clearSuccess() - viewModel.onEvent(OrderDetailUiEvent.LoadOrder) } // 실패 시 Toast 표시 @@ -99,11 +100,15 @@ fun OrderResultBottomSheet( Spacer(modifier = Modifier.height(16.dp)) Row( - modifier = Modifier.fillMaxWidth().padding(16.dp) + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) ) { CommonButton( modifier = Modifier.weight(1f), variant = ButtonVariant.Error, + enabled = order.firstOrNull()?.status != OrderStatus.COMPLETED && + order.firstOrNull()?.status != OrderStatus.CANCELED, onClick = { showCancelOrderDialog = true } ) { Text(stringResource(R.string.order_detail_order_cancel)) diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt index 02c13bf..d7ee115 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt @@ -12,6 +12,7 @@ import retrofit2.http.PATCH import retrofit2.http.POST import retrofit2.http.Path +// TODO: AgencyId 동적 주입 interface OutboundApi { // 출고 목록 조회 @GET("agency/1/outbound") diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt index 55c3f6f..71f3245 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt @@ -7,6 +7,7 @@ import com.sampoom.android.feature.outbound.data.remote.dto.UpdateOutboundReques import com.sampoom.android.feature.outbound.domain.model.OutboundList import com.sampoom.android.feature.outbound.domain.repository.OutboundRepository import jakarta.inject.Inject +import kotlin.coroutines.cancellation.CancellationException class OutboundRepositoryImpl @Inject constructor( private val api: OutboundApi @@ -18,9 +19,14 @@ class OutboundRepositoryImpl @Inject constructor( } override suspend fun processOutbound(): Result { - return runCatching { + return try { val dto = api.processOutbound() if (!dto.success) throw Exception(dto.message) + Result.success(Unit) + } catch (ce : CancellationException) { + throw ce + } catch (t : Throwable) { + Result.failure(t) } } @@ -28,23 +34,38 @@ class OutboundRepositoryImpl @Inject constructor( partId: Long, quantity: Long ): Result { - return runCatching { + return try { val dto = api.addOutbound(AddOutboundRequestDto(partId, quantity)) if (!dto.success) throw Exception(dto.message) + Result.success(Unit) + } catch (ce : CancellationException) { + throw ce + } catch (t : Throwable) { + Result.failure(t) } } override suspend fun deleteOutbound(outboundId: Long): Result { - return runCatching { + return try { val dto = api.deleteOutbound(outboundId) if (!dto.success) throw Exception(dto.message) + Result.success(Unit) + } catch (ce : CancellationException) { + throw ce + } catch (t : Throwable) { + Result.failure(t) } } override suspend fun deleteAllOutbound(): Result { - return runCatching { + return try { val dto = api.deleteAllOutbound() if (!dto.success) throw Exception(dto.message) + Result.success(Unit) + } catch (ce : CancellationException) { + throw ce + } catch (t : Throwable) { + Result.failure(t) } } @@ -52,9 +73,14 @@ class OutboundRepositoryImpl @Inject constructor( outboundId: Long, quantity: Long ): Result { - return runCatching { + return try { val dto = api.updateOutbound(outboundId, UpdateOutboundRequestDto(quantity)) if (!dto.success) throw Exception(dto.message) + Result.success(Unit) + } catch (ce : CancellationException) { + throw ce + } catch (t : Throwable) { + Result.failure(t) } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt index 4323ec8..a2501d2 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt @@ -70,8 +70,8 @@ fun OutboundListScreen( LaunchedEffect(uiState.isOrderSuccess) { if (uiState.isOrderSuccess) { Toast.makeText(context, context.getString(R.string.outbound_toast_order_text), Toast.LENGTH_SHORT).show() + viewModel.clearSuccess() } - viewModel.clearSuccess() } Column(Modifier.fillMaxSize()) { diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt index 4fa3c09..8a49c79 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt @@ -10,6 +10,7 @@ import com.sampoom.android.feature.outbound.domain.usecase.GetOutboundUseCase import com.sampoom.android.feature.outbound.domain.usecase.ProcessOutboundUseCase import com.sampoom.android.feature.outbound.domain.usecase.UpdateOutboundQuantityUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update @@ -59,26 +60,26 @@ class OutboundListViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(outboundLoading = true, outboundError = null) } - runCatching { getOutboundUseCase() } - .onSuccess { outboundList -> - _uiState.update { - it.copy( - outboundList = outboundList.items, - outboundLoading = false, - outboundError = null - ) - } + try { + val outboundList = getOutboundUseCase() + _uiState.update { + it.copy( + outboundList = outboundList.items, + outboundLoading = false, + outboundError = null + ) } - .onFailure { throwable -> - val backendMessage = throwable.serverMessageOrNull() - _uiState.update { - it.copy( - outboundLoading = false, - outboundError = backendMessage ?: (throwable.message ?: errorLabel) - ) - } - + } catch (ce: CancellationException) { + throw ce + } catch (throwable: Throwable) { + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + outboundLoading = false, + outboundError = backendMessage ?: (throwable.message ?: errorLabel) + ) } + } Log.d(TAG, "submit: ${_uiState.value}") } } diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt b/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt index 06f1004..eaea882 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt @@ -7,6 +7,7 @@ import com.sampoom.android.feature.part.data.remote.dto.PartDto import retrofit2.http.GET import retrofit2.http.Path +// TODO: AgencyId 동적 주입 interface PartApi { @GET("agency/category") suspend fun getCategoryList(): ApiResponse> diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt index 540c120..d9a2701 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt @@ -70,16 +70,16 @@ fun PartDetailBottomSheet( LaunchedEffect(uiState.isOutboundSuccess) { if (uiState.isOutboundSuccess) { Toast.makeText(context, context.getString(R.string.outbound_toast_success), Toast.LENGTH_SHORT).show() + viewModel.clearSuccess() } - viewModel.clearSuccess() } // 성공 시 Toast 표시 후 다이얼로그 닫기 LaunchedEffect(uiState.isCartSuccess) { if (uiState.isCartSuccess) { Toast.makeText(context, context.getString(R.string.cart_toast_success), Toast.LENGTH_SHORT).show() + viewModel.clearSuccess() } - viewModel.clearSuccess() } // 실패 시 Toast 표시 diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt index f582f31..80897f3 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.viewModelScope import com.sampoom.android.core.network.serverMessageOrNull import com.sampoom.android.feature.part.domain.usecase.GetPartUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update @@ -54,25 +55,26 @@ class PartListViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(partListLoading = true, partListError = null) } - runCatching { getPartListUseCase(groupId) } - .onSuccess { partList -> - _uiState.update { - it.copy( - partList = partList.items, - partListLoading = false, - partListError = null - ) - } + try { + val partList = getPartListUseCase(groupId) + _uiState.update { + it.copy( + partList = partList.items, + partListLoading = false, + partListError = null + ) } - .onFailure { throwable -> - val backendMessage = throwable.serverMessageOrNull() - _uiState.update { - it.copy( - partListLoading = false, - partListError = backendMessage ?: (throwable.message ?: errorLabel) - ) - } + } catch (ce: CancellationException) { + throw ce + } catch (throwable: Throwable) { + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + partListLoading = false, + partListError = backendMessage ?: (throwable.message ?: errorLabel) + ) } + } Log.d(TAG, "submit: ${_uiState.value}") } } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt index 2a87763..bb8e0c8 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt @@ -8,6 +8,7 @@ import com.sampoom.android.feature.part.domain.model.Category import com.sampoom.android.feature.part.domain.usecase.GetCategoryUseCase import com.sampoom.android.feature.part.domain.usecase.GetGroupUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -52,25 +53,26 @@ class PartViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(categoryLoading = true, categoryError = null) } - runCatching { getCategoryUseCase() } - .onSuccess { categoryList -> - _uiState.update { - it.copy( - categoryList = categoryList.items, - categoryLoading = false, - categoryError = null - ) - } + try { + val categoryList = getCategoryUseCase() + _uiState.update { + it.copy( + categoryList = categoryList.items, + categoryLoading = false, + categoryError = null + ) } - .onFailure { throwable -> - val backendMessage = throwable.serverMessageOrNull() - _uiState.update { - it.copy( - categoryLoading = false, - categoryError = backendMessage ?: (throwable.message ?: errorLabel) - ) - } + } catch (ce: CancellationException) { + throw ce + } catch (throwable: Throwable) { + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + categoryLoading = false, + categoryError = backendMessage ?: (throwable.message ?: errorLabel) + ) } + } Log.d(TAG, "loadCategory: ${_uiState.value}") } } @@ -88,28 +90,29 @@ class PartViewModel @Inject constructor( groupLoadJob = viewModelScope.launch { _uiState.update { it.copy(groupLoading = true, groupError = null) } - runCatching { getGroupUseCase(categoryId) } - .onSuccess { groupList -> - // 최신 선택과 불일치하면 무시 - if (_uiState.value.selectedCategory?.id != categoryId) return@onSuccess - _uiState.update { - it.copy( - groupList = groupList.items, - groupLoading = false, - groupError = null - ) - } + try { + val groupList = getGroupUseCase(categoryId) + // 최신 선택과 불일치하면 무시 + if (_uiState.value.selectedCategory?.id != categoryId) return@launch + _uiState.update { + it.copy( + groupList = groupList.items, + groupLoading = false, + groupError = null + ) } - .onFailure { throwable -> - val backendMessage = throwable.serverMessageOrNull() - if (_uiState.value.selectedCategory?.id != categoryId) return@onFailure - _uiState.update { - it.copy( - groupLoading = false, - groupError = backendMessage ?: (throwable.message ?: errorLabel) - ) - } + } catch (ce: CancellationException) { + throw ce + } catch (throwable: Throwable) { + val backendMessage = throwable.serverMessageOrNull() + if (_uiState.value.selectedCategory?.id != categoryId) return@launch + _uiState.update { + it.copy( + groupLoading = false, + groupError = backendMessage ?: (throwable.message ?: errorLabel) + ) } + } Log.d(TAG, "loadGroup: ${_uiState.value}") } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dbc472d..b61421d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -73,7 +73,7 @@ 장바구니 목록이 없습니다. 장바구니 목록에 추가하시겠습니까? 장바구니 목록에 추가되었습니다 - 장바구니 목륵의 상품을 주문하시겠습니까? + 장바구니 목록의 상품을 주문하시겠습니까? 장바구니를 비우시겠습니까? 주문이 완료되었습니다 부품 주문 From bed77cda51715442eda578a56248228ab733906f Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Tue, 21 Oct 2025 13:03:47 +0900 Subject: [PATCH 43/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/order/ui/OrderListScreen.kt | 2 -- .../android/feature/order/ui/OrderListViewModel.kt | 10 ++++++++-- .../android/feature/order/ui/OrderResultBottomSheet.kt | 8 +++++--- app/src/main/res/values/strings.xml | 4 ++-- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt index 3b38ff8..f13f0e6 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt @@ -1,6 +1,5 @@ package com.sampoom.android.feature.order.ui -import android.R.attr.order import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -51,7 +50,6 @@ fun OrderListScreen( LaunchedEffect(errorLabel) { viewModel.bindLabel(errorLabel) - viewModel.onEvent(OrderListUiEvent.LoadOrderList) } Column(Modifier.fillMaxSize()) { diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt index a9cd392..a2bfa67 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt @@ -7,10 +7,14 @@ import com.sampoom.android.core.network.serverMessageOrNull import com.sampoom.android.feature.order.domain.usecase.GetOrderUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import okhttp3.Dispatcher import javax.inject.Inject @HiltViewModel @@ -26,6 +30,7 @@ class OrderListViewModel @Inject constructor( val uiState: StateFlow = _uiState private var errorLabel: String = "" + private var loadJob: Job? = null fun bindLabel(error: String) { errorLabel = error @@ -43,11 +48,12 @@ class OrderListViewModel @Inject constructor( } private fun loadOrderList() { - viewModelScope.launch { + if (loadJob?.isActive == true) return + loadJob = viewModelScope.launch { _uiState.update { it.copy(orderLoading = true, orderError = null) } try { - val orderList = getOrderListUseCase() + val orderList = withContext(Dispatchers.IO) { getOrderListUseCase() } _uiState.update { it.copy( orderList = orderList.items, diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt index b125c62..abd4407 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt @@ -1,5 +1,6 @@ package com.sampoom.android.feature.order.ui +import android.R.attr.onClick import android.widget.Toast import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -56,7 +57,7 @@ fun OrderResultBottomSheet( var showCancelOrderDialog by remember { mutableStateOf(false) } val context = LocalContext.current - LaunchedEffect(order) { + LaunchedEffect(order.firstOrNull()?.orderId) { if (order.isNotEmpty()) viewModel.setOrderIdFromApi(order.first().orderId) } @@ -107,8 +108,9 @@ fun OrderResultBottomSheet( CommonButton( modifier = Modifier.weight(1f), variant = ButtonVariant.Error, - enabled = order.firstOrNull()?.status != OrderStatus.COMPLETED && - order.firstOrNull()?.status != OrderStatus.CANCELED, + enabled = order.firstOrNull()?.let { + it.status != OrderStatus.COMPLETED && it.status != OrderStatus.CANCELED + } ?: false, onClick = { showCancelOrderDialog = true } ) { Text(stringResource(R.string.order_detail_order_cancel)) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b61421d..1956094 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -96,8 +96,8 @@ 승인대기 - 배송완료 - 주문실패 + 입고완료 + 주문취소 오류가 발생했습니다 From 7b6058e00ae8248568ed2221a692736f72ec5f37 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Tue, 21 Oct 2025 14:06:11 +0900 Subject: [PATCH 44/88] =?UTF-8?q?[FIX]=20=EB=B2=84=ED=8A=BC=20=EB=B9=84?= =?UTF-8?q?=ED=99=9C=EC=84=B1=ED=99=94=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/sampoom/android/feature/order/ui/OrderDetailScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt index 7f7b5a3..ef3352c 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt @@ -107,7 +107,7 @@ fun OrderDetailScreen( Spacer(Modifier.width(16.dp)) CommonButton( modifier = Modifier.weight(1f), - enabled = uiState.orderDetail.firstOrNull()?.status != OrderStatus.PENDING && + enabled = uiState.orderDetail.firstOrNull()?.status != OrderStatus.COMPLETED && uiState.orderDetail.firstOrNull()?.status != OrderStatus.CANCELED, onClick = { showReceiveOrderDialog = true } ) { From 3ece7b981aca47156364a4fdca3f0e7c49cf3d7b Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Wed, 22 Oct 2025 09:11:58 +0900 Subject: [PATCH 45/88] =?UTF-8?q?[FEAT]=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=8A=A4=EC=99=80=EC=9D=B4=ED=94=84=20=EC=83=88=EB=A1=9C?= =?UTF-8?q?=EA=B3=A0=EC=B9=A8=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/AppNavHost.kt | 33 ++- .../sampoom/android/core/util/FormatDate.kt | 2 +- .../android/feature/cart/ui/CartListScreen.kt | 203 +++++++++-------- .../feature/order/ui/OrderDetailScreen.kt | 159 ++++++++------ .../feature/order/ui/OrderListScreen.kt | 144 ++++++++----- .../feature/order/ui/OrderListViewModel.kt | 1 + .../order/ui/OrderResultBottomSheet.kt | 7 +- .../feature/outbound/ui/OutboundListScreen.kt | 204 ++++++++++-------- .../android/feature/part/ui/PartListScreen.kt | 142 ++++++------ 9 files changed, 518 insertions(+), 377 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index d243585..94d0f63 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -1,5 +1,8 @@ package com.sampoom.android.app.navigation +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.padding import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon @@ -59,6 +62,7 @@ sealed class BottomNavItem( object Orders : BottomNavItem(ROUTE_ORDERS, R.string.nav_order, R.drawable.orders) } +@RequiresApi(Build.VERSION_CODES.O) @Composable fun AppNavHost() { val navController = rememberNavController() @@ -134,6 +138,7 @@ fun AppNavHost() { } } +@RequiresApi(Build.VERSION_CODES.O) @Composable fun MainScreen( parentNavController: NavHostController @@ -146,14 +151,26 @@ fun MainScreen( ) { innerPadding -> NavHost( navController = navController, - startDestination = ROUTE_DASHBOARD, - modifier = Modifier.padding(innerPadding) + startDestination = ROUTE_DASHBOARD ) { - composable(ROUTE_DASHBOARD) { DashboardScreen() } - composable(ROUTE_OUTBOUND) { OutboundListScreen() } - composable(ROUTE_CART) { CartListScreen() } + composable(ROUTE_DASHBOARD) { + DashboardScreen( + paddingValues = innerPadding + ) + } + composable(ROUTE_OUTBOUND) { + OutboundListScreen( + paddingValues = innerPadding + ) + } + composable(ROUTE_CART) { + CartListScreen( + paddingValues = innerPadding + ) + } composable(ROUTE_ORDERS) { OrderListScreen( + paddingValues = innerPadding, onNavigateOrderDetail = { order -> // TODO: 실제 사용자의 agencyId 사용 parentNavController.navigate(routeOrderDetail(1, order.orderId)) @@ -223,7 +240,9 @@ fun BottomNavigationBar(navController: NavHostController) { // 임시 화면들 (실제로는 각각의 feature 모듈에서 구현) @Composable -private fun DashboardScreen() { +private fun DashboardScreen( + paddingValues: PaddingValues +) { // 홈 화면 구현 - Text("대시보드 화면") + Text("대시보드 화면", modifier = Modifier.padding(paddingValues)) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt b/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt index 272d9e4..425a09b 100644 --- a/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt +++ b/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt @@ -12,7 +12,7 @@ fun formatDate(dateString: String): String { dateString.endsWith("Z") || dateString.contains('+') || dateString.contains('-') .and(dateString.count { it == ':' } >= 3) val date = if (hasOffset) { - val inFmt = java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME + val inFmt = DateTimeFormatter.ISO_OFFSET_DATE_TIME java.time.OffsetDateTime.parse(dateString, inFmt).toLocalDate() } else { val inFmt = java.time.format.DateTimeFormatterBuilder() diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt index 52e1333..bf83548 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt @@ -3,6 +3,7 @@ package com.sampoom.android.feature.cart.ui import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -19,6 +20,9 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextButton +import androidx.compose.material3.pulltorefresh.PullToRefreshBox +import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults.Indicator +import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -43,15 +47,18 @@ import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.cart.domain.model.CartPart +import com.sampoom.android.feature.order.ui.OrderListUiEvent import com.sampoom.android.feature.order.ui.OrderResultBottomSheet import kotlin.collections.forEach @Composable fun CartListScreen( + paddingValues: PaddingValues, viewModel: CartListViewModel = hiltViewModel() ) { val errorLabel = stringResource(R.string.common_error) val uiState by viewModel.uiState.collectAsStateWithLifecycle() + val pullRefreshState = rememberPullToRefreshState() var showEmptyCartDialog by remember { mutableStateOf(false) } var showConfirmDialog by remember { mutableStateOf(false) } @@ -67,113 +74,129 @@ fun CartListScreen( ) } - Column(Modifier.fillMaxSize()) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - modifier = Modifier - .padding(vertical = 16.dp), - text = stringResource(R.string.cart_title), - style = MaterialTheme.typography.titleLarge, - color = textColor() + PullToRefreshBox( + isRefreshing = uiState.cartLoading, + onRefresh = { viewModel.onEvent(CartListUiEvent.LoadCartList) }, + state = pullRefreshState, + modifier = Modifier.fillMaxSize(), + indicator = { + Indicator( + modifier = Modifier.align(Alignment.TopCenter), + isRefreshing = uiState.cartLoading, + containerColor = MaterialTheme.colorScheme.primaryContainer, + color = MaterialTheme.colorScheme.onPrimaryContainer, + state = pullRefreshState ) + } + ) { + Column(Modifier.fillMaxSize().padding(paddingValues)) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + modifier = Modifier + .padding(vertical = 16.dp), + text = stringResource(R.string.cart_title), + style = MaterialTheme.typography.titleLarge, + color = textColor() + ) - when { - uiState.cartLoading -> {} - uiState.cartError != null -> {} - uiState.cartList.isEmpty() -> {} - else -> { - TextButton( - onClick = { showEmptyCartDialog = true } - ) { - Text( - text = stringResource(R.string.cart_empty_list), - style = MaterialTheme.typography.titleMedium, - color = FailRed - ) + when { + uiState.cartLoading -> {} + uiState.cartError != null -> {} + uiState.cartList.isEmpty() -> {} + else -> { + TextButton( + onClick = { showEmptyCartDialog = true } + ) { + Text( + text = stringResource(R.string.cart_empty_list), + style = MaterialTheme.typography.titleMedium, + color = FailRed + ) + } } } } - } - when { - uiState.cartLoading -> { - Box( - modifier = Modifier - .fillMaxSize(), - contentAlignment = Alignment.Center - ) { - CircularProgressIndicator() - } - } - - uiState.cartError != null -> { - Box( - modifier = Modifier - .fillMaxSize(), - contentAlignment = Alignment.Center - ) { - ErrorContent( - onRetry = { viewModel.onEvent(CartListUiEvent.RetryCartList) }, - modifier = Modifier.height(200.dp) - ) + when { + uiState.cartLoading -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } } - } - uiState.cartList.isEmpty() -> { - Box( - modifier = Modifier - .fillMaxSize(), - contentAlignment = Alignment.Center - ) { - EmptyContent( - message = stringResource(R.string.cart_empty_outbound), - modifier = Modifier.height(200.dp) - ) + uiState.cartError != null -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + ErrorContent( + onRetry = { viewModel.onEvent(CartListUiEvent.RetryCartList) }, + modifier = Modifier.height(200.dp) + ) + } } - } - else -> { - Box(modifier = Modifier.fillMaxSize()) { - LazyColumn( + uiState.cartList.isEmpty() -> { + Box( modifier = Modifier - .fillMaxSize() - .padding(horizontal = 16.dp), - verticalArrangement = Arrangement.spacedBy(16.dp) + .fillMaxSize(), + contentAlignment = Alignment.Center ) { - uiState.cartList.forEach { category -> - category.groups.forEach { group -> - item { - CartSection( - categoryName = category.categoryName, - groupName = group.groupName, - parts = group.parts, - isUpdating = uiState.isUpdating, - isDeleting = uiState.isDeleting, - onEvent = { viewModel.onEvent(it) } - ) + EmptyContent( + message = stringResource(R.string.cart_empty_outbound), + modifier = Modifier.height(200.dp) + ) + } + } + + else -> { + Box(modifier = Modifier.fillMaxSize()) { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + uiState.cartList.forEach { category -> + category.groups.forEach { group -> + item { + CartSection( + categoryName = category.categoryName, + groupName = group.groupName, + parts = group.parts, + isUpdating = uiState.isUpdating, + isDeleting = uiState.isDeleting, + onEvent = { viewModel.onEvent(it) } + ) + } } } + item { Spacer(Modifier.height(100.dp)) } } - item { Spacer(Modifier.height(100.dp)) } - } - CommonButton( - modifier = Modifier - .fillMaxWidth() - .align(Alignment.BottomEnd) - .padding(16.dp) - .padding(end = 72.dp), - variant = ButtonVariant.Primary, - size = ButtonSize.Large, - onClick = { showConfirmDialog = true } - ) { Text(stringResource(R.string.cart_order_parts)) } + CommonButton( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.BottomEnd) + .padding(16.dp) + .padding(end = 72.dp), + variant = ButtonVariant.Primary, + size = ButtonSize.Large, + onClick = { showConfirmDialog = true } + ) { Text(stringResource(R.string.cart_order_parts)) } + } } } } diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt index ef3352c..d4bbfcc 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt @@ -1,9 +1,11 @@ package com.sampoom.android.feature.order.ui +import android.R.attr.order import android.widget.Toast import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -13,10 +15,14 @@ import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBar +import androidx.compose.material3.pulltorefresh.PullToRefreshBox +import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults.Indicator +import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -37,6 +43,7 @@ import com.sampoom.android.core.ui.component.CommonButton import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent import com.sampoom.android.feature.order.domain.model.OrderStatus +import com.sampoom.android.feature.outbound.ui.OutboundListUiEvent @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -45,6 +52,7 @@ fun OrderDetailScreen( viewModel: OrderDetailViewModel = hiltViewModel() ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() + val pullRefreshState = rememberPullToRefreshState() var showCancelOrderDialog by remember { mutableStateOf(false) } var showReceiveOrderDialog by remember { mutableStateOf(false) } val context = LocalContext.current @@ -75,82 +83,101 @@ fun OrderDetailScreen( } } - Scaffold( - topBar = { - TopAppBar( - title = { Text(stringResource(R.string.order_detail_title)) }, - navigationIcon = { - IconButton(onClick = onNavigateBack) { - Icon( - painter = painterResource(R.drawable.ic_arrow_back), - contentDescription = stringResource(R.string.nav_back) - ) - } - } + PullToRefreshBox( + isRefreshing = uiState.orderDetailLoading, + onRefresh = { viewModel.onEvent(OrderDetailUiEvent.LoadOrder) }, + state = pullRefreshState, + modifier = Modifier.fillMaxSize(), + indicator = { + Indicator( + modifier = Modifier.align(Alignment.TopCenter), + isRefreshing = uiState.orderDetailLoading, + containerColor = MaterialTheme.colorScheme.primaryContainer, + color = MaterialTheme.colorScheme.onPrimaryContainer, + state = pullRefreshState ) - }, - bottomBar = { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp) - ) { - CommonButton( - modifier = Modifier.weight(1f), - variant = ButtonVariant.Error, - enabled = uiState.orderDetail.firstOrNull()?.status != OrderStatus.COMPLETED && - uiState.orderDetail.firstOrNull()?.status != OrderStatus.CANCELED, - onClick = { showCancelOrderDialog = true } - ) { - Text(stringResource(R.string.order_detail_order_cancel)) - } - Spacer(Modifier.width(16.dp)) - CommonButton( - modifier = Modifier.weight(1f), - enabled = uiState.orderDetail.firstOrNull()?.status != OrderStatus.COMPLETED && - uiState.orderDetail.firstOrNull()?.status != OrderStatus.CANCELED, - onClick = { showReceiveOrderDialog = true } - ) { - Text(stringResource(R.string.order_detail_order_receive)) - } - } } - ) { innerPadding -> - when { - uiState.orderDetailLoading -> { - Box( + ) { + Scaffold( + topBar = { + TopAppBar( + title = { Text(stringResource(R.string.order_detail_title)) }, + navigationIcon = { + IconButton(onClick = onNavigateBack) { + Icon( + painter = painterResource(R.drawable.ic_arrow_back), + contentDescription = stringResource(R.string.nav_back) + ) + } + } + ) + }, + bottomBar = { + val orderStatus = uiState.orderDetail.firstOrNull()?.status + Row( modifier = Modifier .fillMaxWidth() - .height(200.dp), - contentAlignment = Alignment.Center + .padding(16.dp) ) { - CircularProgressIndicator() + CommonButton( + modifier = Modifier.weight(1f), + variant = ButtonVariant.Error, + enabled = orderStatus != null && + !uiState.isProcessing && + orderStatus == OrderStatus.PENDING, + onClick = { showCancelOrderDialog = true } + ) { + Text(stringResource(R.string.order_detail_order_cancel)) + } + Spacer(Modifier.width(16.dp)) + CommonButton( + modifier = Modifier.weight(1f), + enabled = orderStatus != null && + !uiState.isProcessing && + orderStatus == OrderStatus.PENDING, + onClick = { showReceiveOrderDialog = true } + ) { + Text(stringResource(R.string.order_detail_order_receive)) + } } } + ) { innerPadding -> + when { + uiState.orderDetailLoading -> { + Box( + modifier = Modifier + .fillMaxWidth() + .height(200.dp), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } - uiState.orderDetailError != null -> { - ErrorContent( - onRetry = { viewModel.onEvent(OrderDetailUiEvent.RetryOrder) }, - modifier = Modifier - .height(200.dp) - .fillMaxWidth() - ) - } + uiState.orderDetailError != null -> { + ErrorContent( + onRetry = { viewModel.onEvent(OrderDetailUiEvent.RetryOrder) }, + modifier = Modifier + .height(200.dp) + .fillMaxWidth() + ) + } - uiState.orderDetail.isEmpty() -> { - EmptyContent( - message = stringResource(R.string.order_empty_list), - modifier = Modifier - .height(200.dp) - .fillMaxWidth() - ) - } + uiState.orderDetail.isEmpty() -> { + EmptyContent( + message = stringResource(R.string.order_empty_list), + modifier = Modifier + .height(200.dp) + .fillMaxWidth() + ) + } - else -> { - OrderDetailContent( - order = uiState.orderDetail, - modifier = Modifier.padding(innerPadding) - ) + else -> { + OrderDetailContent( + order = uiState.orderDetail, + modifier = Modifier.padding(innerPadding) + ) + } } } } diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt index f13f0e6..6125a00 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt @@ -1,8 +1,11 @@ package com.sampoom.android.feature.order.ui +import android.os.Build +import androidx.annotation.RequiresApi import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -13,11 +16,15 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.items +import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text +import androidx.compose.material3.pulltorefresh.PullToRefreshBox +import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults.Indicator +import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -39,94 +46,115 @@ import com.sampoom.android.core.util.buildOrderTitle import com.sampoom.android.core.util.formatDate import com.sampoom.android.feature.order.domain.model.Order +@RequiresApi(Build.VERSION_CODES.O) +@OptIn(ExperimentalMaterialApi::class) @Composable fun OrderListScreen( + paddingValues: PaddingValues, onNavigateOrderDetail: (Order) -> Unit, viewModel: OrderListViewModel = hiltViewModel() ) { val errorLabel = stringResource(R.string.common_error) val uiState by viewModel.uiState.collectAsStateWithLifecycle() + val pullRefreshState = rememberPullToRefreshState() val listState = rememberSaveable(saver = LazyListState.Saver) { LazyListState() } LaunchedEffect(errorLabel) { viewModel.bindLabel(errorLabel) } - Column(Modifier.fillMaxSize()) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - modifier = Modifier - .padding(vertical = 16.dp), - text = stringResource(R.string.order_title), - style = MaterialTheme.typography.titleLarge, - color = textColor() + PullToRefreshBox( + isRefreshing = uiState.orderLoading, + onRefresh = { viewModel.onEvent(OrderListUiEvent.LoadOrderList) }, + state = pullRefreshState, + modifier = Modifier.fillMaxSize(), + indicator = { + Indicator( + modifier = Modifier.align(Alignment.TopCenter), + isRefreshing = uiState.orderLoading, + containerColor = MaterialTheme.colorScheme.primaryContainer, + color = MaterialTheme.colorScheme.onPrimaryContainer, + state = pullRefreshState ) } - - when { - uiState.orderLoading -> { - Box( + ) { + Column(Modifier.fillMaxSize().padding(paddingValues)) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( modifier = Modifier - .fillMaxSize(), - contentAlignment = Alignment.Center - ) { - CircularProgressIndicator() - } + .padding(vertical = 16.dp), + text = stringResource(R.string.order_title), + style = MaterialTheme.typography.titleLarge, + color = textColor() + ) } - uiState.orderError != null -> { - Box( - modifier = Modifier - .fillMaxSize(), - contentAlignment = Alignment.Center - ) { - ErrorContent( - onRetry = { viewModel.onEvent(OrderListUiEvent.RetryOrderList) }, - modifier = Modifier.height(200.dp) - ) + when { + uiState.orderLoading -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } } - } - uiState.orderList.isEmpty() -> { - Box( - modifier = Modifier - .fillMaxSize(), - contentAlignment = Alignment.Center - ) { - EmptyContent( - message = stringResource(R.string.order_empty_list), - modifier = Modifier.height(200.dp) - ) + uiState.orderError != null -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + ErrorContent( + onRetry = { viewModel.onEvent(OrderListUiEvent.RetryOrderList) }, + modifier = Modifier.height(200.dp) + ) + } } - } - else -> { - LazyColumn( - state = listState, - modifier = Modifier - .fillMaxSize() - .padding(horizontal = 16.dp), - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - items(uiState.orderList) { order -> - OrderItem( - order = order, - onClick = { onNavigateOrderDetail(order) } + uiState.orderList.isEmpty() -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + EmptyContent( + message = stringResource(R.string.order_empty_list), + modifier = Modifier.height(200.dp) ) } - item { Spacer(Modifier.height(100.dp)) } + } + + else -> { + LazyColumn( + state = listState, + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + items(uiState.orderList) { order -> + OrderItem( + order = order, + onClick = { onNavigateOrderDetail(order) } + ) + } + item { Spacer(Modifier.height(100.dp)) } + } } } } } } +@RequiresApi(Build.VERSION_CODES.O) @Composable private fun OrderItem( order: Order, diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt index a2bfa67..4060fc4 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt @@ -9,6 +9,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt index abd4407..e859080 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt @@ -105,12 +105,13 @@ fun OrderResultBottomSheet( .fillMaxWidth() .padding(16.dp) ) { + val orderStatus = order.firstOrNull()?.status CommonButton( modifier = Modifier.weight(1f), variant = ButtonVariant.Error, - enabled = order.firstOrNull()?.let { - it.status != OrderStatus.COMPLETED && it.status != OrderStatus.CANCELED - } ?: false, + enabled = orderStatus != null && + !uiState.isProcessing && + orderStatus == OrderStatus.PENDING, onClick = { showCancelOrderDialog = true } ) { Text(stringResource(R.string.order_detail_order_cancel)) diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt index a2501d2..21c1664 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt @@ -4,6 +4,7 @@ import android.widget.Toast import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -21,6 +22,9 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextButton +import androidx.compose.material3.pulltorefresh.PullToRefreshBox +import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults.Indicator +import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -45,15 +49,18 @@ import com.sampoom.android.core.ui.theme.FailRed import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.feature.order.ui.OrderListUiEvent import com.sampoom.android.feature.outbound.domain.model.OutboundPart @OptIn(ExperimentalMaterial3Api::class) @Composable fun OutboundListScreen( + paddingValues: PaddingValues, viewModel: OutboundListViewModel = hiltViewModel() ) { val errorLabel = stringResource(R.string.common_error) val uiState by viewModel.uiState.collectAsStateWithLifecycle() + val pullRefreshState = rememberPullToRefreshState() var showEmptyOutboundDialog by remember { mutableStateOf(false) } var showConfirmDialog by remember { mutableStateOf(false) } val context = LocalContext.current @@ -73,113 +80,128 @@ fun OutboundListScreen( viewModel.clearSuccess() } } - - Column(Modifier.fillMaxSize()) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - modifier = Modifier - .padding(vertical = 16.dp), - text = stringResource(R.string.outbound_title), - style = MaterialTheme.typography.titleLarge, - color = textColor() + PullToRefreshBox( + isRefreshing = uiState.outboundLoading, + onRefresh = { viewModel.onEvent(OutboundListUiEvent.LoadOutboundList) }, + state = pullRefreshState, + modifier = Modifier.fillMaxSize(), + indicator = { + Indicator( + modifier = Modifier.align(Alignment.TopCenter), + isRefreshing = uiState.outboundLoading, + containerColor = MaterialTheme.colorScheme.primaryContainer, + color = MaterialTheme.colorScheme.onPrimaryContainer, + state = pullRefreshState ) - - when { - uiState.outboundLoading -> {} - uiState.outboundError != null -> {} - uiState.outboundList.isEmpty() -> {} - else -> { - TextButton( - onClick = { showEmptyOutboundDialog = true } - ) { - Text( - text = stringResource(R.string.outbound_empty_list), - style = MaterialTheme.typography.titleMedium, - color = FailRed - ) - } - } - } } - - when { - uiState.outboundLoading -> { - Box( + ) { + Column(Modifier.fillMaxSize().padding(paddingValues)) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( modifier = Modifier - .fillMaxSize(), - contentAlignment = Alignment.Center - ) { - CircularProgressIndicator() + .padding(vertical = 16.dp), + text = stringResource(R.string.outbound_title), + style = MaterialTheme.typography.titleLarge, + color = textColor() + ) + + when { + uiState.outboundLoading -> {} + uiState.outboundError != null -> {} + uiState.outboundList.isEmpty() -> {} + else -> { + TextButton( + onClick = { showEmptyOutboundDialog = true } + ) { + Text( + text = stringResource(R.string.outbound_empty_list), + style = MaterialTheme.typography.titleMedium, + color = FailRed + ) + } + } } } - uiState.outboundError != null -> { - Box( - modifier = Modifier - .fillMaxSize(), - contentAlignment = Alignment.Center - ) { - ErrorContent( - onRetry = { viewModel.onEvent(OutboundListUiEvent.RetryOutboundList) }, - modifier = Modifier.height(200.dp) - ) + when { + uiState.outboundLoading -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } } - } - uiState.outboundList.isEmpty() -> { - Box( - modifier = Modifier - .fillMaxSize(), - contentAlignment = Alignment.Center - ) { - EmptyContent( - message = stringResource(R.string.outbound_empty_outbound), - modifier = Modifier.height(200.dp) - ) + uiState.outboundError != null -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + ErrorContent( + onRetry = { viewModel.onEvent(OutboundListUiEvent.RetryOutboundList) }, + modifier = Modifier.height(200.dp) + ) + } } - } - else -> { - Box(modifier = Modifier.fillMaxSize()) { - LazyColumn( + uiState.outboundList.isEmpty() -> { + Box( modifier = Modifier - .fillMaxSize() - .padding(horizontal = 16.dp), - verticalArrangement = Arrangement.spacedBy(16.dp) + .fillMaxSize(), + contentAlignment = Alignment.Center ) { - uiState.outboundList.forEach { category -> - category.groups.forEach { group -> - item { - OutboundSection( - categoryName = category.categoryName, - groupName = group.groupName, - parts = group.parts, - isUpdating = uiState.isUpdating, - isDeleting = uiState.isDeleting, - onEvent = { viewModel.onEvent(it) } - ) + EmptyContent( + message = stringResource(R.string.outbound_empty_outbound), + modifier = Modifier.height(200.dp) + ) + } + } + + else -> { + Box(modifier = Modifier.fillMaxSize()) { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + uiState.outboundList.forEach { category -> + category.groups.forEach { group -> + item { + OutboundSection( + categoryName = category.categoryName, + groupName = group.groupName, + parts = group.parts, + isUpdating = uiState.isUpdating, + isDeleting = uiState.isDeleting, + onEvent = { viewModel.onEvent(it) } + ) + } } } + item { Spacer(Modifier.height(100.dp)) } } - item { Spacer(Modifier.height(100.dp)) } - } - CommonButton( - modifier = Modifier - .fillMaxWidth() - .align(Alignment.BottomEnd) - .padding(16.dp) - .padding(end = 72.dp), - variant = ButtonVariant.Error, - size = ButtonSize.Large, - onClick = { showConfirmDialog = true } - ) { Text(stringResource(R.string.outbound_order_parts)) } + CommonButton( + modifier = Modifier + .fillMaxWidth() + .align(Alignment.BottomEnd) + .padding(16.dp) + .padding(end = 72.dp), + variant = ButtonVariant.Error, + size = ButtonSize.Large, + onClick = { showConfirmDialog = true } + ) { Text(stringResource(R.string.outbound_order_parts)) } + } } } } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt index 8aa2fae..161c8d9 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt @@ -22,6 +22,9 @@ import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar +import androidx.compose.material3.pulltorefresh.PullToRefreshBox +import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults.Indicator +import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -44,6 +47,7 @@ import com.sampoom.android.core.ui.component.ErrorContent import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.feature.outbound.ui.OutboundListUiEvent import com.sampoom.android.feature.part.domain.model.Part @OptIn(ExperimentalMaterial3Api::class) @@ -59,82 +63,98 @@ fun PartListScreen( } val uiState by viewModel.uiState.collectAsStateWithLifecycle() + val pullRefreshState = rememberPullToRefreshState() // ModalBottomSheet 상태 관리 val sheetState = rememberModalBottomSheetState() - val scope = rememberCoroutineScope() var showBottomSheet by remember { mutableStateOf(false) } - Scaffold( - topBar = { - TopAppBar( - title = { Text(stringResource(R.string.part_title)) }, - navigationIcon = { - IconButton(onClick = onNavigateBack) { - Icon( - painter = painterResource(R.drawable.ic_arrow_back), - contentDescription = stringResource(R.string.nav_back) - ) - } - } + PullToRefreshBox( + isRefreshing = uiState.partListLoading, + onRefresh = { viewModel.onEvent(PartListUiEvent.LoadPartList) }, + state = pullRefreshState, + modifier = Modifier.fillMaxSize(), + indicator = { + Indicator( + modifier = Modifier.align(Alignment.TopCenter), + isRefreshing = uiState.partListLoading, + containerColor = MaterialTheme.colorScheme.primaryContainer, + color = MaterialTheme.colorScheme.onPrimaryContainer, + state = pullRefreshState ) } - ) { innerPadding -> - when { - uiState.partListLoading -> { - Box( - modifier = Modifier - .fillMaxSize(), - contentAlignment = Alignment.Center - ) { - CircularProgressIndicator() - } + ) { + Scaffold( + topBar = { + TopAppBar( + title = { Text(stringResource(R.string.part_title)) }, + navigationIcon = { + IconButton(onClick = onNavigateBack) { + Icon( + painter = painterResource(R.drawable.ic_arrow_back), + contentDescription = stringResource(R.string.nav_back) + ) + } + } + ) } - - uiState.partListError != null -> { - Box( - modifier = Modifier - .fillMaxSize(), - contentAlignment = Alignment.Center - ) { - ErrorContent( - onRetry = { viewModel.onEvent(PartListUiEvent.RetryPartList) }, - modifier = Modifier.height(200.dp) - ) + ) { innerPadding -> + when { + uiState.partListLoading -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } } - } - uiState.partList.isEmpty() -> { - Box( - modifier = Modifier - .fillMaxSize(), - contentAlignment = Alignment.Center - ) { - EmptyContent( - message = stringResource(R.string.part_empty_part), - modifier = Modifier.height(200.dp) - ) + uiState.partListError != null -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + ErrorContent( + onRetry = { viewModel.onEvent(PartListUiEvent.RetryPartList) }, + modifier = Modifier.height(200.dp) + ) + } } - } - else -> { - LazyColumn( - modifier = Modifier - .fillMaxSize() - .padding(innerPadding), - contentPadding = PaddingValues(16.dp), - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - items(uiState.partList) { part -> - PartListItemCard( - part = part, - onClick = { - viewModel.onEvent(PartListUiEvent.ShowBottomSheet(part)) - showBottomSheet = true - } + uiState.partList.isEmpty() -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + EmptyContent( + message = stringResource(R.string.part_empty_part), + modifier = Modifier.height(200.dp) ) } } + + else -> { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(innerPadding), + contentPadding = PaddingValues(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + items(uiState.partList) { part -> + PartListItemCard( + part = part, + onClick = { + viewModel.onEvent(PartListUiEvent.ShowBottomSheet(part)) + showBottomSheet = true + } + ) + } + } + } } } } From 81b543f0210cfe0199803b27b37fc1b0e3455ba6 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Wed, 22 Oct 2025 09:43:55 +0900 Subject: [PATCH 46/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/sampoom/android/core/util/FormatDate.kt | 5 +++-- .../sampoom/android/feature/order/ui/OrderListViewModel.kt | 2 -- .../com/sampoom/android/feature/part/ui/PartListScreen.kt | 6 +++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt b/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt index 425a09b..5835cde 100644 --- a/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt +++ b/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt @@ -9,8 +9,9 @@ fun formatDate(dateString: String): String { return runCatching { val out = DateTimeFormatter.ISO_LOCAL_DATE val hasOffset = - dateString.endsWith("Z") || dateString.contains('+') || dateString.contains('-') - .and(dateString.count { it == ':' } >= 3) + dateString.contains("Z") || dateString.lastIndexOf('+') > dateString.indexOf('T') || (dateString.lastIndexOf( + '-' + ) > dateString.indexOf('T') && dateString.count { it == ':' } >= 3) val date = if (hasOffset) { val inFmt = DateTimeFormatter.ISO_OFFSET_DATE_TIME java.time.OffsetDateTime.parse(dateString, inFmt).toLocalDate() diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt index 4060fc4..0a4fab1 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt @@ -9,13 +9,11 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job -import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import okhttp3.Dispatcher import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt index 161c8d9..b32c2cb 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt @@ -103,7 +103,7 @@ fun PartListScreen( uiState.partListLoading -> { Box( modifier = Modifier - .fillMaxSize(), + .fillMaxSize().padding(innerPadding), contentAlignment = Alignment.Center ) { CircularProgressIndicator() @@ -113,7 +113,7 @@ fun PartListScreen( uiState.partListError != null -> { Box( modifier = Modifier - .fillMaxSize(), + .fillMaxSize().padding(innerPadding), contentAlignment = Alignment.Center ) { ErrorContent( @@ -126,7 +126,7 @@ fun PartListScreen( uiState.partList.isEmpty() -> { Box( modifier = Modifier - .fillMaxSize(), + .fillMaxSize().padding(innerPadding), contentAlignment = Alignment.Center ) { EmptyContent( From 39c473661f73f93a83212bfb137eee64599e6c92 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Wed, 22 Oct 2025 09:50:17 +0900 Subject: [PATCH 47/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/sampoom/android/core/util/FormatDate.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt b/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt index 5835cde..7684ba3 100644 --- a/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt +++ b/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt @@ -9,9 +9,9 @@ fun formatDate(dateString: String): String { return runCatching { val out = DateTimeFormatter.ISO_LOCAL_DATE val hasOffset = - dateString.contains("Z") || dateString.lastIndexOf('+') > dateString.indexOf('T') || (dateString.lastIndexOf( - '-' - ) > dateString.indexOf('T') && dateString.count { it == ':' } >= 3) + dateString.contains("Z") || (dateString.contains('T') && (dateString.lastIndexOf('+') > dateString.indexOf( + 'T' + ) || (dateString.lastIndexOf('-') > dateString.indexOf('T') && dateString.count { it == ':' } >= 3))) val date = if (hasOffset) { val inFmt = DateTimeFormatter.ISO_OFFSET_DATE_TIME java.time.OffsetDateTime.parse(dateString, inFmt).toLocalDate() From de5068ce19b58eea43fb9ab8782caf5a93561444 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Wed, 22 Oct 2025 18:37:28 +0900 Subject: [PATCH 48/88] =?UTF-8?q?[FEAT]=20=EA=B2=80=EC=83=89=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/AppNavHost.kt | 1 + .../feature/part/data/mapper/PartMappers.kt | 9 +- .../feature/part/data/remote/api/PartApi.kt | 9 + .../part/data/remote/dto/SearchDataDto.kt | 20 ++ .../data/repository/PartRepositoryImpl.kt | 16 + .../feature/part/domain/model/SearchResult.kt | 20 ++ .../part/domain/repository/PartRepository.kt | 2 + .../part/domain/usecase/SearchPartsUseCase.kt | 13 + .../android/feature/part/ui/PartScreen.kt | 287 +++++++++++++++--- .../android/feature/part/ui/PartUiEvent.kt | 3 + .../android/feature/part/ui/PartUiState.kt | 9 +- .../android/feature/part/ui/PartViewModel.kt | 35 ++- app/src/main/res/values/strings.xml | 1 + 13 files changed, 377 insertions(+), 48 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/SearchDataDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/domain/model/SearchResult.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/part/domain/usecase/SearchPartsUseCase.kt diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 94d0f63..7ad8397 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -48,6 +48,7 @@ const val ROUTE_PART_LIST = "parts/{agencyId}/group/{groupId}" fun routePartList(agencyId: Long, groupId: Long): String = "parts/$agencyId/group/$groupId" const val ROUTE_ORDER_DETAIL = "orders/{agencyId}/orders/{orderId}" fun routeOrderDetail(agencyId: Long, orderId: Long): String = "orders/$agencyId/orders/$orderId" +const val ROUTE_SEARCH = "search" const val ROUTE_EMPLOYEE = "employee" const val ROUTE_SETTINGS = "settings" diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt b/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt index 65800a6..2d1f75c 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt @@ -3,10 +3,17 @@ package com.sampoom.android.feature.part.data.mapper import com.sampoom.android.feature.part.data.remote.dto.CategoryDto import com.sampoom.android.feature.part.data.remote.dto.GroupDto import com.sampoom.android.feature.part.data.remote.dto.PartDto +import com.sampoom.android.feature.part.data.remote.dto.SearchCategoryDto +import com.sampoom.android.feature.part.data.remote.dto.SearchGroupDto import com.sampoom.android.feature.part.domain.model.Category import com.sampoom.android.feature.part.domain.model.Group import com.sampoom.android.feature.part.domain.model.Part +import com.sampoom.android.feature.part.domain.model.SearchCategory +import com.sampoom.android.feature.part.domain.model.SearchGroup fun CategoryDto.toModel(): Category = Category(id, code, name) fun GroupDto.toModel(): Group = Group(id, code, name, categoryId) -fun PartDto.toModel(): Part = Part(partId, code, name, quantity) \ No newline at end of file +fun PartDto.toModel(): Part = Part(partId, code, name, quantity) + +fun SearchCategoryDto.toModel(): SearchCategory = SearchCategory(categoryId, categoryName, groups.map { it.toModel() }) +fun SearchGroupDto.toModel(): SearchGroup = SearchGroup(groupId, groupName, parts.map { it.toModel() }) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt b/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt index eaea882..a7aa4d5 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt @@ -4,8 +4,10 @@ import com.sampoom.android.core.network.ApiResponse import com.sampoom.android.feature.part.data.remote.dto.CategoryDto import com.sampoom.android.feature.part.data.remote.dto.GroupDto import com.sampoom.android.feature.part.data.remote.dto.PartDto +import com.sampoom.android.feature.part.data.remote.dto.SearchDataDto import retrofit2.http.GET import retrofit2.http.Path +import retrofit2.http.Query // TODO: AgencyId 동적 주입 interface PartApi { @@ -17,4 +19,11 @@ interface PartApi { @GET("agency/1/group/{groupId}") suspend fun getPartList(@Path("groupId") groupId: Long): ApiResponse> + + @GET("agency/1/search") + suspend fun searchParts( + @Query("keyword") keyword: String, + @Query("page") page: Int = 0, + @Query("size") size: Int = 10 + ): ApiResponse } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/SearchDataDto.kt b/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/SearchDataDto.kt new file mode 100644 index 0000000..5f29d7e --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/SearchDataDto.kt @@ -0,0 +1,20 @@ +package com.sampoom.android.feature.part.data.remote.dto + +data class SearchDataDto( + val content: List, + val totalElements: Int, + val totalPages: Int, + val currentPage: Int +) + +data class SearchCategoryDto( + val categoryId: Long, + val categoryName: String, + val groups: List +) + +data class SearchGroupDto( + val groupId: Long, + val groupName: String, + val parts: List +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt index f40c510..c205359 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt @@ -5,7 +5,9 @@ import com.sampoom.android.feature.part.data.remote.api.PartApi import com.sampoom.android.feature.part.domain.model.CategoryList import com.sampoom.android.feature.part.domain.model.GroupList import com.sampoom.android.feature.part.domain.model.PartList +import com.sampoom.android.feature.part.domain.model.SearchResult import com.sampoom.android.feature.part.domain.repository.PartRepository +import kotlinx.coroutines.CancellationException import javax.inject.Inject class PartRepositoryImpl @Inject constructor( @@ -28,4 +30,18 @@ class PartRepositoryImpl @Inject constructor( val partItems = response.data.map { it.toModel() } return PartList(items = partItems) } + + override suspend fun searchParts( + keyword: String, + page: Int, + size: Int + ): SearchResult { + val response = api.searchParts(keyword, page, size) + val searchItems = response.data.content.map { it.toModel() } + val totalElements = response.data.totalElements + val totalPages = response.data.totalPages + val currentPage = response.data.currentPage + + return SearchResult(searchItems, totalElements, totalPages, currentPage) + } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/model/SearchResult.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/model/SearchResult.kt new file mode 100644 index 0000000..fa37597 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/model/SearchResult.kt @@ -0,0 +1,20 @@ +package com.sampoom.android.feature.part.domain.model + +data class SearchResult( + val content: List, + val totalElements: Int, + val totalPages: Int, + val currentPage: Int +) + +data class SearchCategory( + val categoryId: Long, + val categoryName: String, + val groups: List +) + +data class SearchGroup( + val groupId: Long, + val groupName: String, + val parts: List +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt index 3d761e0..41b490f 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt @@ -3,9 +3,11 @@ package com.sampoom.android.feature.part.domain.repository import com.sampoom.android.feature.part.domain.model.CategoryList import com.sampoom.android.feature.part.domain.model.GroupList import com.sampoom.android.feature.part.domain.model.PartList +import com.sampoom.android.feature.part.domain.model.SearchResult interface PartRepository { suspend fun getCategoryList(): CategoryList suspend fun getGroupList(categoryId: Long): GroupList suspend fun getPartList(groupId: Long): PartList + suspend fun searchParts(keyword: String, page: Int = 0, size: Int = 10): SearchResult } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/SearchPartsUseCase.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/SearchPartsUseCase.kt new file mode 100644 index 0000000..f9b6c4f --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/SearchPartsUseCase.kt @@ -0,0 +1,13 @@ +package com.sampoom.android.feature.part.domain.usecase + +import com.sampoom.android.feature.part.domain.model.SearchResult +import com.sampoom.android.feature.part.domain.repository.PartRepository +import javax.inject.Inject + +class SearchPartsUseCase @Inject constructor( + private val repository: PartRepository +) { + suspend operator fun invoke(keyword: String, page: Int = 0, size: Int = 20): SearchResult { + return repository.searchParts(keyword, page, size) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index 3585da3..555f1c2 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -1,6 +1,9 @@ package com.sampoom.android.feature.part.ui +import android.R.attr.fontWeight +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll @@ -8,32 +11,47 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Search import androidx.compose.material3.* import androidx.compose.runtime.* +import androidx.compose.runtime.getValue +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.isTraversalGroup +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.traversalIndex import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.viewmodel.compose.viewModel import com.sampoom.android.R import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent import com.sampoom.android.core.ui.theme.Main500 import com.sampoom.android.core.ui.theme.White import com.sampoom.android.core.ui.theme.backgroundCardColor +import com.sampoom.android.core.ui.theme.backgroundColor +import com.sampoom.android.core.ui.theme.disableColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.part.domain.model.Category import com.sampoom.android.feature.part.domain.model.Group +import com.sampoom.android.feature.part.domain.model.Part +import com.sampoom.android.feature.part.domain.model.SearchResult +import kotlin.collections.forEach @OptIn(ExperimentalMaterial3Api::class) @Composable fun PartScreen( onNavigateBack: () -> Unit = {}, onNavigatePartList: (Group) -> Unit, - viewModel: PartViewModel = hiltViewModel() + viewModel: PartViewModel = hiltViewModel(), + searchViewModel: PartListViewModel = hiltViewModel() ) { val errorLabel = stringResource(R.string.common_error) @@ -42,60 +60,116 @@ fun PartScreen( } val uiState by viewModel.uiState.collectAsStateWithLifecycle() + val searchUiState by searchViewModel.uiState.collectAsStateWithLifecycle() + var textFieldState by remember { mutableStateOf(TextFieldValue("")) } + var expanded by rememberSaveable { mutableStateOf(false) } - Scaffold( - topBar = { - TopAppBar( - title = { Text(stringResource(R.string.part_title)) }, - navigationIcon = { - IconButton(onClick = onNavigateBack) { - Icon( - painter = painterResource(R.drawable.ic_arrow_back), - contentDescription = stringResource(R.string.nav_back) + // ModalBottomSheet 상태 관리 + val sheetState = rememberModalBottomSheetState() + var showBottomSheet by remember { mutableStateOf(false) } + + Box( + modifier = Modifier.fillMaxSize().background(backgroundColor()) + ) { + SearchBar( + modifier = Modifier.align(Alignment.TopCenter), + inputField = { + SearchBarDefaults.InputField( + query = textFieldState.text, + onQueryChange = { + textFieldState = textFieldState.copy(it) + }, + onSearch = { + viewModel.onEvent(PartUiEvent.Search(textFieldState.text)) +// expanded = false + }, + expanded = expanded, + onExpandedChange = { expanded = it }, + placeholder = { Text(stringResource(R.string.part_title_search)) }, + leadingIcon = { + if (expanded) { + IconButton(onClick = { expanded = false }) { + Icon( + painter = painterResource(R.drawable.ic_arrow_back), + contentDescription = stringResource(R.string.nav_back) + ) + } + } else { + IconButton(onClick = { onNavigateBack() }) { + Icon( + painter = painterResource(R.drawable.ic_arrow_back), + contentDescription = stringResource(R.string.nav_back) + ) + } + } + }, + colors = OutlinedTextFieldDefaults.colors( + focusedContainerColor = backgroundColor(), + unfocusedContainerColor = backgroundCardColor(), + focusedBorderColor = Color.Transparent, + unfocusedBorderColor = textSecondaryColor().copy(0.3f) + ) + ) + }, + expanded = expanded, + onExpandedChange = { expanded = it }, + colors = SearchBarDefaults.colors( + containerColor = backgroundColor() + ) + ) { + when { + uiState.isLoading -> { + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + + uiState.error != null -> { + ErrorContent( + onRetry = { viewModel.onEvent(PartUiEvent.Search(textFieldState.text)) }, + modifier = Modifier.fillMaxWidth() + ) + } + + uiState.searchResults?.content?.isEmpty() == true -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + EmptyContent( + message = stringResource(R.string.part_search_empty) ) } } - ) + + else -> { + SearchResultsList( + searchResults = uiState.searchResults, + onPartClick = { part -> + searchViewModel.onEvent(PartListUiEvent.ShowBottomSheet(part)) + showBottomSheet = true + } + ) + } + } } - ) { innerPadding -> Column( modifier = Modifier .fillMaxSize() - .padding(innerPadding) .padding(horizontal = 16.dp) .verticalScroll(rememberScrollState()) ) { - Spacer(Modifier.height(16.dp)) - - // 검색 바 - OutlinedTextField( - value = "uiState.searchQuery", - onValueChange = { "viewModel.onSearchQueryChanged(it)" }, - placeholder = { Text(stringResource(R.string.part_placeholder_search)) }, - trailingIcon = { - Icon( - Icons.Default.Search, - contentDescription = stringResource(R.string.part_title_search), - tint = MaterialTheme.colorScheme.onSurfaceVariant - ) - }, - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 8.dp), - shape = RoundedCornerShape(24.dp), - singleLine = true, - colors = OutlinedTextFieldDefaults.colors( - focusedBorderColor = Color.Transparent, - unfocusedBorderColor = Color.Transparent, - focusedContainerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f), - unfocusedContainerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f), - ) - ) + Spacer(Modifier.height(100.dp)) // Category 선택 제목 Text( text = stringResource(R.string.part_title_category), style = MaterialTheme.typography.titleMedium, + color = textColor(), fontWeight = FontWeight.Bold, modifier = Modifier.padding(vertical = 16.dp) ) @@ -116,14 +190,18 @@ fun PartScreen( uiState.categoryError != null -> { ErrorContent( onRetry = { viewModel.onEvent(PartUiEvent.RetryCategories) }, - modifier = Modifier.height(200.dp).fillMaxWidth() + modifier = Modifier + .height(200.dp) + .fillMaxWidth() ) } uiState.categoryList.isEmpty() -> { EmptyContent( message = stringResource(R.string.part_empty_category), - modifier = Modifier.height(200.dp).fillMaxWidth() + modifier = Modifier + .height(200.dp) + .fillMaxWidth() ) } @@ -193,6 +271,7 @@ fun PartScreen( Text( text = stringResource(R.string.part_title_group), style = MaterialTheme.typography.titleMedium, + color = textColor(), fontWeight = FontWeight.Bold, modifier = Modifier.padding(vertical = 16.dp) ) @@ -230,7 +309,8 @@ fun PartScreen( uiState.groupList.forEach { group -> PartItemCard( group = group, - onClick = { onNavigatePartList(group) } + onClick = { + onNavigatePartList(group) } ) } } @@ -238,7 +318,27 @@ fun PartScreen( } } - Spacer(Modifier.height(32.dp)) + Spacer(Modifier.height(100.dp)) + } + } + + if (showBottomSheet) { + searchUiState.selectedPart?.let { selectedPart -> + ModalBottomSheet( + onDismissRequest = { + showBottomSheet = false + searchViewModel.onEvent(PartListUiEvent.DismissBottomSheet) + }, + sheetState = sheetState + ) { + PartDetailBottomSheet( + part = selectedPart, + onDismiss = { + showBottomSheet = false + searchViewModel.onEvent(PartListUiEvent.DismissBottomSheet) + } + ) + } } } } @@ -311,12 +411,109 @@ private fun PartItemCard( ) { Text( text = group.name, - style = MaterialTheme.typography.titleMedium + style = MaterialTheme.typography.titleMedium, + color = textColor() ) Icon( painterResource(R.drawable.chevron_right), - contentDescription = stringResource(R.string.common_detail) + contentDescription = stringResource(R.string.common_detail), + tint = disableColor() + ) + } + } +} + +@Composable +fun SearchResultsList( + searchResults: SearchResult?, + onPartClick: (Part) -> Unit +) { + LazyColumn( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.spacedBy(16.dp), + contentPadding = PaddingValues(16.dp) + ) { + searchResults?.content?.forEach { category -> + category.groups.forEach { group -> + item { + SearchSection( + categoryName = category.categoryName, + groupName = group.groupName, + parts = group.parts, + onPartClick = onPartClick + ) + } + } + } + } +} + +@Composable +private fun SearchSection( + categoryName: String, + groupName: String, + parts: List, + onPartClick: (Part) -> Unit +) { + Column( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + text = "$categoryName > $groupName", + style = MaterialTheme.typography.titleMedium, + color = textColor() + ) + + parts.forEach { part -> + SearchPartItem( + part = part, + onClick = { onPartClick(part) } + ) + } + } +} + +@Composable +private fun SearchPartItem( + part: Part, + onClick: () -> Unit +) { + Card( + onClick = { onClick() }, + modifier = Modifier + .fillMaxWidth(), + colors = CardDefaults.cardColors( + containerColor = backgroundCardColor() + ) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier.weight(1f) + ) { + Text( + text = part.name, + style = MaterialTheme.typography.titleMedium, + color = textColor() + ) + + Text( + text = part.code, + style = MaterialTheme.typography.bodySmall, + color = textSecondaryColor() + ) + } + + Text( + text = "${part.quantity}개", + style = MaterialTheme.typography.bodyMedium, + color = textColor() ) } } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiEvent.kt index 7dbf889..50836ce 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiEvent.kt @@ -7,4 +7,7 @@ sealed interface PartUiEvent { data class CategorySelected(val category: Category) : PartUiEvent object RetryCategories : PartUiEvent object RetryGroups : PartUiEvent + data class Search(val keyword: String) : PartUiEvent + data class SetKeyword(val keyword: String) : PartUiEvent + object ClearError : PartUiEvent } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt index f43a4f6..9ca3ade 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt @@ -2,6 +2,7 @@ package com.sampoom.android.feature.part.ui import com.sampoom.android.feature.part.domain.model.Category import com.sampoom.android.feature.part.domain.model.Group +import com.sampoom.android.feature.part.domain.model.SearchResult data class PartUiState( // Part @@ -15,5 +16,11 @@ data class PartUiState( // Category val categoryList: List = emptyList(), val categoryLoading: Boolean = false, - val categoryError: String? = null + val categoryError: String? = null, + + // Search + val searchResults: SearchResult? = null, + val isLoading: Boolean = false, + val error: String? = null, + val keyword: String = "" ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt index bb8e0c8..75c858a 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt @@ -7,6 +7,7 @@ import com.sampoom.android.core.network.serverMessageOrNull import com.sampoom.android.feature.part.domain.model.Category import com.sampoom.android.feature.part.domain.usecase.GetCategoryUseCase import com.sampoom.android.feature.part.domain.usecase.GetGroupUseCase +import com.sampoom.android.feature.part.domain.usecase.SearchPartsUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Job @@ -19,7 +20,8 @@ import javax.inject.Inject @HiltViewModel class PartViewModel @Inject constructor( private val getCategoryUseCase: GetCategoryUseCase, - private val getGroupUseCase: GetGroupUseCase + private val getGroupUseCase: GetGroupUseCase, + private val searchPartsUseCase: SearchPartsUseCase ) : ViewModel() { private companion object { @@ -46,6 +48,9 @@ class PartViewModel @Inject constructor( is PartUiEvent.CategorySelected -> selectCategory(event.category) is PartUiEvent.RetryCategories -> loadCategory() is PartUiEvent.RetryGroups -> loadGroup() + is PartUiEvent.Search -> searchParts(event.keyword) + is PartUiEvent.SetKeyword -> _uiState.update { it.copy(keyword = event.keyword) } + is PartUiEvent.ClearError -> _uiState.update { it.copy(error = null) } } } @@ -123,4 +128,32 @@ class PartViewModel @Inject constructor( loadGroup(selectedCategory.id) } } + + private fun searchParts(keyword: String) { + viewModelScope.launch { + if (keyword.isBlank()) return@launch + + _uiState.update { it.copy(isLoading = true, error = null) } + + try { + val searchResult = searchPartsUseCase(keyword) + _uiState.update { + it.copy( + searchResults = searchResult, + isLoading = false + ) + } + } catch (ce: kotlin.coroutines.cancellation.CancellationException) { + throw ce + } catch (throwable: Throwable) { + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + isLoading = false, + error = backendMessage ?: (throwable.message ?: errorLabel) + ) + } + } + } + } } \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1956094..337f1b5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -47,6 +47,7 @@ 부품 목록이 없습니다. 카테고리를 선택해주세요. 그룹 목록이 없습니다. + 검색 결과가 없습니다. 현재 재고 : From c6dce5674228ed08cb9585ff21bfc1ac42c23cee Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Thu, 23 Oct 2025 19:46:22 +0900 Subject: [PATCH 49/88] =?UTF-8?q?[FEAT]=20=EA=B2=80=EC=83=89=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=20=ED=8E=98=EC=9D=B4=EC=A7=95=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 3 + .../feature/part/data/mapper/PartMappers.kt | 24 +++-- .../part/data/paging/PartPagingSource.kt | 38 ++++++++ .../data/repository/PartRepositoryImpl.kt | 23 +++-- .../feature/part/domain/model/SearchResult.kt | 17 +--- .../part/domain/repository/PartRepository.kt | 4 +- .../part/domain/usecase/SearchPartsUseCase.kt | 6 +- .../android/feature/part/ui/PartListScreen.kt | 3 +- .../android/feature/part/ui/PartScreen.kt | 88 +++++++++---------- .../android/feature/part/ui/PartUiState.kt | 2 +- .../android/feature/part/ui/PartViewModel.kt | 61 +++++++------ gradle/libs.versions.toml | 7 +- 12 files changed, 161 insertions(+), 115 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/feature/part/data/paging/PartPagingSource.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0ba8b70..e6c89f7 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -85,6 +85,9 @@ dependencies { // DataStore implementation(libs.androidx.datastore.preferences) + // Paging + implementation(libs.androidx.paging.runtime) + implementation(libs.androidx.paging.compose) implementation(libs.androidx.core.splashscreen) implementation(libs.androidx.material) implementation(libs.androidx.material.icons.core) diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt b/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt index 2d1f75c..998e90f 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt @@ -4,16 +4,30 @@ import com.sampoom.android.feature.part.data.remote.dto.CategoryDto import com.sampoom.android.feature.part.data.remote.dto.GroupDto import com.sampoom.android.feature.part.data.remote.dto.PartDto import com.sampoom.android.feature.part.data.remote.dto.SearchCategoryDto -import com.sampoom.android.feature.part.data.remote.dto.SearchGroupDto +import com.sampoom.android.feature.part.data.remote.dto.SearchDataDto import com.sampoom.android.feature.part.domain.model.Category import com.sampoom.android.feature.part.domain.model.Group import com.sampoom.android.feature.part.domain.model.Part -import com.sampoom.android.feature.part.domain.model.SearchCategory -import com.sampoom.android.feature.part.domain.model.SearchGroup +import com.sampoom.android.feature.part.domain.model.SearchResult fun CategoryDto.toModel(): Category = Category(id, code, name) fun GroupDto.toModel(): Group = Group(id, code, name, categoryId) fun PartDto.toModel(): Part = Part(partId, code, name, quantity) -fun SearchCategoryDto.toModel(): SearchCategory = SearchCategory(categoryId, categoryName, groups.map { it.toModel() }) -fun SearchGroupDto.toModel(): SearchGroup = SearchGroup(groupId, groupName, parts.map { it.toModel() }) \ No newline at end of file +fun SearchCategoryDto.toModel(): List { + return groups.flatMap { group -> + group.parts.map { part -> + SearchResult( + part = part.toModel(), + categoryName = categoryName, + groupName = group.groupName + ) + } + } +} + +fun SearchDataDto.toModel(): List { + return content.flatMap { category -> + category.toModel() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/paging/PartPagingSource.kt b/app/src/main/java/com/sampoom/android/feature/part/data/paging/PartPagingSource.kt new file mode 100644 index 0000000..510320e --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/part/data/paging/PartPagingSource.kt @@ -0,0 +1,38 @@ +package com.sampoom.android.feature.part.data.paging + +import androidx.paging.PagingSource +import androidx.paging.PagingState +import com.sampoom.android.feature.part.data.mapper.toModel +import com.sampoom.android.feature.part.data.remote.api.PartApi +import com.sampoom.android.feature.part.domain.model.SearchResult +import javax.inject.Inject + +class PartPagingSource @Inject constructor( + private val api: PartApi, + private val keyword: String +) : PagingSource() { + + override fun getRefreshKey(state: PagingState): Int? { + return state.anchorPosition?.let { anchorPosition -> + state.closestPageToPosition(anchorPosition)?.prevKey?.plus(1) + ?: state.closestPageToPosition(anchorPosition)?.nextKey?.minus(1) + } + } + + override suspend fun load(params: LoadParams): LoadResult { + return try { + val page = params.key ?: 0 + val response = api.searchParts(keyword, page, params.loadSize) + + val flatParts = response.data.toModel() + + LoadResult.Page( + data = flatParts, + prevKey = if (page == 0) null else page - 1, + nextKey = if (page < response.data.totalPages - 1) page + 1 else null + ) + } catch (e: Exception) { + LoadResult.Error(e) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt index c205359..a04d79b 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt @@ -1,13 +1,17 @@ package com.sampoom.android.feature.part.data.repository +import androidx.paging.Pager +import androidx.paging.PagingConfig +import androidx.paging.PagingData import com.sampoom.android.feature.part.data.mapper.toModel +import com.sampoom.android.feature.part.data.paging.PartPagingSource import com.sampoom.android.feature.part.data.remote.api.PartApi import com.sampoom.android.feature.part.domain.model.CategoryList import com.sampoom.android.feature.part.domain.model.GroupList import com.sampoom.android.feature.part.domain.model.PartList import com.sampoom.android.feature.part.domain.model.SearchResult import com.sampoom.android.feature.part.domain.repository.PartRepository -import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.flow.Flow import javax.inject.Inject class PartRepositoryImpl @Inject constructor( @@ -31,17 +35,10 @@ class PartRepositoryImpl @Inject constructor( return PartList(items = partItems) } - override suspend fun searchParts( - keyword: String, - page: Int, - size: Int - ): SearchResult { - val response = api.searchParts(keyword, page, size) - val searchItems = response.data.content.map { it.toModel() } - val totalElements = response.data.totalElements - val totalPages = response.data.totalPages - val currentPage = response.data.currentPage - - return SearchResult(searchItems, totalElements, totalPages, currentPage) + override fun searchParts(keyword: String): Flow> { + return Pager( + config = PagingConfig(pageSize = 20), + pagingSourceFactory = { PartPagingSource(api, keyword) } + ).flow } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/model/SearchResult.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/model/SearchResult.kt index fa37597..cfa350b 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/domain/model/SearchResult.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/model/SearchResult.kt @@ -1,20 +1,7 @@ package com.sampoom.android.feature.part.domain.model data class SearchResult( - val content: List, - val totalElements: Int, - val totalPages: Int, - val currentPage: Int -) - -data class SearchCategory( - val categoryId: Long, + val part: Part, val categoryName: String, - val groups: List -) - -data class SearchGroup( - val groupId: Long, - val groupName: String, - val parts: List + val groupName: String ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt index 41b490f..d5fbdd1 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt @@ -1,13 +1,15 @@ package com.sampoom.android.feature.part.domain.repository +import androidx.paging.PagingData import com.sampoom.android.feature.part.domain.model.CategoryList import com.sampoom.android.feature.part.domain.model.GroupList import com.sampoom.android.feature.part.domain.model.PartList import com.sampoom.android.feature.part.domain.model.SearchResult +import kotlinx.coroutines.flow.Flow interface PartRepository { suspend fun getCategoryList(): CategoryList suspend fun getGroupList(categoryId: Long): GroupList suspend fun getPartList(groupId: Long): PartList - suspend fun searchParts(keyword: String, page: Int = 0, size: Int = 10): SearchResult + fun searchParts(keyword: String): Flow> } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/SearchPartsUseCase.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/SearchPartsUseCase.kt index f9b6c4f..dd13cef 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/SearchPartsUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/SearchPartsUseCase.kt @@ -1,13 +1,15 @@ package com.sampoom.android.feature.part.domain.usecase +import androidx.paging.PagingData import com.sampoom.android.feature.part.domain.model.SearchResult import com.sampoom.android.feature.part.domain.repository.PartRepository +import kotlinx.coroutines.flow.Flow import javax.inject.Inject class SearchPartsUseCase @Inject constructor( private val repository: PartRepository ) { - suspend operator fun invoke(keyword: String, page: Int = 0, size: Int = 20): SearchResult { - return repository.searchParts(keyword, page, size) + operator fun invoke(keyword: String): Flow> { + return repository.searchParts(keyword) } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt index b32c2cb..31d630a 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt @@ -45,6 +45,7 @@ import com.sampoom.android.R import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent import com.sampoom.android.core.ui.theme.backgroundCardColor +import com.sampoom.android.core.ui.theme.disableColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.outbound.ui.OutboundListUiEvent @@ -222,7 +223,7 @@ private fun PartListItemCard( Icon( painterResource(R.drawable.chevron_right), contentDescription = stringResource(R.string.common_detail), - tint = textSecondaryColor() + tint = disableColor() ) } } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index 555f1c2..6e4749a 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -4,6 +4,7 @@ import android.R.attr.fontWeight import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll @@ -29,6 +30,9 @@ import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.paging.compose.LazyPagingItems +import androidx.paging.compose.collectAsLazyPagingItems +import androidx.paging.compose.itemKey import com.sampoom.android.R import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent @@ -69,7 +73,9 @@ fun PartScreen( var showBottomSheet by remember { mutableStateOf(false) } Box( - modifier = Modifier.fillMaxSize().background(backgroundColor()) + modifier = Modifier + .fillMaxSize() + .background(backgroundColor()) ) { SearchBar( modifier = Modifier.align(Alignment.TopCenter), @@ -81,7 +87,6 @@ fun PartScreen( }, onSearch = { viewModel.onEvent(PartUiEvent.Search(textFieldState.text)) -// expanded = false }, expanded = expanded, onExpandedChange = { expanded = it }, @@ -134,7 +139,7 @@ fun PartScreen( ) } - uiState.searchResults?.content?.isEmpty() == true -> { + viewModel.searchResult.collectAsLazyPagingItems().itemCount == 0 && textFieldState.text.isNotBlank() -> { Box( modifier = Modifier .fillMaxSize(), @@ -148,7 +153,7 @@ fun PartScreen( else -> { SearchResultsList( - searchResults = uiState.searchResults, + searchResults = viewModel.searchResult.collectAsLazyPagingItems(), onPartClick = { part -> searchViewModel.onEvent(PartListUiEvent.ShowBottomSheet(part)) showBottomSheet = true @@ -310,7 +315,8 @@ fun PartScreen( PartItemCard( group = group, onClick = { - onNavigatePartList(group) } + onNavigatePartList(group) + } ) } } @@ -426,50 +432,28 @@ private fun PartItemCard( @Composable fun SearchResultsList( - searchResults: SearchResult?, - onPartClick: (Part) -> Unit + searchResults: LazyPagingItems, + onPartClick: (Part) -> Unit, ) { LazyColumn( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.spacedBy(16.dp), contentPadding = PaddingValues(16.dp) ) { - searchResults?.content?.forEach { category -> - category.groups.forEach { group -> - item { - SearchSection( - categoryName = category.categoryName, - groupName = group.groupName, - parts = group.parts, - onPartClick = onPartClick - ) - } - } - } - } -} -@Composable -private fun SearchSection( - categoryName: String, - groupName: String, - parts: List, - onPartClick: (Part) -> Unit -) { - Column( - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - Text( - text = "$categoryName > $groupName", - style = MaterialTheme.typography.titleMedium, - color = textColor() - ) - - parts.forEach { part -> - SearchPartItem( - part = part, - onClick = { onPartClick(part) } - ) + items( + count = searchResults.itemCount, + key = searchResults.itemKey { it.part.partId } + ) { index -> + val partWithContext = searchResults[index] + if (partWithContext != null) { + SearchPartItem( + part = partWithContext.part, + categoryName = partWithContext.categoryName, + groupName = partWithContext.groupName, + onClick = { onPartClick(partWithContext.part) } + ) + } } } } @@ -477,6 +461,8 @@ private fun SearchSection( @Composable private fun SearchPartItem( part: Part, + categoryName: String, + groupName: String, onClick: () -> Unit ) { Card( @@ -488,15 +474,19 @@ private fun SearchPartItem( ) ) { Row( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), + modifier = Modifier.fillMaxWidth().padding(16.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Column( modifier = Modifier.weight(1f) ) { + Text( + text = "$categoryName > $groupName", + style = MaterialTheme.typography.bodySmall, + color = textSecondaryColor() + ) + Text( text = part.name, style = MaterialTheme.typography.titleMedium, @@ -511,10 +501,16 @@ private fun SearchPartItem( } Text( - text = "${part.quantity}개", + text = "${part.quantity}", style = MaterialTheme.typography.bodyMedium, color = textColor() ) + + Icon( + painterResource(R.drawable.chevron_right), + contentDescription = stringResource(R.string.common_detail), + tint = disableColor() + ) } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt index 9ca3ade..a4f00e4 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt @@ -22,5 +22,5 @@ data class PartUiState( val searchResults: SearchResult? = null, val isLoading: Boolean = false, val error: String? = null, - val keyword: String = "" + val keyword: String? = null ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt index 75c858a..0512e65 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt @@ -3,16 +3,27 @@ package com.sampoom.android.feature.part.ui import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import androidx.paging.PagingData +import androidx.paging.cachedIn import com.sampoom.android.core.network.serverMessageOrNull import com.sampoom.android.feature.part.domain.model.Category +import com.sampoom.android.feature.part.domain.model.SearchResult import com.sampoom.android.feature.part.domain.usecase.GetCategoryUseCase import com.sampoom.android.feature.part.domain.usecase.GetGroupUseCase import com.sampoom.android.feature.part.domain.usecase.SearchPartsUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.debounce +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject @@ -42,13 +53,33 @@ class PartViewModel @Inject constructor( loadCategory() } + private val _searchKeyword = MutableStateFlow(null) + + @OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class) + val searchResult: Flow> = _searchKeyword + .debounce(300) + .distinctUntilChanged() + .flatMapLatest { keyword -> + if (keyword.isNullOrBlank()) { + flowOf(PagingData.empty()) + } else { + searchPartsUseCase(keyword) + } + } + .cachedIn(viewModelScope) + fun onEvent(event: PartUiEvent) { when (event) { is PartUiEvent.LoadCategories -> loadCategory() is PartUiEvent.CategorySelected -> selectCategory(event.category) is PartUiEvent.RetryCategories -> loadCategory() is PartUiEvent.RetryGroups -> loadGroup() - is PartUiEvent.Search -> searchParts(event.keyword) + is PartUiEvent.Search -> { + _searchKeyword.value = event.keyword + _uiState.update { + it.copy(keyword = event.keyword) + } + } is PartUiEvent.SetKeyword -> _uiState.update { it.copy(keyword = event.keyword) } is PartUiEvent.ClearError -> _uiState.update { it.copy(error = null) } } @@ -128,32 +159,4 @@ class PartViewModel @Inject constructor( loadGroup(selectedCategory.id) } } - - private fun searchParts(keyword: String) { - viewModelScope.launch { - if (keyword.isBlank()) return@launch - - _uiState.update { it.copy(isLoading = true, error = null) } - - try { - val searchResult = searchPartsUseCase(keyword) - _uiState.update { - it.copy( - searchResults = searchResult, - isLoading = false - ) - } - } catch (ce: kotlin.coroutines.cancellation.CancellationException) { - throw ce - } catch (throwable: Throwable) { - val backendMessage = throwable.serverMessageOrNull() - _uiState.update { - it.copy( - isLoading = false, - error = backendMessage ?: (throwable.message ?: errorLabel) - ) - } - } - } - } } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3d5c222..740e32f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,12 +11,13 @@ junitVersion = "1.3.0" espressoCore = "3.7.0" lifecycleRuntimeKtx = "2.9.4" activityCompose = "1.11.0" -composeBom = "2025.10.00" +composeBom = "2025.10.01" loggingInterceptor = "5.2.1" -material = "1.9.3" +material = "1.9.4" materialIconsCore = "1.7.8" navigationCompose = "2.9.5" retrofitVersion = "3.0.0" +paging = "3.3.6" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -44,6 +45,8 @@ androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "u androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" } +androidx-paging-runtime = { group = "androidx.paging", name = "paging-runtime", version.ref = "paging" } +androidx-paging-compose = { group = "androidx.paging", name = "paging-compose", version.ref = "paging" } logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "loggingInterceptor" } retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofitVersion" } From cb5d147301c94fc1fb14548aaf362160aabe4ade Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Thu, 23 Oct 2025 20:57:53 +0900 Subject: [PATCH 50/88] =?UTF-8?q?[FIX]=20=EC=83=88=EB=A1=9C=EA=B3=A0?= =?UTF-8?q?=EC=B9=A8=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95=20/=20?= =?UTF-8?q?=EB=B6=88=ED=95=84=EC=9A=94=20import=20=EC=A0=9C=EA=B1=B0=20/?= =?UTF-8?q?=20Nav=20Animation=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/AppNavHost.kt | 13 ++- .../android/core/ui/component/EmptyContent.kt | 8 +- .../android/feature/cart/ui/CartListScreen.kt | 3 +- .../feature/order/ui/OrderDetailScreen.kt | 4 +- .../feature/order/ui/OrderListScreen.kt | 2 +- .../feature/outbound/ui/OutboundListScreen.kt | 3 +- .../android/feature/part/ui/PartListScreen.kt | 24 ++++-- .../android/feature/part/ui/PartScreen.kt | 81 +++++++++++++------ .../android/feature/part/ui/PartUiEvent.kt | 1 - .../android/feature/part/ui/PartUiState.kt | 2 - .../android/feature/part/ui/PartViewModel.kt | 2 - app/src/main/res/values/strings.xml | 1 + 12 files changed, 95 insertions(+), 49 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 7ad8397..482e416 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -2,6 +2,7 @@ package com.sampoom.android.app.navigation import android.os.Build import androidx.annotation.RequiresApi +import androidx.compose.foundation.background import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.padding import androidx.compose.material3.FloatingActionButton @@ -13,6 +14,7 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.navigation.NavHostController @@ -23,6 +25,7 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import com.sampoom.android.R +import com.sampoom.android.core.ui.theme.backgroundColor import com.sampoom.android.feature.auth.ui.LoginScreen import com.sampoom.android.feature.auth.ui.SignUpScreen import com.sampoom.android.feature.cart.ui.CartListScreen @@ -73,7 +76,8 @@ fun AppNavHost() { NavHost( navController = navController, - startDestination = if (isLoggedIn) ROUTE_HOME else ROUTE_LOGIN + startDestination = if (isLoggedIn) ROUTE_HOME else ROUTE_LOGIN, + modifier = Modifier.background(backgroundColor()) ) { composable(ROUTE_LOGIN) { LoginScreen( @@ -106,6 +110,7 @@ fun AppNavHost() { }, onNavigatePartList = { group -> // TODO: 실제 사용자의 agencyId 사용 + navController.currentBackStackEntry?.savedStateHandle?.set("groupName", group.name) navController.navigate(routePartList(1, group.id)) } ) @@ -120,7 +125,8 @@ fun AppNavHost() { PartListScreen( onNavigateBack = { navController.navigateUp() - } + }, + navController = navController ) } composable( @@ -197,7 +203,8 @@ fun PartsFab(navController: NavHostController) { ) { Icon( painterResource(R.drawable.parts), - contentDescription = stringResource(R.string.part_title) + contentDescription = stringResource(R.string.part_title), + tint = Color.White ) } } diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/EmptyContent.kt b/app/src/main/java/com/sampoom/android/core/ui/component/EmptyContent.kt index 83439f1..b522f20 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/EmptyContent.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/EmptyContent.kt @@ -1,10 +1,12 @@ package com.sampoom.android.core.ui.component import androidx.compose.foundation.layout.Box +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import com.sampoom.android.core.ui.theme.textSecondaryColor @Composable fun EmptyContent( @@ -15,6 +17,10 @@ fun EmptyContent( modifier = modifier, contentAlignment = Alignment.Center ) { - Text(message) + Text( + text = message, + color = textSecondaryColor(), + style = MaterialTheme.typography.bodyMedium + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt index bf83548..96a3913 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt @@ -47,7 +47,6 @@ import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.cart.domain.model.CartPart -import com.sampoom.android.feature.order.ui.OrderListUiEvent import com.sampoom.android.feature.order.ui.OrderResultBottomSheet import kotlin.collections.forEach @@ -75,7 +74,7 @@ fun CartListScreen( } PullToRefreshBox( - isRefreshing = uiState.cartLoading, + isRefreshing = false, onRefresh = { viewModel.onEvent(CartListUiEvent.LoadCartList) }, state = pullRefreshState, modifier = Modifier.fillMaxSize(), diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt index d4bbfcc..d67385d 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt @@ -1,6 +1,5 @@ package com.sampoom.android.feature.order.ui -import android.R.attr.order import android.widget.Toast import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row @@ -43,7 +42,6 @@ import com.sampoom.android.core.ui.component.CommonButton import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent import com.sampoom.android.feature.order.domain.model.OrderStatus -import com.sampoom.android.feature.outbound.ui.OutboundListUiEvent @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -84,7 +82,7 @@ fun OrderDetailScreen( } PullToRefreshBox( - isRefreshing = uiState.orderDetailLoading, + isRefreshing = false, onRefresh = { viewModel.onEvent(OrderDetailUiEvent.LoadOrder) }, state = pullRefreshState, modifier = Modifier.fillMaxSize(), diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt index 6125a00..4f88017 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt @@ -64,7 +64,7 @@ fun OrderListScreen( } PullToRefreshBox( - isRefreshing = uiState.orderLoading, + isRefreshing = false, onRefresh = { viewModel.onEvent(OrderListUiEvent.LoadOrderList) }, state = pullRefreshState, modifier = Modifier.fillMaxSize(), diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt index 21c1664..7888457 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt @@ -49,7 +49,6 @@ import com.sampoom.android.core.ui.theme.FailRed import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor -import com.sampoom.android.feature.order.ui.OrderListUiEvent import com.sampoom.android.feature.outbound.domain.model.OutboundPart @OptIn(ExperimentalMaterial3Api::class) @@ -81,7 +80,7 @@ fun OutboundListScreen( } } PullToRefreshBox( - isRefreshing = uiState.outboundLoading, + isRefreshing = false, onRefresh = { viewModel.onEvent(OutboundListUiEvent.LoadOutboundList) }, state = pullRefreshState, modifier = Modifier.fillMaxSize(), diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt index 31d630a..be98d9e 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt @@ -28,10 +28,10 @@ import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -41,6 +41,8 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.navigation.NavHostController +import androidx.navigation.compose.rememberNavController import com.sampoom.android.R import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent @@ -48,15 +50,20 @@ import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.disableColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor -import com.sampoom.android.feature.outbound.ui.OutboundListUiEvent import com.sampoom.android.feature.part.domain.model.Part @OptIn(ExperimentalMaterial3Api::class) @Composable fun PartListScreen( onNavigateBack: () -> Unit = {}, + navController: NavHostController = rememberNavController(), viewModel: PartListViewModel = hiltViewModel() ) { + val groupName by navController.previousBackStackEntry?.savedStateHandle?.getStateFlow( + "groupName", + null + )?.collectAsState() ?: remember { mutableStateOf(null) } + val errorLabel = stringResource(R.string.common_error) LaunchedEffect(errorLabel) { @@ -71,7 +78,7 @@ fun PartListScreen( var showBottomSheet by remember { mutableStateOf(false) } PullToRefreshBox( - isRefreshing = uiState.partListLoading, + isRefreshing = false, onRefresh = { viewModel.onEvent(PartListUiEvent.LoadPartList) }, state = pullRefreshState, modifier = Modifier.fillMaxSize(), @@ -88,7 +95,7 @@ fun PartListScreen( Scaffold( topBar = { TopAppBar( - title = { Text(stringResource(R.string.part_title)) }, + title = { Text(groupName ?: stringResource(R.string.part_title)) }, navigationIcon = { IconButton(onClick = onNavigateBack) { Icon( @@ -104,7 +111,8 @@ fun PartListScreen( uiState.partListLoading -> { Box( modifier = Modifier - .fillMaxSize().padding(innerPadding), + .fillMaxSize() + .padding(innerPadding), contentAlignment = Alignment.Center ) { CircularProgressIndicator() @@ -114,7 +122,8 @@ fun PartListScreen( uiState.partListError != null -> { Box( modifier = Modifier - .fillMaxSize().padding(innerPadding), + .fillMaxSize() + .padding(innerPadding), contentAlignment = Alignment.Center ) { ErrorContent( @@ -127,7 +136,8 @@ fun PartListScreen( uiState.partList.isEmpty() -> { Box( modifier = Modifier - .fillMaxSize().padding(innerPadding), + .fillMaxSize() + .padding(innerPadding), contentAlignment = Alignment.Center ) { EmptyContent( diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index 6e4749a..f1e7322 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -1,15 +1,10 @@ package com.sampoom.android.feature.part.ui -import android.R.attr.fontWeight -import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Search import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.runtime.getValue @@ -17,19 +12,15 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.isTraversalGroup -import androidx.compose.ui.semantics.semantics -import androidx.compose.ui.semantics.traversalIndex import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.paging.LoadState import androidx.paging.compose.LazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.itemKey @@ -47,6 +38,11 @@ import com.sampoom.android.feature.part.domain.model.Category import com.sampoom.android.feature.part.domain.model.Group import com.sampoom.android.feature.part.domain.model.Part import com.sampoom.android.feature.part.domain.model.SearchResult +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch import kotlin.collections.forEach @OptIn(ExperimentalMaterial3Api::class) @@ -65,9 +61,13 @@ fun PartScreen( val uiState by viewModel.uiState.collectAsStateWithLifecycle() val searchUiState by searchViewModel.uiState.collectAsStateWithLifecycle() + val searchResultsPaged = viewModel.searchResult.collectAsLazyPagingItems() var textFieldState by remember { mutableStateOf(TextFieldValue("")) } var expanded by rememberSaveable { mutableStateOf(false) } + // 자동 검색을 위한 LaunchedEffect + var searchJob by remember { mutableStateOf(null) } + // ModalBottomSheet 상태 관리 val sheetState = rememberModalBottomSheetState() var showBottomSheet by remember { mutableStateOf(false) } @@ -75,15 +75,30 @@ fun PartScreen( Box( modifier = Modifier .fillMaxSize() - .background(backgroundColor()) ) { SearchBar( modifier = Modifier.align(Alignment.TopCenter), inputField = { SearchBarDefaults.InputField( query = textFieldState.text, - onQueryChange = { - textFieldState = textFieldState.copy(it) + onQueryChange = { newText -> + textFieldState = textFieldState.copy(newText) + + // 기존 검색 작업 취소 + searchJob?.cancel() + + if (newText.isNotBlank()) { + // 500ms 지연 후 검색 실행 + searchJob = CoroutineScope(Dispatchers.Main).launch { + delay(500) + if (newText.isNotBlank()) { + viewModel.onEvent(PartUiEvent.Search(newText)) + } + } + } else { + // 검색어가 비어있으면 검색 결과 초기화 + viewModel.onEvent(PartUiEvent.Search("")) + } }, onSearch = { viewModel.onEvent(PartUiEvent.Search(textFieldState.text)) @@ -119,27 +134,42 @@ fun PartScreen( expanded = expanded, onExpandedChange = { expanded = it }, colors = SearchBarDefaults.colors( - containerColor = backgroundColor() + containerColor = backgroundColor(), + dividerColor = Color.Transparent ) ) { when { - uiState.isLoading -> { + textFieldState.text.isBlank() -> { Box( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Text( + text = stringResource(R.string.part_search_description), + color = textSecondaryColor(), + style = MaterialTheme.typography.bodyMedium + ) + } + } + + searchResultsPaged.loadState.refresh is LoadState.Loading -> { + Box( + modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { CircularProgressIndicator() } } - uiState.error != null -> { + searchResultsPaged.loadState.refresh is LoadState.Error -> { ErrorContent( onRetry = { viewModel.onEvent(PartUiEvent.Search(textFieldState.text)) }, - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxSize() ) } - viewModel.searchResult.collectAsLazyPagingItems().itemCount == 0 && textFieldState.text.isNotBlank() -> { + searchResultsPaged.itemCount == 0 && textFieldState.text.isNotBlank() -> { Box( modifier = Modifier .fillMaxSize(), @@ -153,7 +183,7 @@ fun PartScreen( else -> { SearchResultsList( - searchResults = viewModel.searchResult.collectAsLazyPagingItems(), + searchResults = searchResultsPaged, onPartClick = { part -> searchViewModel.onEvent(PartListUiEvent.ShowBottomSheet(part)) showBottomSheet = true @@ -285,7 +315,7 @@ fun PartScreen( when { uiState.groupLoading -> { Box( - modifier = Modifier.fillMaxSize(), + modifier = Modifier.height(200.dp).fillMaxSize(), contentAlignment = Alignment.Center ) { CircularProgressIndicator() @@ -295,14 +325,14 @@ fun PartScreen( uiState.groupError != null -> { ErrorContent( onRetry = { viewModel.onEvent(PartUiEvent.RetryGroups) }, - modifier = Modifier.height(200.dp) + modifier = Modifier.height(200.dp).fillMaxWidth() ) } uiState.groupList.isEmpty() -> { EmptyContent( message = stringResource(R.string.part_empty_group), - modifier = Modifier.height(200.dp) + modifier = Modifier.height(200.dp).fillMaxWidth() ) } @@ -438,7 +468,7 @@ fun SearchResultsList( LazyColumn( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.spacedBy(16.dp), - contentPadding = PaddingValues(16.dp) + contentPadding = PaddingValues(8.dp) ) { items( @@ -496,7 +526,8 @@ private fun SearchPartItem( Text( text = part.code, style = MaterialTheme.typography.bodySmall, - color = textSecondaryColor() + color = textSecondaryColor(), + fontWeight = FontWeight.Light ) } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiEvent.kt index 50836ce..271f828 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiEvent.kt @@ -9,5 +9,4 @@ sealed interface PartUiEvent { object RetryGroups : PartUiEvent data class Search(val keyword: String) : PartUiEvent data class SetKeyword(val keyword: String) : PartUiEvent - object ClearError : PartUiEvent } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt index a4f00e4..497dae7 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt @@ -20,7 +20,5 @@ data class PartUiState( // Search val searchResults: SearchResult? = null, - val isLoading: Boolean = false, - val error: String? = null, val keyword: String? = null ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt index 0512e65..c51775b 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt @@ -23,7 +23,6 @@ import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject @@ -81,7 +80,6 @@ class PartViewModel @Inject constructor( } } is PartUiEvent.SetKeyword -> _uiState.update { it.copy(keyword = event.keyword) } - is PartUiEvent.ClearError -> _uiState.update { it.copy(error = null) } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 337f1b5..3ef3aa1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -48,6 +48,7 @@ 카테고리를 선택해주세요. 그룹 목록이 없습니다. 검색 결과가 없습니다. + 부품명으로 검색어를 입력하세요. 현재 재고 : From 104cbe27edf4ed361858ea0138bfb84953a35b0e Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Thu, 23 Oct 2025 21:07:31 +0900 Subject: [PATCH 51/88] =?UTF-8?q?[FEAT]=20=EA=B2=80=EC=83=89=EC=96=B4=20?= =?UTF-8?q?=EC=A7=80=EC=9A=B0=EA=B8=B0=20=EB=B2=84=ED=8A=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/part/ui/PartScreen.kt | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index f1e7322..52348b4 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -5,6 +5,8 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Clear import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.runtime.getValue @@ -123,11 +125,28 @@ fun PartScreen( } } }, + trailingIcon = { + if (textFieldState.text.isNotEmpty()) { + IconButton( + onClick = { + textFieldState = textFieldState.copy("") + viewModel.onEvent(PartUiEvent.Search("")) + } + ) { + Icon( + imageVector = Icons.Default.Clear, + contentDescription = "검색어 지우기" + ) + } + } + }, colors = OutlinedTextFieldDefaults.colors( focusedContainerColor = backgroundColor(), unfocusedContainerColor = backgroundCardColor(), focusedBorderColor = Color.Transparent, - unfocusedBorderColor = textSecondaryColor().copy(0.3f) + unfocusedBorderColor = textSecondaryColor().copy(0.3f), + focusedTrailingIconColor = textSecondaryColor(), + unfocusedTrailingIconColor = textSecondaryColor() ) ) }, From 8740130723b7656dfcfbc0df0a6dc7bc47f7bfb5 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Thu, 23 Oct 2025 21:33:27 +0900 Subject: [PATCH 52/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/part/data/paging/PartPagingSource.kt | 13 ++++++++++--- .../android/feature/part/data/remote/api/PartApi.kt | 2 +- .../part/data/repository/PartRepositoryImpl.kt | 5 +++-- .../sampoom/android/feature/part/ui/PartScreen.kt | 6 ++++-- .../sampoom/android/feature/part/ui/PartUiState.kt | 1 - 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/paging/PartPagingSource.kt b/app/src/main/java/com/sampoom/android/feature/part/data/paging/PartPagingSource.kt index 510320e..7435ff7 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/paging/PartPagingSource.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/paging/PartPagingSource.kt @@ -5,13 +5,20 @@ import androidx.paging.PagingState import com.sampoom.android.feature.part.data.mapper.toModel import com.sampoom.android.feature.part.data.remote.api.PartApi import com.sampoom.android.feature.part.domain.model.SearchResult -import javax.inject.Inject +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject -class PartPagingSource @Inject constructor( +class PartPagingSource @AssistedInject constructor( private val api: PartApi, - private val keyword: String + @Assisted private val keyword: String ) : PagingSource() { + @AssistedFactory + interface Factory { + fun create(keyword: String): PartPagingSource + } + override fun getRefreshKey(state: PagingState): Int? { return state.anchorPosition?.let { anchorPosition -> state.closestPageToPosition(anchorPosition)?.prevKey?.plus(1) diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt b/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt index a7aa4d5..617f12a 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt @@ -24,6 +24,6 @@ interface PartApi { suspend fun searchParts( @Query("keyword") keyword: String, @Query("page") page: Int = 0, - @Query("size") size: Int = 10 + @Query("size") size: Int = 20 ): ApiResponse } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt index a04d79b..cd0694a 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt @@ -15,7 +15,8 @@ import kotlinx.coroutines.flow.Flow import javax.inject.Inject class PartRepositoryImpl @Inject constructor( - private val api: PartApi + private val api: PartApi, + private val pagingSourceFactory: PartPagingSource.Factory ) : PartRepository { override suspend fun getCategoryList(): CategoryList { val dto = api.getCategoryList() @@ -38,7 +39,7 @@ class PartRepositoryImpl @Inject constructor( override fun searchParts(keyword: String): Flow> { return Pager( config = PagingConfig(pageSize = 20), - pagingSourceFactory = { PartPagingSource(api, keyword) } + pagingSourceFactory = { pagingSourceFactory.create(keyword) } ).flow } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index 52348b4..e897f85 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -22,6 +22,7 @@ import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.paging.LoadState import androidx.paging.compose.LazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems @@ -69,6 +70,7 @@ fun PartScreen( // 자동 검색을 위한 LaunchedEffect var searchJob by remember { mutableStateOf(null) } + val coroutineScope = rememberCoroutineScope() // ModalBottomSheet 상태 관리 val sheetState = rememberModalBottomSheetState() @@ -91,7 +93,7 @@ fun PartScreen( if (newText.isNotBlank()) { // 500ms 지연 후 검색 실행 - searchJob = CoroutineScope(Dispatchers.Main).launch { + searchJob = coroutineScope.launch { delay(500) if (newText.isNotBlank()) { viewModel.onEvent(PartUiEvent.Search(newText)) @@ -334,7 +336,7 @@ fun PartScreen( when { uiState.groupLoading -> { Box( - modifier = Modifier.height(200.dp).fillMaxSize(), + modifier = Modifier.height(200.dp).fillMaxWidth(), contentAlignment = Alignment.Center ) { CircularProgressIndicator() diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt index 497dae7..19d8842 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartUiState.kt @@ -19,6 +19,5 @@ data class PartUiState( val categoryError: String? = null, // Search - val searchResults: SearchResult? = null, val keyword: String? = null ) \ No newline at end of file From 5dbbd7ea492bc48669a5a462d5dfcd51ed6f7566 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Thu, 23 Oct 2025 21:35:09 +0900 Subject: [PATCH 53/88] =?UTF-8?q?[FIX]=20padding=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sampoom/android/feature/part/ui/PartScreen.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index e897f85..0408995 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -488,8 +488,8 @@ fun SearchResultsList( ) { LazyColumn( modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.spacedBy(16.dp), - contentPadding = PaddingValues(8.dp) + verticalArrangement = Arrangement.spacedBy(8.dp), + contentPadding = PaddingValues(16.dp) ) { items( From 109c8ca65e44f39674c12c4bca4272e56cb3b437 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Thu, 23 Oct 2025 21:42:24 +0900 Subject: [PATCH 54/88] =?UTF-8?q?[FIX]=20coroutineJob=20=EC=9E=91=EC=97=85?= =?UTF-8?q?=20=EC=B7=A8=EC=86=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/sampoom/android/feature/part/ui/PartScreen.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index 0408995..1d459f8 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -105,6 +105,7 @@ fun PartScreen( } }, onSearch = { + searchJob?.cancel() viewModel.onEvent(PartUiEvent.Search(textFieldState.text)) }, expanded = expanded, @@ -131,6 +132,7 @@ fun PartScreen( if (textFieldState.text.isNotEmpty()) { IconButton( onClick = { + searchJob?.cancel() textFieldState = textFieldState.copy("") viewModel.onEvent(PartUiEvent.Search("")) } From a346a7ab2ba40eff2d786ce48fda0ddaa96e1979 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Thu, 23 Oct 2025 22:01:20 +0900 Subject: [PATCH 55/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../part/data/paging/PartPagingSource.kt | 2 +- .../android/feature/part/ui/PartScreen.kt | 52 +++++++++++++++---- app/src/main/res/values/strings.xml | 1 + 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/paging/PartPagingSource.kt b/app/src/main/java/com/sampoom/android/feature/part/data/paging/PartPagingSource.kt index 7435ff7..1509218 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/paging/PartPagingSource.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/paging/PartPagingSource.kt @@ -29,7 +29,7 @@ class PartPagingSource @AssistedInject constructor( override suspend fun load(params: LoadParams): LoadResult { return try { val page = params.key ?: 0 - val response = api.searchParts(keyword, page, params.loadSize) + val response = api.searchParts(keyword, page, 20) val flatParts = response.data.toModel() diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index 1d459f8..94f9257 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -22,7 +22,6 @@ import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.lifecycle.viewmodel.compose.viewModel import androidx.paging.LoadState import androidx.paging.compose.LazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems @@ -30,6 +29,7 @@ import androidx.paging.compose.itemKey import com.sampoom.android.R import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent +import com.sampoom.android.core.ui.theme.FailRed import com.sampoom.android.core.ui.theme.Main500 import com.sampoom.android.core.ui.theme.White import com.sampoom.android.core.ui.theme.backgroundCardColor @@ -41,8 +41,6 @@ import com.sampoom.android.feature.part.domain.model.Category import com.sampoom.android.feature.part.domain.model.Group import com.sampoom.android.feature.part.domain.model.Part import com.sampoom.android.feature.part.domain.model.SearchResult -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -139,7 +137,7 @@ fun PartScreen( ) { Icon( imageVector = Icons.Default.Clear, - contentDescription = "검색어 지우기" + contentDescription = stringResource(R.string.part_search_clear) ) } } @@ -338,7 +336,9 @@ fun PartScreen( when { uiState.groupLoading -> { Box( - modifier = Modifier.height(200.dp).fillMaxWidth(), + modifier = Modifier + .height(200.dp) + .fillMaxWidth(), contentAlignment = Alignment.Center ) { CircularProgressIndicator() @@ -348,14 +348,18 @@ fun PartScreen( uiState.groupError != null -> { ErrorContent( onRetry = { viewModel.onEvent(PartUiEvent.RetryGroups) }, - modifier = Modifier.height(200.dp).fillMaxWidth() + modifier = Modifier + .height(200.dp) + .fillMaxWidth() ) } uiState.groupList.isEmpty() -> { EmptyContent( message = stringResource(R.string.part_empty_group), - modifier = Modifier.height(200.dp).fillMaxWidth() + modifier = Modifier + .height(200.dp) + .fillMaxWidth() ) } @@ -493,7 +497,6 @@ fun SearchResultsList( verticalArrangement = Arrangement.spacedBy(8.dp), contentPadding = PaddingValues(16.dp) ) { - items( count = searchResults.itemCount, key = searchResults.itemKey { it.part.partId } @@ -508,6 +511,35 @@ fun SearchResultsList( ) } } + + item { + when (searchResults.loadState.append) { + is LoadState.Loading -> { + Box( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + is LoadState.Error -> { + Box( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + contentAlignment = Alignment.Center + ) { + Text( + text = stringResource(R.string.common_error), + color = FailRed + ) + } + } + else -> {} + } + } } } @@ -527,7 +559,9 @@ private fun SearchPartItem( ) ) { Row( - modifier = Modifier.fillMaxWidth().padding(16.dp), + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3ef3aa1..afe136a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -49,6 +49,7 @@ 그룹 목록이 없습니다. 검색 결과가 없습니다. 부품명으로 검색어를 입력하세요. + 검색어 지우기 현재 재고 : From 53efebbdedd8d9050b7d262d71fa82b2f53a19d7 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Fri, 24 Oct 2025 21:00:10 +0900 Subject: [PATCH 56/88] =?UTF-8?q?[FEAT]=20=EC=9C=A0=EC=A0=80=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8,=20=ED=9A=8C=EC=9B=90=20=EA=B0=80=EC=9E=85,?= =?UTF-8?q?=20=ED=86=A0=ED=81=B0=20=EA=B0=B1=EC=8B=A0,=20=EC=9E=90?= =?UTF-8?q?=EB=8F=99=20=EB=A1=9C=EA=B7=B8=EC=9D=B8,=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=95=84=EC=9B=83,=20Authorization=20=EC=A0=84=EC=97=AD=20?= =?UTF-8?q?=ED=97=A4=EB=8D=94=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/AppNavHost.kt | 44 ++++++++-- .../sampoom/android/core/database/.gitkeep | 0 .../android/core/datastore/AuthPreferences.kt | 88 +++++++++++++++++++ .../android/core/network/NetworkModule.kt | 61 ++++++++++--- .../android/core/network/TokenInterceptor.kt | 26 ++++++ .../core/network/TokenRefreshInterceptor.kt | 40 +++++++++ .../core/network/TokenRefreshService.kt | 41 +++++++++ .../data/local/preferences/AuthPreferences.kt | 50 ----------- .../feature/auth/data/mapper/AuthMappers.kt | 6 -- .../feature/auth/data/remote/api/AuthApi.kt | 17 ---- .../auth/data/remote/dto/SignUpRequestDto.kt | 10 --- .../data/repository/AuthRepositoryImpl.kt | 47 ---------- .../android/feature/auth/domain/model/User.kt | 10 --- .../auth/domain/repository/AuthRepository.kt | 18 ---- .../feature/user/data/mapper/AuthMappers.kt | 6 ++ .../feature/user/data/remote/api/AuthApi.kt | 36 ++++++++ .../data/remote/dto/LoginRequestDto.kt | 2 +- .../data/remote/dto/LoginResponseDto.kt | 4 +- .../user/data/remote/dto/RefreshRequestDto.kt | 5 ++ .../data/remote/dto/RefreshResponseDto.kt | 7 ++ .../user/data/remote/dto/SignUpRequestDto.kt | 10 +++ .../data/remote/dto/SignUpResponseDto.kt | 2 +- .../user/data/remote/dto/UpdateRequestDto.kt | 8 ++ .../user/data/remote/dto/UpdateResponseDto.kt | 10 +++ .../user/data/remote/dto/VerifyRequestDto.kt | 6 ++ .../user/data/remote/dto/VerifyResponseDto.kt | 8 ++ .../data/repository/AuthRepositoryImpl.kt | 72 +++++++++++++++ .../feature/{auth => user}/di/AuthModules.kt | 8 +- .../{auth => user}/domain/AuthValidator.kt | 2 +- .../android/feature/user/domain/model/User.kt | 10 +++ .../user/domain/repository/AuthRepository.kt | 20 +++++ .../domain/usecase/CheckLoginStateUseCase.kt | 10 +++ .../domain/usecase/LoginUseCase.kt | 6 +- .../user/domain/usecase/SignOutUseCase.kt | 10 +++ .../domain/usecase/SignUpUseCase.kt | 22 ++--- .../android/feature/user/ui/AuthViewModel.kt | 37 ++++++++ .../feature/{auth => user}/ui/LoginScreen.kt | 3 +- .../feature/{auth => user}/ui/LoginUiEvent.kt | 2 +- .../feature/{auth => user}/ui/LoginUiState.kt | 2 +- .../{auth => user}/ui/LoginViewModel.kt | 8 +- .../feature/{auth => user}/ui/SignUpScreen.kt | 5 +- .../{auth => user}/ui/SignUpUiEvent.kt | 2 +- .../{auth => user}/ui/SignUpUiState.kt | 2 +- .../{auth => user}/ui/SignUpViewModel.kt | 16 ++-- 44 files changed, 576 insertions(+), 223 deletions(-) delete mode 100644 app/src/main/java/com/sampoom/android/core/database/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt create mode 100644 app/src/main/java/com/sampoom/android/core/network/TokenInterceptor.kt create mode 100644 app/src/main/java/com/sampoom/android/core/network/TokenRefreshInterceptor.kt create mode 100644 app/src/main/java/com/sampoom/android/core/network/TokenRefreshService.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/auth/data/local/preferences/AuthPreferences.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpRequestDto.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/user/data/mapper/AuthMappers.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt rename app/src/main/java/com/sampoom/android/feature/{auth => user}/data/remote/dto/LoginRequestDto.kt (57%) rename app/src/main/java/com/sampoom/android/feature/{auth => user}/data/remote/dto/LoginResponseDto.kt (66%) create mode 100644 app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/RefreshRequestDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/RefreshResponseDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/SignUpRequestDto.kt rename app/src/main/java/com/sampoom/android/feature/{auth => user}/data/remote/dto/SignUpResponseDto.kt (64%) create mode 100644 app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateRequestDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateResponseDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/VerifyRequestDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/VerifyResponseDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt rename app/src/main/java/com/sampoom/android/feature/{auth => user}/di/AuthModules.kt (71%) rename app/src/main/java/com/sampoom/android/feature/{auth => user}/domain/AuthValidator.kt (98%) create mode 100644 app/src/main/java/com/sampoom/android/feature/user/domain/model/User.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/user/domain/usecase/CheckLoginStateUseCase.kt rename app/src/main/java/com/sampoom/android/feature/{auth => user}/domain/usecase/LoginUseCase.kt (57%) create mode 100644 app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignOutUseCase.kt rename app/src/main/java/com/sampoom/android/feature/{auth => user}/domain/usecase/SignUpUseCase.kt (50%) create mode 100644 app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt rename app/src/main/java/com/sampoom/android/feature/{auth => user}/ui/LoginScreen.kt (98%) rename app/src/main/java/com/sampoom/android/feature/{auth => user}/ui/LoginUiEvent.kt (82%) rename app/src/main/java/com/sampoom/android/feature/{auth => user}/ui/LoginUiState.kt (91%) rename app/src/main/java/com/sampoom/android/feature/{auth => user}/ui/LoginViewModel.kt (92%) rename app/src/main/java/com/sampoom/android/feature/{auth => user}/ui/SignUpScreen.kt (97%) rename app/src/main/java/com/sampoom/android/feature/{auth => user}/ui/SignUpUiEvent.kt (91%) rename app/src/main/java/com/sampoom/android/feature/{auth => user}/ui/SignUpUiState.kt (96%) rename app/src/main/java/com/sampoom/android/feature/{auth => user}/ui/SignUpViewModel.kt (93%) diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 482e416..db35350 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -3,8 +3,10 @@ package com.sampoom.android.app.navigation import android.os.Build import androidx.annotation.RequiresApi import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.NavigationBar @@ -12,11 +14,14 @@ import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.navigation.NavHostController import androidx.navigation.NavType import androidx.navigation.compose.NavHost @@ -26,8 +31,9 @@ import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import com.sampoom.android.R import com.sampoom.android.core.ui.theme.backgroundColor -import com.sampoom.android.feature.auth.ui.LoginScreen -import com.sampoom.android.feature.auth.ui.SignUpScreen +import com.sampoom.android.feature.user.ui.AuthViewModel +import com.sampoom.android.feature.user.ui.LoginScreen +import com.sampoom.android.feature.user.ui.SignUpScreen import com.sampoom.android.feature.cart.ui.CartListScreen import com.sampoom.android.feature.order.ui.OrderDetailScreen import com.sampoom.android.feature.order.ui.OrderListScreen @@ -70,9 +76,16 @@ sealed class BottomNavItem( @Composable fun AppNavHost() { val navController = rememberNavController() + val authViewModel: AuthViewModel = hiltViewModel() + val isLoggedIn by authViewModel.isLoggedIn.collectAsState() - // TODO: 임시 로그인 상태 확인 -> AuthRepository에서 확인하도록 변경 - val isLoggedIn = true + LaunchedEffect(Unit) { + authViewModel.logoutEvent.collect { + navController.navigate(ROUTE_LOGIN) { + popUpTo(0) { inclusive = true } + } + } + } NavHost( navController = navController, @@ -82,6 +95,7 @@ fun AppNavHost() { composable(ROUTE_LOGIN) { LoginScreen( onSuccess = { + authViewModel.updateLoginState() navController.navigate(ROUTE_HOME) { popUpTo(ROUTE_LOGIN) { inclusive = true } // 로그인 화면 스택 제거 } @@ -163,7 +177,11 @@ fun MainScreen( composable(ROUTE_DASHBOARD) { DashboardScreen( paddingValues = innerPadding - ) + ) { + parentNavController.navigate(ROUTE_LOGIN) { + popUpTo(0) { inclusive = true } + } + } } composable(ROUTE_OUTBOUND) { OutboundListScreen( @@ -249,8 +267,20 @@ fun BottomNavigationBar(navController: NavHostController) { // 임시 화면들 (실제로는 각각의 feature 모듈에서 구현) @Composable private fun DashboardScreen( - paddingValues: PaddingValues + paddingValues: PaddingValues, + onClick: () -> Unit ) { + val authViewModel: AuthViewModel = hiltViewModel() // 홈 화면 구현 - Text("대시보드 화면", modifier = Modifier.padding(paddingValues)) + Column(Modifier.padding(paddingValues)) { + Text("대시보드 화면", modifier = Modifier.padding(paddingValues)) + + Button(onClick = { + authViewModel.signOut() + onClick() + }) { + Text("로그아웃") + } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/database/.gitkeep b/app/src/main/java/com/sampoom/android/core/database/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt b/app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt new file mode 100644 index 0000000..4c30e3c --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt @@ -0,0 +1,88 @@ +package com.sampoom.android.core.datastore + +import android.content.Context +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.longPreferencesKey +import androidx.datastore.preferences.core.stringPreferencesKey +import androidx.datastore.preferences.preferencesDataStore +import com.sampoom.android.feature.user.domain.model.User +import dagger.hilt.android.qualifiers.ApplicationContext +import javax.inject.Inject +import javax.inject.Singleton +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.runBlocking + +// Per official guidance, DataStore instance should be single and at top-level. +private val Context.authDataStore by preferencesDataStore(name = "auth_prefs") + +@Singleton +class AuthPreferences @Inject constructor( + @param:ApplicationContext private val context: Context +){ + private val dataStore = context.authDataStore + + private object Keys { + val ACCESS_TOKEN: Preferences.Key = stringPreferencesKey("access_token") + val REFRESH_TOKEN: Preferences.Key = stringPreferencesKey("refresh_token") + val TOKEN_EXPIRES_AT: Preferences.Key = longPreferencesKey("token_expires_at") + val USER_ID: Preferences.Key = longPreferencesKey("user_id") + val USER_NAME: Preferences.Key = stringPreferencesKey("user_name") + val USER_ROLE: Preferences.Key = stringPreferencesKey("user_role") + } + + suspend fun saveUser(user: User) { + val expiresAt = System.currentTimeMillis() + (user.expiresIn * 1000) + dataStore.edit { prefs -> + prefs[Keys.ACCESS_TOKEN] = user.accessToken + prefs[Keys.REFRESH_TOKEN] = user.refreshToken + prefs[Keys.TOKEN_EXPIRES_AT] = expiresAt + prefs[Keys.USER_ID] = user.userId + prefs[Keys.USER_NAME] = user.userName + prefs[Keys.USER_ROLE] = user.role + } + } + + // Suspend save to avoid blocking thread + suspend fun saveToken(accessToken: String, refreshToken: String, expiresIn: Long) { + val expiresAt = System.currentTimeMillis() + (expiresIn * 1000) + dataStore.edit { prefs -> + prefs[Keys.ACCESS_TOKEN] = accessToken + prefs[Keys.REFRESH_TOKEN] = refreshToken + prefs[Keys.TOKEN_EXPIRES_AT] = expiresAt + } + } + + fun getStoredUser(): User? = runBlocking { + val userId = dataStore.data.first()[Keys.USER_ID] + val userName = dataStore.data.first()[Keys.USER_NAME] + val userRole = dataStore.data.first()[Keys.USER_ROLE] + val accessToken = dataStore.data.first()[Keys.ACCESS_TOKEN] + val refreshToken = dataStore.data.first()[Keys.REFRESH_TOKEN] + + if (userId != null && userName != null && userRole != null && + accessToken != null && refreshToken != null) { + User(userId, userName, userRole, accessToken, refreshToken, 0) + } else null + } + + // Synchronous getters backed by runBlocking for minimal surface change + fun getAccessToken(): String? = runBlocking { + dataStore.data.first()[Keys.ACCESS_TOKEN] + } + + fun getRefreshToken(): String? = runBlocking { + dataStore.data.first()[Keys.REFRESH_TOKEN] + } + + fun isTokenExpired(): Boolean { + val expiresAt = runBlocking { dataStore.data.first()[Keys.TOKEN_EXPIRES_AT] } + return expiresAt == null || System.currentTimeMillis() > expiresAt + } + + suspend fun clear() { + dataStore.edit { it.clear() } + } + + fun hasToken(): Boolean = !getAccessToken().isNullOrEmpty() && !getRefreshToken().isNullOrEmpty() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt index dac6a14..3393b9b 100644 --- a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt +++ b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt @@ -11,26 +11,61 @@ import javax.inject.Singleton import com.google.gson.GsonBuilder import com.google.gson.FieldNamingPolicy import com.sampoom.android.BuildConfig +import com.sampoom.android.core.datastore.AuthPreferences import okhttp3.logging.HttpLoggingInterceptor import java.util.concurrent.TimeUnit @Module @InstallIn(SingletonComponent::class) object NetworkModule { - @Provides @Singleton fun provideOkHttp(): OkHttpClient = OkHttpClient.Builder() - .connectTimeout(30, TimeUnit.SECONDS) - .readTimeout(30, TimeUnit.SECONDS) - .writeTimeout(30, TimeUnit.SECONDS) - .addInterceptor(HttpLoggingInterceptor().apply { - level = if (BuildConfig.DEBUG) - HttpLoggingInterceptor.Level.BODY - else - HttpLoggingInterceptor.Level.NONE - }) - // TODO: 로그인 기능 연동 후 인증 인터셉터 추가 필요 - .build() + @Provides + @Singleton + fun provideTokenInterceptor( + authPreferences: AuthPreferences + ): TokenInterceptor { + return TokenInterceptor(authPreferences) + } + + @Provides + @Singleton + fun provideTokenRefreshService( + authPreferences: AuthPreferences + ): TokenRefreshService { + return TokenRefreshService(authPreferences) + } + + @Provides + @Singleton + fun provideTokenRefreshInterceptor( + authPreferences: AuthPreferences, + tokenRefreshService: TokenRefreshService + ): TokenRefreshInterceptor { + return TokenRefreshInterceptor(authPreferences, tokenRefreshService) + } + + @Provides + @Singleton + fun provideOkHttpClient( + tokenInterceptor: TokenInterceptor, + tokenRefreshInterceptor: TokenRefreshInterceptor + ): OkHttpClient { + return OkHttpClient.Builder() + .connectTimeout(30, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .writeTimeout(30, TimeUnit.SECONDS) + .addInterceptor(HttpLoggingInterceptor().apply { + level = if (BuildConfig.DEBUG) + HttpLoggingInterceptor.Level.BODY + else + HttpLoggingInterceptor.Level.NONE + }) + .addInterceptor(tokenInterceptor) // 토큰 자동 삽입 + .addInterceptor(tokenRefreshInterceptor) // 토큰 갱신 + .build() + } - @Provides @Singleton + @Provides + @Singleton fun provideRetrofit(client: OkHttpClient): Retrofit { val gson = GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.IDENTITY) diff --git a/app/src/main/java/com/sampoom/android/core/network/TokenInterceptor.kt b/app/src/main/java/com/sampoom/android/core/network/TokenInterceptor.kt new file mode 100644 index 0000000..945fc23 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/network/TokenInterceptor.kt @@ -0,0 +1,26 @@ +package com.sampoom.android.core.network + +import com.sampoom.android.core.datastore.AuthPreferences +import okhttp3.Interceptor +import okhttp3.Response +import javax.inject.Inject + +class TokenInterceptor @Inject constructor( + private val authPreferences: AuthPreferences +) : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + val originalRequest = chain.request() + + if (originalRequest.header("Authorization") == null) { + val accessToken = authPreferences.getAccessToken() + if (!accessToken.isNullOrEmpty()) { + val newRequest = originalRequest.newBuilder() + .addHeader("Authorization", "Bearer $accessToken") + .build() + return chain.proceed(newRequest) + } + } + + return chain.proceed(originalRequest) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/network/TokenRefreshInterceptor.kt b/app/src/main/java/com/sampoom/android/core/network/TokenRefreshInterceptor.kt new file mode 100644 index 0000000..ce9720f --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/network/TokenRefreshInterceptor.kt @@ -0,0 +1,40 @@ +package com.sampoom.android.core.network + +import com.sampoom.android.core.datastore.AuthPreferences +import kotlinx.coroutines.runBlocking +import okhttp3.Interceptor +import okhttp3.Response +import javax.inject.Inject + +class TokenRefreshInterceptor @Inject constructor( + private val authPreferences: AuthPreferences, + private val tokenRefreshService: TokenRefreshService +) : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + val request = chain.request() + val response = chain.proceed(request) + + // 401 error + if (response.code == 401) { + try { + val newUser = runBlocking { + tokenRefreshService.refreshToken().getOrThrow() + } + + val newRequest = request.newBuilder() + .removeHeader("Authorization") + .addHeader("Authorization", "Bearer ${newUser.accessToken}") + .build() + + return chain.proceed(newRequest) + } catch (e: Exception) { + runBlocking { + authPreferences.clear() + } + return response + } + } + + return response + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/network/TokenRefreshService.kt b/app/src/main/java/com/sampoom/android/core/network/TokenRefreshService.kt new file mode 100644 index 0000000..d95f9dc --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/network/TokenRefreshService.kt @@ -0,0 +1,41 @@ +package com.sampoom.android.core.network + +import com.sampoom.android.core.datastore.AuthPreferences +import com.sampoom.android.feature.user.data.remote.api.AuthApi +import com.sampoom.android.feature.user.data.remote.dto.RefreshRequestDto +import com.sampoom.android.feature.user.domain.model.User +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class TokenRefreshService @Inject constructor( + private val authPreferences: AuthPreferences +) { + suspend fun refreshToken(): Result = runCatching { + val refreshToken = authPreferences.getRefreshToken() + ?: throw Exception("No refresh token available") + + // 새로운 Retrofit 인스턴스 생성 (인터셉터 없이) + val retrofit = Retrofit.Builder() + .baseUrl("https://sampoom.store/api/") + .addConverterFactory(GsonConverterFactory.create()) + .build() + + val authApi = retrofit.create(AuthApi::class.java) + val response = authApi.refresh(RefreshRequestDto(refreshToken)) + + val existingUser = authPreferences.getStoredUser() + ?: throw Exception("No user information available") + + val updatedUser = existingUser.copy( + accessToken = response.data.accessToken, + refreshToken = response.data.refreshToken, + expiresIn = response.data.expiresIn + ) + + authPreferences.saveUser(updatedUser) + updatedUser + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/local/preferences/AuthPreferences.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/local/preferences/AuthPreferences.kt deleted file mode 100644 index 789a143..0000000 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/local/preferences/AuthPreferences.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.sampoom.android.feature.auth.data.local.preferences - -import android.content.Context -import androidx.datastore.preferences.core.Preferences -import androidx.datastore.preferences.core.edit -import androidx.datastore.preferences.core.stringPreferencesKey -import androidx.datastore.preferences.preferencesDataStore -import dagger.hilt.android.qualifiers.ApplicationContext -import javax.inject.Inject -import javax.inject.Singleton -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.runBlocking - -// Per official guidance, DataStore instance should be single and at top-level. -private val Context.authDataStore by preferencesDataStore(name = "auth_prefs") - -@Singleton -class AuthPreferences @Inject constructor( - @param:ApplicationContext private val context: Context -){ - private val dataStore = context.authDataStore - - private object Keys { - val ACCESS_TOKEN: Preferences.Key = stringPreferencesKey("access_token") - val REFRESH_TOKEN: Preferences.Key = stringPreferencesKey("refresh_token") - } - - // Suspend save to avoid blocking thread - suspend fun saveToken(accessToken: String, refreshToken: String) { - dataStore.edit { prefs -> - prefs[Keys.ACCESS_TOKEN] = accessToken - prefs[Keys.REFRESH_TOKEN] = refreshToken - } - } - - // Synchronous getters backed by runBlocking for minimal surface change - fun getAccessToken(): String? = runBlocking { - dataStore.data.first()[Keys.ACCESS_TOKEN] - } - - fun getRefreshToken(): String? = runBlocking { - dataStore.data.first()[Keys.REFRESH_TOKEN] - } - - suspend fun clear() { - dataStore.edit { it.clear() } - } - - fun hasToken(): Boolean = !getAccessToken().isNullOrEmpty() && !getRefreshToken().isNullOrEmpty() -} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt deleted file mode 100644 index b79dea4..0000000 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.sampoom.android.feature.auth.data.mapper - -import com.sampoom.android.feature.auth.data.remote.dto.LoginResponseDto -import com.sampoom.android.feature.auth.domain.model.User - -fun LoginResponseDto.toModel(): User = User(userId, userName, role, accessToken, refreshToken, expiresIn) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt deleted file mode 100644 index 41ee5bd..0000000 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.sampoom.android.feature.auth.data.remote.api - -import com.sampoom.android.core.network.ApiResponse -import com.sampoom.android.feature.auth.data.remote.dto.LoginRequestDto -import com.sampoom.android.feature.auth.data.remote.dto.SignUpRequestDto -import com.sampoom.android.feature.auth.data.remote.dto.SignUpResponseDto -import com.sampoom.android.feature.auth.data.remote.dto.LoginResponseDto -import retrofit2.http.Body -import retrofit2.http.POST - -interface AuthApi { - @POST("auth/login") - suspend fun login(@Body body: LoginRequestDto): ApiResponse - - @POST("auth/signup") - suspend fun signUp(@Body body: SignUpRequestDto): ApiResponse -} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpRequestDto.kt deleted file mode 100644 index ff24ca2..0000000 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpRequestDto.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.sampoom.android.feature.auth.data.remote.dto - -data class SignUpRequestDto( - val name: String, - val workspace: String, - val branch: String, - val position: String, - val email: String, - val password: String -) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt deleted file mode 100644 index 673d57a..0000000 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.sampoom.android.feature.auth.data.repository - -import com.sampoom.android.feature.auth.data.local.preferences.AuthPreferences -import com.sampoom.android.feature.auth.data.mapper.toModel -import com.sampoom.android.feature.auth.data.remote.api.AuthApi -import com.sampoom.android.feature.auth.data.remote.dto.LoginRequestDto -import com.sampoom.android.feature.auth.data.remote.dto.SignUpRequestDto -import com.sampoom.android.feature.auth.domain.model.User -import com.sampoom.android.feature.auth.domain.repository.AuthRepository -import javax.inject.Inject - -class AuthRepositoryImpl @Inject constructor( - private val api: AuthApi, - private val preferences: AuthPreferences -) : AuthRepository { - override suspend fun signUp( - name: String, - workspace: String, - branch: String, - position: String, - email: String, - password: String - ): User { - api.signUp(SignUpRequestDto( - name = name, - workspace = workspace, - branch = branch, - position = position, - email = email, - password = password - )) - return signIn(email, password) - } - - override suspend fun signIn( - email: String, - password: String - ): User { - val dto = api.login(LoginRequestDto(email, password)) - preferences.saveToken(dto.data.accessToken, dto.data.refreshToken) - return dto.data.toModel() - } - - override suspend fun signOut() { preferences.clear() } - - override fun isSignedIn(): Boolean = preferences.hasToken() -} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt deleted file mode 100644 index d8479ae..0000000 --- a/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.sampoom.android.feature.auth.domain.model - -data class User( - val id: Long, - val name: String, - val role: String, - val accessToken: String, - val refreshToken: String, - val expiresIn: Int -) diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt deleted file mode 100644 index 747e985..0000000 --- a/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.sampoom.android.feature.auth.domain.repository - -import com.sampoom.android.feature.auth.domain.model.User - -interface AuthRepository { - suspend fun signUp( - name: String, - workspace: String, - branch: String, - position: String, - email: String, - password: String - ): User - - suspend fun signIn(email: String, password: String): User - suspend fun signOut() - fun isSignedIn(): Boolean -} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/mapper/AuthMappers.kt b/app/src/main/java/com/sampoom/android/feature/user/data/mapper/AuthMappers.kt new file mode 100644 index 0000000..9108f35 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/data/mapper/AuthMappers.kt @@ -0,0 +1,6 @@ +package com.sampoom.android.feature.user.data.mapper + +import com.sampoom.android.feature.user.data.remote.dto.LoginResponseDto +import com.sampoom.android.feature.user.domain.model.User + +fun LoginResponseDto.toModel(): User = User(userId, userName, role, accessToken, refreshToken, expiresIn) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt new file mode 100644 index 0000000..ca324e1 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt @@ -0,0 +1,36 @@ +package com.sampoom.android.feature.user.data.remote.api + +import com.sampoom.android.core.network.ApiResponse +import com.sampoom.android.core.network.ApiSuccessResponse +import com.sampoom.android.feature.user.data.remote.dto.LoginRequestDto +import com.sampoom.android.feature.user.data.remote.dto.SignUpRequestDto +import com.sampoom.android.feature.user.data.remote.dto.SignUpResponseDto +import com.sampoom.android.feature.user.data.remote.dto.LoginResponseDto +import com.sampoom.android.feature.user.data.remote.dto.RefreshRequestDto +import com.sampoom.android.feature.user.data.remote.dto.RefreshResponseDto +import com.sampoom.android.feature.user.data.remote.dto.UpdateRequestDto +import com.sampoom.android.feature.user.data.remote.dto.UpdateResponseDto +import com.sampoom.android.feature.user.data.remote.dto.VerifyResponseDto +import retrofit2.http.Body +import retrofit2.http.PATCH +import retrofit2.http.POST + +interface AuthApi { + @POST("auth/login") + suspend fun login(@Body body: LoginRequestDto): ApiResponse + + @POST("auth/logout") + suspend fun logout(): ApiSuccessResponse + + @POST("auth/refresh") + suspend fun refresh(@Body body: RefreshRequestDto): ApiResponse + + @POST("user/signup") + suspend fun signUp(@Body body: SignUpRequestDto): ApiResponse + + @POST("user/verify") + suspend fun verify(@Body body: LoginRequestDto): ApiResponse + + @PATCH("user/update") + suspend fun update(@Body body: UpdateRequestDto): ApiResponse +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/LoginRequestDto.kt similarity index 57% rename from app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginRequestDto.kt rename to app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/LoginRequestDto.kt index 136b9ac..95427ab 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginRequestDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/LoginRequestDto.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.auth.data.remote.dto +package com.sampoom.android.feature.user.data.remote.dto data class LoginRequestDto( val email: String, diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/LoginResponseDto.kt similarity index 66% rename from app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginResponseDto.kt rename to app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/LoginResponseDto.kt index 3d44982..e48ba2c 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginResponseDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/LoginResponseDto.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.auth.data.remote.dto +package com.sampoom.android.feature.user.data.remote.dto data class LoginResponseDto( val userId: Long, @@ -6,5 +6,5 @@ data class LoginResponseDto( val role: String, val accessToken: String, val refreshToken: String, - val expiresIn: Int + val expiresIn: Long ) diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/RefreshRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/RefreshRequestDto.kt new file mode 100644 index 0000000..667e6c6 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/RefreshRequestDto.kt @@ -0,0 +1,5 @@ +package com.sampoom.android.feature.user.data.remote.dto + +data class RefreshRequestDto( + val refreshToken: String +) diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/RefreshResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/RefreshResponseDto.kt new file mode 100644 index 0000000..e9cfd8b --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/RefreshResponseDto.kt @@ -0,0 +1,7 @@ +package com.sampoom.android.feature.user.data.remote.dto + +data class RefreshResponseDto( + val accessToken: String, + val expiresIn: Long, + val refreshToken: String +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/SignUpRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/SignUpRequestDto.kt new file mode 100644 index 0000000..2f611f8 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/SignUpRequestDto.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.user.data.remote.dto + +data class SignUpRequestDto( + val email: String, + val password: String, + val workspace: String, + val branch: String, + val userName: String, + val position: String +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/SignUpResponseDto.kt similarity index 64% rename from app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpResponseDto.kt rename to app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/SignUpResponseDto.kt index d683a69..f300491 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpResponseDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/SignUpResponseDto.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.auth.data.remote.dto +package com.sampoom.android.feature.user.data.remote.dto data class SignUpResponseDto( val userId: Long, diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateRequestDto.kt new file mode 100644 index 0000000..24b7a03 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateRequestDto.kt @@ -0,0 +1,8 @@ +package com.sampoom.android.feature.user.data.remote.dto + +data class UpdateRequestDto( + val userName: String, + val position: String, + val workspace: String, + val branch: String +) diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateResponseDto.kt new file mode 100644 index 0000000..b5b2cd5 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateResponseDto.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.user.data.remote.dto + +data class UpdateResponseDto( + val userId: Long, + val email: String, + val userName: String, + val position: String, + val workspace: String, + val branch: String +) diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/VerifyRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/VerifyRequestDto.kt new file mode 100644 index 0000000..0ee23f1 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/VerifyRequestDto.kt @@ -0,0 +1,6 @@ +package com.sampoom.android.feature.user.data.remote.dto + +data class VerifyRequestDto( + val email: String, + val password: String +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/VerifyResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/VerifyResponseDto.kt new file mode 100644 index 0000000..9d061f6 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/VerifyResponseDto.kt @@ -0,0 +1,8 @@ +package com.sampoom.android.feature.user.data.remote.dto + +data class VerifyResponseDto( + val userId: Long, + val email: String, + val userName: String, + val role: String +) diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt new file mode 100644 index 0000000..0b7c9f1 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt @@ -0,0 +1,72 @@ +package com.sampoom.android.feature.user.data.repository + +import com.sampoom.android.core.datastore.AuthPreferences +import com.sampoom.android.feature.user.data.mapper.toModel +import com.sampoom.android.feature.user.data.remote.api.AuthApi +import com.sampoom.android.feature.user.data.remote.dto.LoginRequestDto +import com.sampoom.android.feature.user.data.remote.dto.RefreshRequestDto +import com.sampoom.android.feature.user.data.remote.dto.SignUpRequestDto +import com.sampoom.android.feature.user.domain.model.User +import com.sampoom.android.feature.user.domain.repository.AuthRepository +import javax.inject.Inject + +class AuthRepositoryImpl @Inject constructor( + private val api: AuthApi, + private val preferences: AuthPreferences +) : AuthRepository { + override suspend fun signUp( + email: String, + password: String, + workspace: String, + branch: String, + userName: String, + position: String + ): User { + api.signUp(SignUpRequestDto( + email = email, + password = password, + workspace = workspace, + branch = branch, + userName = userName, + position = position + )) + return signIn(email, password) + } + + override suspend fun signIn( + email: String, + password: String + ): User { + val dto = api.login(LoginRequestDto(email, password)) + val user = dto.data.toModel() + preferences.saveUser(user) + return user + } + + override suspend fun signOut() { + api.logout() + preferences.clear() + } + + override suspend fun refreshToken(): Result { + return runCatching { + val refreshToken = preferences.getRefreshToken() ?: throw Exception("No refresh token available") + val response = api.refresh(RefreshRequestDto(refreshToken)) + val existingUser = preferences.getStoredUser() ?: throw Exception("No user information available") + + val updatedUser = existingUser.copy( + accessToken = response.data.accessToken, + refreshToken = response.data.refreshToken, + expiresIn = response.data.expiresIn + ) + preferences.saveUser(updatedUser) + updatedUser + } + } + + override suspend fun clearTokens() { + preferences.clear() + } + + override fun isSignedIn(): Boolean = preferences.hasToken() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/di/AuthModules.kt b/app/src/main/java/com/sampoom/android/feature/user/di/AuthModules.kt similarity index 71% rename from app/src/main/java/com/sampoom/android/feature/auth/di/AuthModules.kt rename to app/src/main/java/com/sampoom/android/feature/user/di/AuthModules.kt index 87b7f09..0be2f12 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/di/AuthModules.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/di/AuthModules.kt @@ -1,8 +1,8 @@ -package com.sampoom.android.feature.auth.di +package com.sampoom.android.feature.user.di -import com.sampoom.android.feature.auth.data.remote.api.AuthApi -import com.sampoom.android.feature.auth.data.repository.AuthRepositoryImpl -import com.sampoom.android.feature.auth.domain.repository.AuthRepository +import com.sampoom.android.feature.user.data.remote.api.AuthApi +import com.sampoom.android.feature.user.data.repository.AuthRepositoryImpl +import com.sampoom.android.feature.user.domain.repository.AuthRepository import dagger.Binds import dagger.Module import dagger.Provides diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/AuthValidator.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/AuthValidator.kt similarity index 98% rename from app/src/main/java/com/sampoom/android/feature/auth/domain/AuthValidator.kt rename to app/src/main/java/com/sampoom/android/feature/user/domain/AuthValidator.kt index b7c4516..5b3bc1e 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/domain/AuthValidator.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/AuthValidator.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.auth.domain +package com.sampoom.android.feature.user.domain import com.sampoom.android.R diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/model/User.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/model/User.kt new file mode 100644 index 0000000..84be2f9 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/model/User.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.user.domain.model + +data class User( + val userId: Long, + val userName: String, + val role: String, + val accessToken: String, + val refreshToken: String, + val expiresIn: Long +) diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt new file mode 100644 index 0000000..b3035ce --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt @@ -0,0 +1,20 @@ +package com.sampoom.android.feature.user.domain.repository + +import com.sampoom.android.feature.user.domain.model.User + +interface AuthRepository { + suspend fun signUp( + email: String, + password: String, + workspace: String, + branch: String, + userName: String, + position: String + ): User + + suspend fun signIn(email: String, password: String): User + suspend fun signOut() + suspend fun refreshToken(): Result + suspend fun clearTokens() + fun isSignedIn(): Boolean +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/CheckLoginStateUseCase.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/CheckLoginStateUseCase.kt new file mode 100644 index 0000000..53d9f90 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/CheckLoginStateUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.user.domain.usecase + +import com.sampoom.android.feature.user.domain.repository.AuthRepository +import javax.inject.Inject + +class CheckLoginStateUseCase @Inject constructor( + private val repository: AuthRepository +) { + operator fun invoke(): Boolean = repository.isSignedIn() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/LoginUseCase.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/LoginUseCase.kt similarity index 57% rename from app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/LoginUseCase.kt rename to app/src/main/java/com/sampoom/android/feature/user/domain/usecase/LoginUseCase.kt index d31282c..1f01e3d 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/LoginUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/LoginUseCase.kt @@ -1,7 +1,7 @@ -package com.sampoom.android.feature.auth.domain.usecase +package com.sampoom.android.feature.user.domain.usecase -import com.sampoom.android.feature.auth.domain.model.User -import com.sampoom.android.feature.auth.domain.repository.AuthRepository +import com.sampoom.android.feature.user.domain.model.User +import com.sampoom.android.feature.user.domain.repository.AuthRepository import javax.inject.Inject class LoginUseCase @Inject constructor( diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignOutUseCase.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignOutUseCase.kt new file mode 100644 index 0000000..fb896b4 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignOutUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.user.domain.usecase + +import com.sampoom.android.feature.user.domain.repository.AuthRepository +import javax.inject.Inject + +class SignOutUseCase @Inject constructor( + private val repository: AuthRepository +) { + suspend operator fun invoke() = repository.signOut() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignUpUseCase.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignUpUseCase.kt similarity index 50% rename from app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignUpUseCase.kt rename to app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignUpUseCase.kt index 9fa4ddd..f64e7f6 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignUpUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignUpUseCase.kt @@ -1,25 +1,25 @@ -package com.sampoom.android.feature.auth.domain.usecase +package com.sampoom.android.feature.user.domain.usecase -import com.sampoom.android.feature.auth.domain.model.User -import com.sampoom.android.feature.auth.domain.repository.AuthRepository +import com.sampoom.android.feature.user.domain.model.User +import com.sampoom.android.feature.user.domain.repository.AuthRepository import javax.inject.Inject class SignUpUseCase @Inject constructor( private val repository: AuthRepository ) { suspend operator fun invoke( - name: String, + email: String, + password: String, workspace: String, branch: String, - position: String, - email: String, - password: String + userName: String, + position: String ): User = repository.signUp( - name = name, + email = email, + password = password, workspace = workspace, branch = branch, - position = position, - email = email, - password = password + userName = userName, + position = position ) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt new file mode 100644 index 0000000..b8b9ec9 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt @@ -0,0 +1,37 @@ +package com.sampoom.android.feature.user.ui + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.sampoom.android.feature.user.domain.usecase.CheckLoginStateUseCase +import com.sampoom.android.feature.user.domain.usecase.SignOutUseCase +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class AuthViewModel @Inject constructor( + private val checkLoginStateUseCase: CheckLoginStateUseCase, + private val signOutUseCase: SignOutUseCase +) : ViewModel() { + private val _isLoggedIn = MutableStateFlow(checkLoginStateUseCase()) + val isLoggedIn: StateFlow = _isLoggedIn.asStateFlow() + + private val _logoutEvent = MutableSharedFlow() + val logoutEvent: SharedFlow = _logoutEvent.asSharedFlow() + + fun updateLoginState() { + _isLoggedIn.value = checkLoginStateUseCase() + } + + fun signOut() = viewModelScope.launch { + signOutUseCase() + _isLoggedIn.value = false + _logoutEvent.emit(Unit) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/LoginScreen.kt similarity index 98% rename from app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt rename to app/src/main/java/com/sampoom/android/feature/user/ui/LoginScreen.kt index a894c8d..c2e758b 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/LoginScreen.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.auth.ui +package com.sampoom.android.feature.user.ui import androidx.compose.foundation.Image import androidx.compose.foundation.clickable @@ -39,7 +39,6 @@ import com.sampoom.android.core.ui.theme.Main500 import com.sampoom.android.core.ui.component.ShowErrorSnackBar import com.sampoom.android.core.ui.component.rememberCommonSnackBarHostState import com.sampoom.android.core.ui.component.TopSnackBarHost -import com.sampoom.android.core.ui.theme.backgroundColor @Composable fun LoginScreen( diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/LoginUiEvent.kt similarity index 82% rename from app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiEvent.kt rename to app/src/main/java/com/sampoom/android/feature/user/ui/LoginUiEvent.kt index ea2af9a..7b68d9d 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/LoginUiEvent.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.auth.ui +package com.sampoom.android.feature.user.ui sealed interface LoginUiEvent { data class EmailChanged(val email: String) : LoginUiEvent diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiState.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/LoginUiState.kt similarity index 91% rename from app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiState.kt rename to app/src/main/java/com/sampoom/android/feature/user/ui/LoginUiState.kt index 2546cab..fb34a74 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/LoginUiState.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.auth.ui +package com.sampoom.android.feature.user.ui data class LoginUiState( val email: String = "", diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/LoginViewModel.kt similarity index 92% rename from app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt rename to app/src/main/java/com/sampoom/android/feature/user/ui/LoginViewModel.kt index e2f404a..0c0f1a9 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/LoginViewModel.kt @@ -1,12 +1,12 @@ -package com.sampoom.android.feature.auth.ui +package com.sampoom.android.feature.user.ui import android.app.Application import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sampoom.android.feature.auth.domain.AuthValidator -import com.sampoom.android.feature.auth.domain.ValidationResult -import com.sampoom.android.feature.auth.domain.usecase.LoginUseCase +import com.sampoom.android.feature.user.domain.AuthValidator +import com.sampoom.android.feature.user.domain.ValidationResult +import com.sampoom.android.feature.user.domain.usecase.LoginUseCase import com.sampoom.android.core.network.serverMessageOrNull import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt similarity index 97% rename from app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt rename to app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt index b252289..d118ccd 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt @@ -1,7 +1,6 @@ -package com.sampoom.android.feature.auth.ui +package com.sampoom.android.feature.user.ui import androidx.compose.foundation.Image -import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement @@ -19,7 +18,6 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar @@ -42,7 +40,6 @@ import com.sampoom.android.core.ui.component.CommonTextField import com.sampoom.android.core.ui.component.ShowErrorSnackBar import com.sampoom.android.core.ui.component.rememberCommonSnackBarHostState import com.sampoom.android.core.ui.component.TopSnackBarHost -import com.sampoom.android.core.ui.theme.backgroundColor @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpUiEvent.kt similarity index 91% rename from app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt rename to app/src/main/java/com/sampoom/android/feature/user/ui/SignUpUiEvent.kt index eb8e77b..2f355e0 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpUiEvent.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.auth.ui +package com.sampoom.android.feature.user.ui sealed interface SignUpUiEvent { data class NameChanged(val name: String) : SignUpUiEvent diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpUiState.kt similarity index 96% rename from app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt rename to app/src/main/java/com/sampoom/android/feature/user/ui/SignUpUiState.kt index 524c1fe..754be8e 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpUiState.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.auth.ui +package com.sampoom.android.feature.user.ui data class SignUpUiState( val name: String = "", diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpViewModel.kt similarity index 93% rename from app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt rename to app/src/main/java/com/sampoom/android/feature/user/ui/SignUpViewModel.kt index 73d29b6..15a5704 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpViewModel.kt @@ -1,12 +1,12 @@ -package com.sampoom.android.feature.auth.ui +package com.sampoom.android.feature.user.ui import android.app.Application import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sampoom.android.feature.auth.domain.AuthValidator -import com.sampoom.android.feature.auth.domain.ValidationResult -import com.sampoom.android.feature.auth.domain.usecase.SignUpUseCase +import com.sampoom.android.feature.user.domain.AuthValidator +import com.sampoom.android.feature.user.domain.ValidationResult +import com.sampoom.android.feature.user.domain.usecase.SignUpUseCase import com.sampoom.android.core.network.serverMessageOrNull import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -137,12 +137,12 @@ class SignUpViewModel @Inject constructor( _state.update { it.copy(loading = true, error = null) } runCatching { singUp( - name = s.name, + email = s.email, + password = s.password, workspace = s.workspace, branch = s.branch, - position = s.position, - email = s.email, - password = s.password + userName = s.name, + position = s.position ) } .onSuccess { _state.update { it.copy(loading = false, success = true) } } From 95ff3c5d0980cd89100fd4360b5a4f450e84eb2f Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Fri, 24 Oct 2025 22:25:13 +0900 Subject: [PATCH 57/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/AppNavHost.kt | 8 -- .../android/core/datastore/AuthPreferences.kt | 82 +++++++++++++------ .../android/core/datastore/CryptoManager.kt | 62 ++++++++++++++ .../android/core/network/NetworkModule.kt | 29 +++---- .../core/network/TokenAuthenticator.kt | 41 ++++++++++ .../android/core/network/TokenInterceptor.kt | 10 ++- .../core/network/TokenRefreshInterceptor.kt | 40 --------- .../data/repository/AuthRepositoryImpl.kt | 3 +- .../user/domain/usecase/ClearTokensUseCase.kt | 10 +++ .../android/feature/user/ui/AuthViewModel.kt | 15 +++- 10 files changed, 203 insertions(+), 97 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/core/datastore/CryptoManager.kt create mode 100644 app/src/main/java/com/sampoom/android/core/network/TokenAuthenticator.kt delete mode 100644 app/src/main/java/com/sampoom/android/core/network/TokenRefreshInterceptor.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/user/domain/usecase/ClearTokensUseCase.kt diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index db35350..d6415c1 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -79,14 +79,6 @@ fun AppNavHost() { val authViewModel: AuthViewModel = hiltViewModel() val isLoggedIn by authViewModel.isLoggedIn.collectAsState() - LaunchedEffect(Unit) { - authViewModel.logoutEvent.collect { - navController.navigate(ROUTE_LOGIN) { - popUpTo(0) { inclusive = true } - } - } - } - NavHost( navController = navController, startDestination = if (isLoggedIn) ROUTE_HOME else ROUTE_LOGIN, diff --git a/app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt b/app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt index 4c30e3c..5610c0b 100644 --- a/app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt +++ b/app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt @@ -18,7 +18,8 @@ private val Context.authDataStore by preferencesDataStore(name = "auth_prefs") @Singleton class AuthPreferences @Inject constructor( - @param:ApplicationContext private val context: Context + @param:ApplicationContext private val context: Context, + private val cryptoManager: CryptoManager ){ private val dataStore = context.authDataStore @@ -26,7 +27,7 @@ class AuthPreferences @Inject constructor( val ACCESS_TOKEN: Preferences.Key = stringPreferencesKey("access_token") val REFRESH_TOKEN: Preferences.Key = stringPreferencesKey("refresh_token") val TOKEN_EXPIRES_AT: Preferences.Key = longPreferencesKey("token_expires_at") - val USER_ID: Preferences.Key = longPreferencesKey("user_id") + val USER_ID: Preferences.Key = stringPreferencesKey("user_id") val USER_NAME: Preferences.Key = stringPreferencesKey("user_name") val USER_ROLE: Preferences.Key = stringPreferencesKey("user_role") } @@ -34,49 +35,74 @@ class AuthPreferences @Inject constructor( suspend fun saveUser(user: User) { val expiresAt = System.currentTimeMillis() + (user.expiresIn * 1000) dataStore.edit { prefs -> - prefs[Keys.ACCESS_TOKEN] = user.accessToken - prefs[Keys.REFRESH_TOKEN] = user.refreshToken + prefs[Keys.ACCESS_TOKEN] = cryptoManager.encrypt(user.accessToken) + prefs[Keys.REFRESH_TOKEN] = cryptoManager.encrypt(user.refreshToken) prefs[Keys.TOKEN_EXPIRES_AT] = expiresAt - prefs[Keys.USER_ID] = user.userId - prefs[Keys.USER_NAME] = user.userName - prefs[Keys.USER_ROLE] = user.role + prefs[Keys.USER_ID] = cryptoManager.encrypt(user.userId.toString()) + prefs[Keys.USER_NAME] = cryptoManager.encrypt(user.userName) + prefs[Keys.USER_ROLE] = cryptoManager.encrypt(user.role) } } - // Suspend save to avoid blocking thread suspend fun saveToken(accessToken: String, refreshToken: String, expiresIn: Long) { val expiresAt = System.currentTimeMillis() + (expiresIn * 1000) dataStore.edit { prefs -> - prefs[Keys.ACCESS_TOKEN] = accessToken - prefs[Keys.REFRESH_TOKEN] = refreshToken + prefs[Keys.ACCESS_TOKEN] = cryptoManager.encrypt(accessToken) + prefs[Keys.REFRESH_TOKEN] = cryptoManager.encrypt(refreshToken) prefs[Keys.TOKEN_EXPIRES_AT] = expiresAt } } - fun getStoredUser(): User? = runBlocking { - val userId = dataStore.data.first()[Keys.USER_ID] - val userName = dataStore.data.first()[Keys.USER_NAME] - val userRole = dataStore.data.first()[Keys.USER_ROLE] - val accessToken = dataStore.data.first()[Keys.ACCESS_TOKEN] - val refreshToken = dataStore.data.first()[Keys.REFRESH_TOKEN] + suspend fun getStoredUser(): User? { + val prefs = dataStore.data.first() + val userId = prefs[Keys.USER_ID] + val userName = prefs[Keys.USER_NAME] + val userRole = prefs[Keys.USER_ROLE] + val accessToken = prefs[Keys.ACCESS_TOKEN] + val refreshToken = prefs[Keys.REFRESH_TOKEN] + val expiresAt = prefs[Keys.TOKEN_EXPIRES_AT] if (userId != null && userName != null && userRole != null && accessToken != null && refreshToken != null) { - User(userId, userName, userRole, accessToken, refreshToken, 0) - } else null + try { + val remaining = expiresAt?.let { + kotlin.math.max(0L, (it - System.currentTimeMillis()) / 1000) + } ?: 0L + + return User( + cryptoManager.decrypt(userId).toLong(), + cryptoManager.decrypt(userName), + cryptoManager.decrypt(userRole), + cryptoManager.decrypt(accessToken), + cryptoManager.decrypt(refreshToken), + remaining + ) + } catch (e: Exception) { + return null + } + } else return null } - // Synchronous getters backed by runBlocking for minimal surface change - fun getAccessToken(): String? = runBlocking { - dataStore.data.first()[Keys.ACCESS_TOKEN] + suspend fun getAccessToken(): String? { + val encrypted = dataStore.data.first()[Keys.ACCESS_TOKEN] ?: return null + return try { + cryptoManager.decrypt(encrypted) + } catch (e: Exception) { + null + } } - fun getRefreshToken(): String? = runBlocking { - dataStore.data.first()[Keys.REFRESH_TOKEN] + suspend fun getRefreshToken(): String? { + val encrypted = dataStore.data.first()[Keys.REFRESH_TOKEN] ?: return null + return try { + cryptoManager.decrypt(encrypted) + } catch (e: Exception) { + null + } } - fun isTokenExpired(): Boolean { - val expiresAt = runBlocking { dataStore.data.first()[Keys.TOKEN_EXPIRES_AT] } + suspend fun isTokenExpired(): Boolean { + val expiresAt = dataStore.data.first()[Keys.TOKEN_EXPIRES_AT] return expiresAt == null || System.currentTimeMillis() > expiresAt } @@ -84,5 +110,9 @@ class AuthPreferences @Inject constructor( dataStore.edit { it.clear() } } - fun hasToken(): Boolean = !getAccessToken().isNullOrEmpty() && !getRefreshToken().isNullOrEmpty() + fun hasToken(): Boolean = runBlocking { + val accessToken = getAccessToken() + val refreshToken = getRefreshToken() + !accessToken.isNullOrEmpty() && !refreshToken.isNullOrEmpty() + } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/datastore/CryptoManager.kt b/app/src/main/java/com/sampoom/android/core/datastore/CryptoManager.kt new file mode 100644 index 0000000..36d0704 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/datastore/CryptoManager.kt @@ -0,0 +1,62 @@ +package com.sampoom.android.core.datastore + +import android.content.Context +import android.security.keystore.KeyGenParameterSpec +import android.security.keystore.KeyProperties +import android.util.Base64 +import dagger.hilt.android.qualifiers.ApplicationContext +import java.security.KeyStore +import javax.crypto.Cipher +import javax.crypto.KeyGenerator +import javax.crypto.spec.GCMParameterSpec +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class CryptoManager @Inject constructor( + @param:ApplicationContext private val context: Context +) { + private val keyAlias = "AuthTokenKey" + private val keyStore = KeyStore.getInstance("AndroidKeyStore") + + init { + keyStore.load(null) + createKeyIfNeeded() + } + + private fun createKeyIfNeeded() { + if (!keyStore.containsAlias(keyAlias)) { + val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore") + val keyGenParameterSpec = KeyGenParameterSpec.Builder( + keyAlias, + KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT + ) + .setBlockModes(KeyProperties.BLOCK_MODE_GCM) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) + .setUserAuthenticationRequired(false) + .setRandomizedEncryptionRequired(true) + .build() + keyGenerator.init(keyGenParameterSpec) + keyGenerator.generateKey() + } + } + + fun encrypt(plaintext: String): String { + val cipher = Cipher.getInstance("AES/GCM/NoPadding") + cipher.init(Cipher.ENCRYPT_MODE, keyStore.getKey(keyAlias, null)) + val iv = cipher.iv + val encrypted = cipher.doFinal(plaintext.toByteArray()) + return Base64.encodeToString(iv + encrypted, Base64.DEFAULT) + } + + fun decrypt(encryptedText: String): String { + val encrypted = Base64.decode(encryptedText, Base64.DEFAULT) + val iv = encrypted.sliceArray(0..11) + val ciphertext = encrypted.sliceArray(12 until encrypted.size) + + val cipher = Cipher.getInstance("AES/GCM/NoPadding") + val spec = GCMParameterSpec(128, iv) + cipher.init(Cipher.DECRYPT_MODE, keyStore.getKey(keyAlias, null), spec) + return String(cipher.doFinal(ciphertext)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt index 3393b9b..cf79aeb 100644 --- a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt +++ b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt @@ -34,33 +34,28 @@ object NetworkModule { return TokenRefreshService(authPreferences) } - @Provides - @Singleton - fun provideTokenRefreshInterceptor( - authPreferences: AuthPreferences, - tokenRefreshService: TokenRefreshService - ): TokenRefreshInterceptor { - return TokenRefreshInterceptor(authPreferences, tokenRefreshService) - } - @Provides @Singleton fun provideOkHttpClient( tokenInterceptor: TokenInterceptor, - tokenRefreshInterceptor: TokenRefreshInterceptor + tokenAuthenticator: TokenAuthenticator ): OkHttpClient { return OkHttpClient.Builder() .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) - .addInterceptor(HttpLoggingInterceptor().apply { - level = if (BuildConfig.DEBUG) - HttpLoggingInterceptor.Level.BODY - else - HttpLoggingInterceptor.Level.NONE - }) + .addInterceptor( + HttpLoggingInterceptor().apply { + level = if (BuildConfig.DEBUG) + HttpLoggingInterceptor.Level.BODY + else + HttpLoggingInterceptor.Level.NONE + redactHeader("Authorization") // 토큰 비식별화 + redactHeader("Cookie") // 쿠키 비식별화 + } + ) .addInterceptor(tokenInterceptor) // 토큰 자동 삽입 - .addInterceptor(tokenRefreshInterceptor) // 토큰 갱신 + .authenticator(tokenAuthenticator) // 토큰 갱신 (Interceptor 대신) .build() } diff --git a/app/src/main/java/com/sampoom/android/core/network/TokenAuthenticator.kt b/app/src/main/java/com/sampoom/android/core/network/TokenAuthenticator.kt new file mode 100644 index 0000000..d0335c9 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/network/TokenAuthenticator.kt @@ -0,0 +1,41 @@ +package com.sampoom.android.core.network + +import com.sampoom.android.core.datastore.AuthPreferences +import kotlinx.coroutines.runBlocking +import okhttp3.Authenticator +import okhttp3.Request +import okhttp3.Response +import okhttp3.Route +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class TokenAuthenticator @Inject constructor( + private val authPreferences: AuthPreferences, + private val tokenRefreshService: TokenRefreshService +) : Authenticator { + override fun authenticate(route: Route?, response: Response): Request? { + // 이미 재시도된 요청인지 확인 + if (response.request.header("X-Retry-Count") != null) { + return null // 재시도 제한 + } + + return try { + val newUser = runBlocking { + tokenRefreshService.refreshToken().getOrThrow() + } + + // 새로운 토큰으로 요청 재시도 + response.request.newBuilder() + .removeHeader("Authorization") + .addHeader("Authorization", "Bearer ${newUser.accessToken}") + .addHeader("X-Retry-Count", "1") // 재시도 표시 + .build() + } catch (e: Exception) { + runBlocking { + authPreferences.clear() + } + null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/network/TokenInterceptor.kt b/app/src/main/java/com/sampoom/android/core/network/TokenInterceptor.kt index 945fc23..290573b 100644 --- a/app/src/main/java/com/sampoom/android/core/network/TokenInterceptor.kt +++ b/app/src/main/java/com/sampoom/android/core/network/TokenInterceptor.kt @@ -1,6 +1,7 @@ package com.sampoom.android.core.network import com.sampoom.android.core.datastore.AuthPreferences +import kotlinx.coroutines.runBlocking import okhttp3.Interceptor import okhttp3.Response import javax.inject.Inject @@ -11,11 +12,14 @@ class TokenInterceptor @Inject constructor( override fun intercept(chain: Interceptor.Chain): Response { val originalRequest = chain.request() - if (originalRequest.header("Authorization") == null) { - val accessToken = authPreferences.getAccessToken() + val existingAuth = originalRequest.header("Authorization") + if (existingAuth.isNullOrBlank()) { + val accessToken = runBlocking { + authPreferences.getAccessToken() + } if (!accessToken.isNullOrEmpty()) { val newRequest = originalRequest.newBuilder() - .addHeader("Authorization", "Bearer $accessToken") + .header("Authorization", "Bearer $accessToken") .build() return chain.proceed(newRequest) } diff --git a/app/src/main/java/com/sampoom/android/core/network/TokenRefreshInterceptor.kt b/app/src/main/java/com/sampoom/android/core/network/TokenRefreshInterceptor.kt deleted file mode 100644 index ce9720f..0000000 --- a/app/src/main/java/com/sampoom/android/core/network/TokenRefreshInterceptor.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.sampoom.android.core.network - -import com.sampoom.android.core.datastore.AuthPreferences -import kotlinx.coroutines.runBlocking -import okhttp3.Interceptor -import okhttp3.Response -import javax.inject.Inject - -class TokenRefreshInterceptor @Inject constructor( - private val authPreferences: AuthPreferences, - private val tokenRefreshService: TokenRefreshService -) : Interceptor { - override fun intercept(chain: Interceptor.Chain): Response { - val request = chain.request() - val response = chain.proceed(request) - - // 401 error - if (response.code == 401) { - try { - val newUser = runBlocking { - tokenRefreshService.refreshToken().getOrThrow() - } - - val newRequest = request.newBuilder() - .removeHeader("Authorization") - .addHeader("Authorization", "Bearer ${newUser.accessToken}") - .build() - - return chain.proceed(newRequest) - } catch (e: Exception) { - runBlocking { - authPreferences.clear() - } - return response - } - } - - return response - } -} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt index 0b7c9f1..244e50a 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt @@ -44,7 +44,8 @@ class AuthRepositoryImpl @Inject constructor( } override suspend fun signOut() { - api.logout() + runCatching { api.logout() } + .onFailure { throw Exception("Failed logout") } preferences.clear() } diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/ClearTokensUseCase.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/ClearTokensUseCase.kt new file mode 100644 index 0000000..c46ace8 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/ClearTokensUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.user.domain.usecase + +import com.sampoom.android.feature.user.domain.repository.AuthRepository +import javax.inject.Inject + +class ClearTokensUseCase @Inject constructor( + private val repository: AuthRepository +) { + suspend operator fun invoke() = repository.clearTokens() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt index b8b9ec9..a05e214 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt @@ -3,6 +3,7 @@ package com.sampoom.android.feature.user.ui import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sampoom.android.feature.user.domain.usecase.CheckLoginStateUseCase +import com.sampoom.android.feature.user.domain.usecase.ClearTokensUseCase import com.sampoom.android.feature.user.domain.usecase.SignOutUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow @@ -17,12 +18,16 @@ import javax.inject.Inject @HiltViewModel class AuthViewModel @Inject constructor( private val checkLoginStateUseCase: CheckLoginStateUseCase, - private val signOutUseCase: SignOutUseCase + private val signOutUseCase: SignOutUseCase, + private val clearTokensUseCase: ClearTokensUseCase ) : ViewModel() { private val _isLoggedIn = MutableStateFlow(checkLoginStateUseCase()) val isLoggedIn: StateFlow = _isLoggedIn.asStateFlow() - private val _logoutEvent = MutableSharedFlow() + private val _logoutEvent = MutableSharedFlow( + replay = 0, + extraBufferCapacity = 1 + ) val logoutEvent: SharedFlow = _logoutEvent.asSharedFlow() fun updateLoginState() { @@ -34,4 +39,10 @@ class AuthViewModel @Inject constructor( _isLoggedIn.value = false _logoutEvent.emit(Unit) } + + fun handleTokenExpired() = viewModelScope.launch { + clearTokensUseCase() + _isLoggedIn.value = false + _logoutEvent.emit(Unit) + } } \ No newline at end of file From d9036e221bec7cce758422a5a99d7828463b4d05 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Fri, 24 Oct 2025 22:26:13 +0900 Subject: [PATCH 58/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sampoom/android/feature/user/data/remote/api/AuthApi.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt index ca324e1..21a588d 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt @@ -10,6 +10,7 @@ import com.sampoom.android.feature.user.data.remote.dto.RefreshRequestDto import com.sampoom.android.feature.user.data.remote.dto.RefreshResponseDto import com.sampoom.android.feature.user.data.remote.dto.UpdateRequestDto import com.sampoom.android.feature.user.data.remote.dto.UpdateResponseDto +import com.sampoom.android.feature.user.data.remote.dto.VerifyRequestDto import com.sampoom.android.feature.user.data.remote.dto.VerifyResponseDto import retrofit2.http.Body import retrofit2.http.PATCH @@ -29,7 +30,7 @@ interface AuthApi { suspend fun signUp(@Body body: SignUpRequestDto): ApiResponse @POST("user/verify") - suspend fun verify(@Body body: LoginRequestDto): ApiResponse + suspend fun verify(@Body body: VerifyRequestDto): ApiResponse @PATCH("user/update") suspend fun update(@Body body: UpdateRequestDto): ApiResponse From 85b24b54e88df3037b0f39a6af265d4516589c4a Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Fri, 24 Oct 2025 22:30:01 +0900 Subject: [PATCH 59/88] =?UTF-8?q?[FIX]=20=EB=B2=84=EC=A0=84=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e6c89f7..f0bcb85 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -33,7 +33,7 @@ android { minSdk = 24 targetSdk = 36 versionCode = 1 - versionName = "1.0" + versionName = "1.0.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } From 3f7780cfeb9b91b3c907dfc05cbf85fe5fc31d58 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Fri, 24 Oct 2025 22:54:16 +0900 Subject: [PATCH 60/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/core/datastore/AuthPreferences.kt | 4 +- .../core/network/TokenAuthenticator.kt | 63 +++++++++++++++++-- .../data/repository/AuthRepositoryImpl.kt | 2 +- .../user/domain/repository/AuthRepository.kt | 2 +- .../domain/usecase/CheckLoginStateUseCase.kt | 2 +- .../android/feature/user/ui/AuthViewModel.kt | 10 ++- 6 files changed, 70 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt b/app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt index 5610c0b..4c30920 100644 --- a/app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt +++ b/app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt @@ -110,9 +110,9 @@ class AuthPreferences @Inject constructor( dataStore.edit { it.clear() } } - fun hasToken(): Boolean = runBlocking { + suspend fun hasToken(): Boolean { val accessToken = getAccessToken() val refreshToken = getRefreshToken() - !accessToken.isNullOrEmpty() && !refreshToken.isNullOrEmpty() + return !accessToken.isNullOrEmpty() && !refreshToken.isNullOrEmpty() } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/network/TokenAuthenticator.kt b/app/src/main/java/com/sampoom/android/core/network/TokenAuthenticator.kt index d0335c9..ea4d018 100644 --- a/app/src/main/java/com/sampoom/android/core/network/TokenAuthenticator.kt +++ b/app/src/main/java/com/sampoom/android/core/network/TokenAuthenticator.kt @@ -2,6 +2,8 @@ package com.sampoom.android.core.network import com.sampoom.android.core.datastore.AuthPreferences import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock import okhttp3.Authenticator import okhttp3.Request import okhttp3.Response @@ -14,6 +16,8 @@ class TokenAuthenticator @Inject constructor( private val authPreferences: AuthPreferences, private val tokenRefreshService: TokenRefreshService ) : Authenticator { + private val refreshMutex = Mutex() + override fun authenticate(route: Route?, response: Response): Request? { // 이미 재시도된 요청인지 확인 if (response.request.header("X-Retry-Count") != null) { @@ -22,20 +26,67 @@ class TokenAuthenticator @Inject constructor( return try { val newUser = runBlocking { - tokenRefreshService.refreshToken().getOrThrow() + refreshMutex.withLock { + tokenRefreshService.refreshToken().getOrThrow() + } } - // 새로운 토큰으로 요청 재시도 response.request.newBuilder() .removeHeader("Authorization") .addHeader("Authorization", "Bearer ${newUser.accessToken}") - .addHeader("X-Retry-Count", "1") // 재시도 표시 + .addHeader("X-Retry-Count", "1") .build() - } catch (e: Exception) { - runBlocking { - authPreferences.clear() + } catch (e: retrofit2.HttpException) { + // HTTP 오류별 분기 처리 + when (e.code()) { + 400, 401 -> { + // 인증 실패: 토큰 삭제 + runBlocking { authPreferences.clear() } + null + } + 403 -> { + // 권한 없음: 토큰 삭제 + runBlocking { authPreferences.clear() } + null + } + 429 -> { + // Rate Limit: 토큰 보존, 재시도는 호출자 판단 + null + } + in 500..599 -> { + // 서버 오류: 토큰 보존 + null + } + else -> { + // 기타 HTTP 오류: 토큰 보존 + null + } } + } catch (e: java.io.IOException) { + // 네트워크 일시 오류: 토큰 보존, 재시도는 호출자 판단 + null + } catch (e: java.net.SocketTimeoutException) { + // 타임아웃: 토큰 보존 + null + } catch (e: java.net.UnknownHostException) { + // DNS 오류: 토큰 보존 + null + } catch (e: java.net.ConnectException) { + // 연결 오류: 토큰 보존 + null + } catch (t: Throwable) { + // 기타 예외: 토큰 보존 null } } + + private suspend fun isTokenExpired(token: String): Boolean { + // 간단한 토큰 만료 체크 (JWT 디코딩 없이) + return try { + val expiresAt = authPreferences.isTokenExpired() + expiresAt + } catch (e: Exception) { + true // 파싱 실패 시 만료로 간주 + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt index 244e50a..620b6e8 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt @@ -69,5 +69,5 @@ class AuthRepositoryImpl @Inject constructor( preferences.clear() } - override fun isSignedIn(): Boolean = preferences.hasToken() + override suspend fun isSignedIn(): Boolean = preferences.hasToken() } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt index b3035ce..fd8b5f9 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt @@ -16,5 +16,5 @@ interface AuthRepository { suspend fun signOut() suspend fun refreshToken(): Result suspend fun clearTokens() - fun isSignedIn(): Boolean + suspend fun isSignedIn(): Boolean } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/CheckLoginStateUseCase.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/CheckLoginStateUseCase.kt index 53d9f90..f63ad59 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/CheckLoginStateUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/CheckLoginStateUseCase.kt @@ -6,5 +6,5 @@ import javax.inject.Inject class CheckLoginStateUseCase @Inject constructor( private val repository: AuthRepository ) { - operator fun invoke(): Boolean = repository.isSignedIn() + suspend operator fun invoke(): Boolean = repository.isSignedIn() } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt index a05e214..d81a398 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt @@ -21,7 +21,7 @@ class AuthViewModel @Inject constructor( private val signOutUseCase: SignOutUseCase, private val clearTokensUseCase: ClearTokensUseCase ) : ViewModel() { - private val _isLoggedIn = MutableStateFlow(checkLoginStateUseCase()) + private val _isLoggedIn = MutableStateFlow(false) val isLoggedIn: StateFlow = _isLoggedIn.asStateFlow() private val _logoutEvent = MutableSharedFlow( @@ -30,7 +30,13 @@ class AuthViewModel @Inject constructor( ) val logoutEvent: SharedFlow = _logoutEvent.asSharedFlow() - fun updateLoginState() { + init { + viewModelScope.launch { + _isLoggedIn.value = checkLoginStateUseCase() + } + } + + fun updateLoginState() = viewModelScope.launch { _isLoggedIn.value = checkLoginStateUseCase() } From 7620a62623529e4ff5c015383d6095c425871312 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Tue, 28 Oct 2025 09:48:55 +0900 Subject: [PATCH 61/88] =?UTF-8?q?[FIX]=20=ED=8F=B0=ED=8A=B8=20=EC=82=AC?= =?UTF-8?q?=EC=9D=B4=EC=A6=88=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/sampoom/android/core/ui/theme/Type.kt | 77 +++++++++++++++---- .../android/feature/user/ui/LoginScreen.kt | 3 +- .../android/feature/user/ui/SignUpScreen.kt | 6 +- 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt b/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt index ed5af64..bc62309 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/theme/Type.kt @@ -4,6 +4,8 @@ import androidx.compose.material3.Typography import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import com.sampoom.android.R val GmarketSansFamily = FontFamily( @@ -15,19 +17,64 @@ val GmarketSansFamily = FontFamily( // Set of Material typography styles to start with private val baseTypography = Typography() val Typography = Typography( - displayLarge = baseTypography.displayLarge.copy(fontFamily = GmarketSansFamily), - displayMedium = baseTypography.displayMedium.copy(fontFamily = GmarketSansFamily), - displaySmall = baseTypography.displaySmall.copy(fontFamily = GmarketSansFamily), - headlineLarge = baseTypography.headlineLarge.copy(fontFamily = GmarketSansFamily), - headlineMedium = baseTypography.headlineMedium.copy(fontFamily = GmarketSansFamily), - headlineSmall = baseTypography.headlineSmall.copy(fontFamily = GmarketSansFamily), - titleLarge = baseTypography.titleLarge.copy(fontFamily = GmarketSansFamily), - titleMedium = baseTypography.titleMedium.copy(fontFamily = GmarketSansFamily), - titleSmall = baseTypography.titleSmall.copy(fontFamily = GmarketSansFamily), - bodyLarge = baseTypography.bodyLarge.copy(fontFamily = GmarketSansFamily), - bodyMedium = baseTypography.bodyMedium.copy(fontFamily = GmarketSansFamily), - bodySmall = baseTypography.bodySmall.copy(fontFamily = GmarketSansFamily), - labelLarge = baseTypography.labelLarge.copy(fontFamily = GmarketSansFamily), - labelMedium = baseTypography.labelMedium.copy(fontFamily = GmarketSansFamily), - labelSmall = baseTypography.labelSmall.copy(fontFamily = GmarketSansFamily) + displayLarge = baseTypography.displayLarge.copy( + fontFamily = GmarketSansFamily, + fontSize = 43.sp + ), + displayMedium = baseTypography.displayMedium.copy( + fontFamily = GmarketSansFamily, + fontSize = 34.sp + ), + displaySmall = baseTypography.displaySmall.copy( + fontFamily = GmarketSansFamily, + fontSize = 27.sp + ), + headlineLarge = baseTypography.headlineLarge.copy( + fontFamily = GmarketSansFamily, + fontSize = 24.sp + ), + headlineMedium = baseTypography.headlineMedium.copy( + fontFamily = GmarketSansFamily, + fontSize = 21.sp + ), + headlineSmall = baseTypography.headlineSmall.copy( + fontFamily = GmarketSansFamily, + fontSize = 18.sp + ), + titleLarge = baseTypography.titleLarge.copy( + fontFamily = GmarketSansFamily, + fontSize = 16.sp + ), + titleMedium = baseTypography.titleMedium.copy( + fontFamily = GmarketSansFamily, + fontSize = 12.sp + ), + titleSmall = baseTypography.titleSmall.copy( + fontFamily = GmarketSansFamily, + fontSize = 11.sp + ), + bodyLarge = baseTypography.bodyLarge.copy( + fontFamily = GmarketSansFamily, + fontSize = 12.sp + ), + bodyMedium = baseTypography.bodyMedium.copy( + fontFamily = GmarketSansFamily, + fontSize = 12.sp + ), + bodySmall = baseTypography.bodySmall.copy( + fontFamily = GmarketSansFamily, + fontSize = 10.sp + ), + labelLarge = baseTypography.labelLarge.copy( + fontFamily = GmarketSansFamily, + fontSize = 11.sp + ), + labelMedium = baseTypography.labelMedium.copy( + fontFamily = GmarketSansFamily, + fontSize = 10.sp + ), + labelSmall = baseTypography.labelSmall.copy( + fontFamily = GmarketSansFamily, + fontSize = 9.sp + ) ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/LoginScreen.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/LoginScreen.kt index c2e758b..3f0bd19 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/LoginScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/LoginScreen.kt @@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.padding import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold +import androidx.compose.material3.ScaffoldDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -67,7 +68,7 @@ fun LoginScreen( onConsumed = { viewModel.consumeError() } ) Scaffold( -// contentWindowInsets = WindowInsets.ime, + contentWindowInsets = ScaffoldDefaults.contentWindowInsets, // snackbarHost = { CommonSnackBarHost(snackBarHostState) } ) { innerPadding -> val focusManager = LocalFocusManager.current diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt index d118ccd..ee1a3b0 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt @@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.ime +import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll @@ -19,6 +20,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.Scaffold +import androidx.compose.material3.ScaffoldDefaults import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable @@ -84,7 +86,7 @@ fun SignUpScreen( } ) }, - contentWindowInsets = WindowInsets.ime, + contentWindowInsets = ScaffoldDefaults.contentWindowInsets, // snackbarHost = { CommonSnackBarHost(snackBarHostState) } ) { innerPadding -> val focusManager = LocalFocusManager.current @@ -195,7 +197,7 @@ fun SignUpScreen( CommonButton( onClick = { viewModel.onEvent(SignUpUiEvent.Submit) }, enabled = state.isValid && !state.loading, - modifier = Modifier.fillMaxWidth(), + modifier = Modifier.fillMaxWidth().navigationBarsPadding(), ) { Text( if (state.loading) stringResource(R.string.signup_button_signup_loading) From aa8adaa81a616dc2ced1e4a349da36a1931dfeb2 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Tue, 28 Oct 2025 09:59:47 +0900 Subject: [PATCH 62/88] =?UTF-8?q?[CHORE]=201.0.2=20=EB=B2=84=EC=A0=84=20?= =?UTF-8?q?=EB=B0=B0=ED=8F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f0bcb85..67ba62b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -32,8 +32,8 @@ android { applicationId = "com.sampoom.android" minSdk = 24 targetSdk = 36 - versionCode = 1 - versionName = "1.0.0" + versionCode = 2 + versionName = "1.0.1" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } From c8ebdad9e0544078d1b51e2e4f660ad343176bf4 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Tue, 28 Oct 2025 12:21:23 +0900 Subject: [PATCH 63/88] =?UTF-8?q?[STYLE]=20=EB=82=B4=EB=B9=84=EA=B2=8C?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EB=B0=94=20=EC=83=89=EC=83=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sampoom/android/MainActivity.kt | 5 +- .../android/app/navigation/AppNavHost.kt | 50 ++++++++++++++++++- app/src/main/res/values-night/themes.xml | 3 ++ app/src/main/res/values/themes.xml | 3 ++ 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/MainActivity.kt b/app/src/main/java/com/sampoom/android/MainActivity.kt index ca423aa..593a197 100644 --- a/app/src/main/java/com/sampoom/android/MainActivity.kt +++ b/app/src/main/java/com/sampoom/android/MainActivity.kt @@ -1,18 +1,21 @@ package com.sampoom.android +import android.os.Build import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge +import androidx.annotation.RequiresApi import com.sampoom.android.app.navigation.AppNavHost import com.sampoom.android.core.ui.theme.SampoomManagementTheme import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint class MainActivity : ComponentActivity() { + @RequiresApi(Build.VERSION_CODES.O) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - enableEdgeToEdge() +// enableEdgeToEdge() setContent { SampoomManagementTheme { AppNavHost() diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index d6415c1..f7ad64f 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -1,6 +1,8 @@ package com.sampoom.android.app.navigation +import android.annotation.SuppressLint import android.os.Build +import androidx.activity.ComponentActivity import androidx.annotation.RequiresApi import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column @@ -11,6 +13,7 @@ import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.NavigationBarItemDefaults import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -19,8 +22,12 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.core.view.WindowInsetsControllerCompat +import androidx.compose.foundation.isSystemInDarkTheme import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.navigation.NavHostController import androidx.navigation.NavType @@ -30,7 +37,12 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import com.sampoom.android.R +import com.sampoom.android.core.ui.theme.Main100 +import com.sampoom.android.core.ui.theme.Main300 +import com.sampoom.android.core.ui.theme.Main500 +import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.backgroundColor +import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.feature.user.ui.AuthViewModel import com.sampoom.android.feature.user.ui.LoginScreen import com.sampoom.android.feature.user.ui.SignUpScreen @@ -72,6 +84,7 @@ sealed class BottomNavItem( object Orders : BottomNavItem(ROUTE_ORDERS, R.string.nav_order, R.drawable.orders) } +@SuppressLint("ContextCastToActivity") @RequiresApi(Build.VERSION_CODES.O) @Composable fun AppNavHost() { @@ -79,9 +92,31 @@ fun AppNavHost() { val authViewModel: AuthViewModel = hiltViewModel() val isLoggedIn by authViewModel.isLoggedIn.collectAsState() + val navBackStackEntry by navController.currentBackStackEntryAsState() + val currentRoute = navBackStackEntry?.destination?.route + val activity = LocalContext.current as ComponentActivity + val homeNavColor = backgroundCardColor() + val elseNavColor = backgroundColor() + val lightIcons = !isSystemInDarkTheme() + + LaunchedEffect(currentRoute, homeNavColor, lightIcons) { + if (currentRoute == ROUTE_HOME) { + val window = activity.window + window.navigationBarColor = homeNavColor.toArgb() + WindowInsetsControllerCompat(window, window.decorView) + .isAppearanceLightNavigationBars = lightIcons + } else { + val window = activity.window + window.navigationBarColor = elseNavColor.toArgb() + WindowInsetsControllerCompat(window, window.decorView) + .isAppearanceLightNavigationBars = lightIcons + } + } + NavHost( navController = navController, - startDestination = if (isLoggedIn) ROUTE_HOME else ROUTE_LOGIN, + startDestination = ROUTE_HOME, +// startDestination = if (isLoggedIn) ROUTE_HOME else ROUTE_LOGIN, modifier = Modifier.background(backgroundColor()) ) { composable(ROUTE_LOGIN) { @@ -201,6 +236,7 @@ fun MainScreen( @Composable fun PartsFab(navController: NavHostController) { FloatingActionButton( + containerColor = Main500, onClick = { navController.navigate(ROUTE_PARTS) { popUpTo(navController.graph.startDestinationId) { @@ -228,12 +264,22 @@ fun BottomNavigationBar(navController: NavHostController) { BottomNavItem.Orders, ) - NavigationBar { + NavigationBar( + containerColor = backgroundCardColor(), + contentColor = Main500, + ) { bottomNavItems.forEach { item -> val navBackStackEntry by navController.currentBackStackEntryAsState() val currentDestination = navBackStackEntry?.destination NavigationBarItem( + colors = NavigationBarItemDefaults.colors( + selectedIconColor = Main500, + unselectedIconColor = textColor(), + selectedTextColor = Main500, + unselectedTextColor = textColor(), + indicatorColor = Main100 + ), icon = { Icon( painterResource(id = item.icon), diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml index d1e3047..ccb60ae 100644 --- a/app/src/main/res/values-night/themes.xml +++ b/app/src/main/res/values-night/themes.xml @@ -2,5 +2,8 @@ \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index d1e3047..fcba5f8 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -2,5 +2,8 @@ \ No newline at end of file From fa60df258cd643385f0645c3e1934aa3b6a17d3b Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Wed, 29 Oct 2025 01:41:42 +0900 Subject: [PATCH 64/88] =?UTF-8?q?[FEAT]=20=EB=8C=80=EC=8B=9C=EB=B3=B4?= =?UTF-8?q?=EB=93=9C=20=ED=99=94=EB=A9=B4=20=EA=B5=AC=ED=98=84,=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=A1=9C=EC=A7=81=20=EC=9D=BC?= =?UTF-8?q?=EB=B6=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/AppNavHost.kt | 57 ++- .../android/core/network/TokenInterceptor.kt | 8 + .../core/ui/component/CommonTextField.kt | 9 +- .../android/core/ui/component/OrderItem.kt | 75 ++++ .../dashboard/data/local/database/.gitkeep | 0 .../dashboard/data/local/preferences/.gitkeep | 0 .../feature/dashboard/data/mapper/.gitkeep | 0 .../dashboard/data/remote/api/.gitkeep | 0 .../dashboard/data/remote/dto/.gitkeep | 0 .../dashboard/data/repository/.gitkeep | 0 .../android/feature/dashboard/di/.gitkeep | 0 .../feature/dashboard/domain/model/.gitkeep | 0 .../dashboard/domain/repository/.gitkeep | 0 .../feature/dashboard/domain/usecase/.gitkeep | 0 .../feature/dashboard/ui/DashboardScreen.kt | 424 ++++++++++++++++++ .../feature/dashboard/ui/DashboardUiEvent.kt | 6 + .../feature/dashboard/ui/DashboardUiState.kt | 9 + .../dashboard/ui/DashboardViewModel.kt | 77 ++++ .../feature/order/ui/OrderListScreen.kt | 50 +-- .../feature/user/data/mapper/AuthMappers.kt | 2 +- .../feature/user/data/remote/api/AuthApi.kt | 5 +- .../user/data/remote/dto/LoginResponseDto.kt | 2 +- .../data/repository/AuthRepositoryImpl.kt | 26 +- .../user/domain/repository/AuthRepository.kt | 4 +- .../android/feature/user/ui/AuthViewModel.kt | 4 + .../android/feature/user/ui/SignUpScreen.kt | 54 ++- app/src/main/res/drawable/money.xml | 5 + app/src/main/res/drawable/warning.xml | 5 + app/src/main/res/values/strings.xml | 13 + 29 files changed, 728 insertions(+), 107 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/core/ui/component/OrderItem.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/data/local/database/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/data/local/preferences/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/data/mapper/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/api/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/dto/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/data/repository/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/di/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/domain/model/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/domain/repository/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/domain/usecase/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardUiEvent.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardUiState.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt create mode 100644 app/src/main/res/drawable/money.xml create mode 100644 app/src/main/res/drawable/warning.xml diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index f7ad64f..86a49dc 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -1,5 +1,6 @@ package com.sampoom.android.app.navigation +import android.R.attr.order import android.annotation.SuppressLint import android.os.Build import androidx.activity.ComponentActivity @@ -47,6 +48,7 @@ import com.sampoom.android.feature.user.ui.AuthViewModel import com.sampoom.android.feature.user.ui.LoginScreen import com.sampoom.android.feature.user.ui.SignUpScreen import com.sampoom.android.feature.cart.ui.CartListScreen +import com.sampoom.android.feature.dashboard.ui.DashboardScreen import com.sampoom.android.feature.order.ui.OrderDetailScreen import com.sampoom.android.feature.order.ui.OrderListScreen import com.sampoom.android.feature.outbound.ui.OutboundListScreen @@ -91,6 +93,7 @@ fun AppNavHost() { val navController = rememberNavController() val authViewModel: AuthViewModel = hiltViewModel() val isLoggedIn by authViewModel.isLoggedIn.collectAsState() + val isLoading by authViewModel.isLoading.collectAsState() val navBackStackEntry by navController.currentBackStackEntryAsState() val currentRoute = navBackStackEntry?.destination?.route @@ -113,10 +116,12 @@ fun AppNavHost() { } } + if (isLoading) { return } + NavHost( navController = navController, - startDestination = ROUTE_HOME, -// startDestination = if (isLoggedIn) ROUTE_HOME else ROUTE_LOGIN, +// startDestination = ROUTE_HOME, + startDestination = if (isLoggedIn) ROUTE_HOME else ROUTE_LOGIN, modifier = Modifier.background(backgroundColor()) ) { composable(ROUTE_LOGIN) { @@ -143,7 +148,7 @@ fun AppNavHost() { } ) } - composable(ROUTE_HOME) { MainScreen(navController) } + composable(ROUTE_HOME) { MainScreen(navController, authViewModel) } composable(ROUTE_PARTS) { PartScreen( onNavigateBack = { @@ -189,7 +194,8 @@ fun AppNavHost() { @RequiresApi(Build.VERSION_CODES.O) @Composable fun MainScreen( - parentNavController: NavHostController + parentNavController: NavHostController, + authViewModel: AuthViewModel ) { val navController = rememberNavController() @@ -203,12 +209,24 @@ fun MainScreen( ) { composable(ROUTE_DASHBOARD) { DashboardScreen( - paddingValues = innerPadding - ) { - parentNavController.navigate(ROUTE_LOGIN) { - popUpTo(0) { inclusive = true } + paddingValues = innerPadding, + onNavigateOrderDetail = { order -> + parentNavController.navigate(routeOrderDetail(1, order.orderId)) + }, + onNavigationOrder = { + navController.navigate(ROUTE_ORDERS) { + popUpTo(ROUTE_DASHBOARD) { saveState = true } + launchSingleTop = true + restoreState = true + } + }, + onLogoutClick = { + authViewModel.signOut() + parentNavController.navigate(ROUTE_LOGIN) { + popUpTo(0) { inclusive = true } + } } - } + ) } composable(ROUTE_OUTBOUND) { OutboundListScreen( @@ -300,25 +318,4 @@ fun BottomNavigationBar(navController: NavHostController) { ) } } -} - -// 임시 화면들 (실제로는 각각의 feature 모듈에서 구현) -@Composable -private fun DashboardScreen( - paddingValues: PaddingValues, - onClick: () -> Unit -) { - val authViewModel: AuthViewModel = hiltViewModel() - // 홈 화면 구현 - Column(Modifier.padding(paddingValues)) { - Text("대시보드 화면", modifier = Modifier.padding(paddingValues)) - - Button(onClick = { - authViewModel.signOut() - onClick() - }) { - Text("로그아웃") - } - } - } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/network/TokenInterceptor.kt b/app/src/main/java/com/sampoom/android/core/network/TokenInterceptor.kt index 290573b..7971e86 100644 --- a/app/src/main/java/com/sampoom/android/core/network/TokenInterceptor.kt +++ b/app/src/main/java/com/sampoom/android/core/network/TokenInterceptor.kt @@ -12,6 +12,14 @@ class TokenInterceptor @Inject constructor( override fun intercept(chain: Interceptor.Chain): Response { val originalRequest = chain.request() + // 스킵 플래그가 있으면 토큰 주입 없이 진행 + if (originalRequest.header("X-No-Auth") == "true") { + val requestWithoutFlag = originalRequest.newBuilder() + .removeHeader("X-No-Auth") + .build() + return chain.proceed(requestWithoutFlag) + } + val existingAuth = originalRequest.header("Authorization") if (existingAuth.isNullOrBlank()) { val accessToken = runBlocking { diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt b/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt index 51d8feb..9044fd7 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.input.InputTransformation.Companion.keyboardOptions import androidx.compose.material.icons.Icons @@ -15,6 +16,7 @@ import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation @@ -37,7 +39,9 @@ fun CommonTextField( isPassword: Boolean = false, variant: TextFieldVariant = TextFieldVariant.Outlined, isError: Boolean = false, - errorMessage: String? = null + errorMessage: String? = null, + imeAction: ImeAction = ImeAction.Next, + keyboardActions: KeyboardActions = KeyboardActions() ) { var passwordVisible by remember { mutableStateOf(false) } @@ -89,7 +93,8 @@ fun CommonTextField( trailingIcon = trailingIconView, supportingText = supportingTextView, visualTransformation = if (isPassword && !passwordVisible) PasswordVisualTransformation() else VisualTransformation.None, - keyboardOptions = KeyboardOptions(keyboardType = if (isPassword) KeyboardType.Password else KeyboardType.Text), + keyboardOptions = KeyboardOptions(keyboardType = if (isPassword) KeyboardType.Password else KeyboardType.Text, imeAction = imeAction), + keyboardActions = keyboardActions, colors = OutlinedTextFieldDefaults.colors( focusedBorderColor = focusedBorderColor, unfocusedBorderColor = unfocusedBorderColor, diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/OrderItem.kt b/app/src/main/java/com/sampoom/android/core/ui/component/OrderItem.kt new file mode 100644 index 0000000..ef8dec0 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/ui/component/OrderItem.kt @@ -0,0 +1,75 @@ +package com.sampoom.android.core.ui.component + +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.sampoom.android.R +import com.sampoom.android.core.ui.theme.backgroundCardColor +import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.core.util.buildOrderTitle +import com.sampoom.android.core.util.formatDate +import com.sampoom.android.feature.order.domain.model.Order + +@RequiresApi(Build.VERSION_CODES.O) +@Composable +fun OrderItem( + order: Order, + onClick: () -> Unit +) { + Card( + onClick = { onClick() }, + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors(containerColor = backgroundCardColor()) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier + .weight(1f) + ) { + Text( + text = buildOrderTitle(order), + style = MaterialTheme.typography.bodyMedium, + maxLines = 1 + ) + Spacer(Modifier.height(4.dp)) + Text( + text = order.agencyName ?: stringResource(R.string.common_slash), + style = MaterialTheme.typography.labelMedium, + color = textSecondaryColor() + ) + } + + Spacer(Modifier.width(12.dp)) + + Column(horizontalAlignment = Alignment.End) { + Text( + text = order.createdAt?.let { formatDate(it) } ?: stringResource(R.string.common_slash), + style = MaterialTheme.typography.labelMedium, + color = textSecondaryColor() + ) + Spacer(Modifier.height(6.dp)) + StatusChip(status = order.status) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/data/local/database/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/data/local/database/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/data/local/preferences/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/data/local/preferences/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/data/mapper/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/data/mapper/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/api/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/api/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/dto/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/dto/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/data/repository/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/data/repository/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/di/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/di/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/domain/model/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/domain/model/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/domain/repository/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/domain/repository/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/domain/usecase/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/domain/usecase/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt new file mode 100644 index 0000000..d567e14 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt @@ -0,0 +1,424 @@ +package com.sampoom.android.feature.dashboard.ui + +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.CornerSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.pulltorefresh.PullToRefreshBox +import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults.Indicator +import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.unit.dp +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.sampoom.android.R +import com.sampoom.android.core.ui.component.EmptyContent +import com.sampoom.android.core.ui.component.ErrorContent +import com.sampoom.android.core.ui.component.OrderItem +import com.sampoom.android.core.ui.theme.Main500 +import com.sampoom.android.core.ui.theme.backgroundCardColor +import com.sampoom.android.core.ui.theme.textColor +import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.feature.order.domain.model.Order + +@RequiresApi(Build.VERSION_CODES.O) +@Composable +fun DashboardScreen( + paddingValues: PaddingValues, + onNavigateOrderDetail: (Order) -> Unit, + onNavigationOrder: () -> Unit, + onLogoutClick: () -> Unit, + viewModel: DashboardViewModel = hiltViewModel() +) { + val errorLabel = stringResource(R.string.common_error) + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + val pullRefreshState = rememberPullToRefreshState() + val isManager = true // TODO: Role 검증 + + LaunchedEffect(errorLabel) { + viewModel.bindLabel(errorLabel) + } + + PullToRefreshBox( + isRefreshing = false, + onRefresh = { viewModel.onEvent(DashboardUiEvent.LoadDashboard) }, + state = pullRefreshState, + modifier = Modifier.fillMaxSize(), + indicator = { + Indicator( + modifier = Modifier.align(Alignment.TopCenter), + isRefreshing = uiState.dashboardLoading, + containerColor = MaterialTheme.colorScheme.primaryContainer, + color = MaterialTheme.colorScheme.onPrimaryContainer, + state = pullRefreshState + ) + } + ) { + Column( + Modifier + .fillMaxSize() + .padding(paddingValues) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Image( + modifier = Modifier + .padding(vertical = 16.dp) + .height(24.dp), + painter = painterResource(id = R.drawable.oneline_logo), + contentDescription = stringResource(R.string.app_name) + ) + + Row { + if (isManager) { + IconButton( + onClick = { } + ) { + Icon( + painter = painterResource(R.drawable.employee), + contentDescription = stringResource(R.string.nav_employee) + ) + } + } + + IconButton( + onClick = { } + ) { + Icon( + painter = painterResource(R.drawable.settings), + contentDescription = stringResource(R.string.nav_setting) + ) + } + } + } + + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + item { + Button(onClick = { onLogoutClick() }) { + Text("로그아웃") + } + } + + item { TitleSection() } + + item { ButtonSection(isManager) } + + item { + OrderListSection( + viewModel = viewModel, + uiState = uiState, + onNavigateOrderDetail = { order -> + onNavigateOrderDetail(order) + }, + onNavigationOrder = { + onNavigationOrder() + } + ) + } + } + } + } +} + +@Composable +fun TitleSection() { + Column( + modifier = Modifier + .fillMaxSize() + .padding(vertical = 24.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Text( + text = "가산디지털단지점", // TODO: Agency Id 받아오기 + style = MaterialTheme.typography.headlineMedium, + fontWeight = FontWeight.Bold, + color = textColor() + ) + + val welcomeText = buildAnnotatedString { + append(stringResource(R.string.dashboard_title_hello)) + + pushStringAnnotation(tag = "NAME", annotation = "name") + withStyle(style = SpanStyle(color = Main500)) { + append("홍길동") // TODO : 이름 받아오기 + } + append(stringResource(R.string.dashboard_title_hello_sir)) + pop() + } + + Text( + text = welcomeText, + style = MaterialTheme.typography.headlineLarge, + fontWeight = FontWeight.Bold, + color = textColor() + ) + + Text( + text = stringResource(R.string.dashboard_title_description), + style = MaterialTheme.typography.bodyLarge, + color = textColor() + ) + } +} + +@Composable +fun ButtonSection( + isManager: Boolean +) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + if (isManager) { + ButtonCard( + modifier = Modifier.border( + 1.dp, + Main500, + shape = RoundedCornerShape(corner = CornerSize(16.dp)) + ), + painter = painterResource(R.drawable.employee), + painterDescription = stringResource(R.string.dashboard_employee), + text = 45.toString(), // TODO : API 연동 + subText = stringResource(R.string.dashboard_employee), + onClick = { } + ) + } + + // 보유 부품, 진행중 주문 + Row( + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + ButtonCard( + modifier = Modifier.weight(1f), + painter = painterResource(R.drawable.parts), + painterDescription = stringResource(R.string.dashboard_parts_on_hand), + text = 1234.toString(), // TODO : API 연동 + subText = stringResource(R.string.dashboard_parts_on_hand), + onClick = { } + ) + + ButtonCard( + modifier = Modifier.weight(1f), + painter = painterResource(R.drawable.orders), + painterDescription = stringResource(R.string.dashboard_parts_in_progress), + text = 23.toString(), // TODO : API 연동 + subText = stringResource(R.string.dashboard_parts_in_progress), + onClick = { } + ) + } + + // 부족 부품, 주문 금액 + Row( + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + ButtonCard( + modifier = Modifier.weight(1f), + painter = painterResource(R.drawable.warning), + painterDescription = stringResource(R.string.dashboard_shortage_of_parts), + text = 19.toString(), // TODO : API 연동 + subText = stringResource(R.string.dashboard_shortage_of_parts), + onClick = { } + ) + + ButtonCard( + modifier = Modifier.weight(1f), + painter = painterResource(R.drawable.money), + painterDescription = stringResource(R.string.dashboard_order_amount), + text = 4123200.toString(), // TODO : API 연동 + subText = stringResource(R.string.dashboard_order_amount), + onClick = { } + ) + } + } +} + +@Composable +fun ButtonCard( + modifier: Modifier, + painter: Painter, + painterDescription: String, + text: String, + subText: String, + onClick: () -> Unit +) { + Card( + modifier = modifier + .fillMaxWidth(), + colors = CardDefaults.cardColors( + containerColor = backgroundCardColor() + ), + onClick = { onClick() }, + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 24.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Icon( + modifier = Modifier + .background(color = Main500, shape = CircleShape) + .padding(8.dp), + painter = painter, + tint = Color.White, + contentDescription = painterDescription, + ) + + Spacer(Modifier.height(16.dp)) + + Text( + text = text, + style = MaterialTheme.typography.headlineMedium, + fontWeight = FontWeight.Bold, + color = textColor() + ) + + Text( + text = subText, + style = MaterialTheme.typography.bodyMedium, + color = textSecondaryColor() + ) + } + } +} + +@RequiresApi(Build.VERSION_CODES.O) +@Composable +fun OrderListSection( + viewModel: DashboardViewModel, + uiState: DashboardUiState, + onNavigateOrderDetail: (Order) -> Unit, + onNavigationOrder: () -> Unit +) { + Column( + modifier = Modifier.fillMaxWidth() + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = stringResource(R.string.dashboard_order_recent_title), + style = MaterialTheme.typography.headlineMedium, + fontWeight = FontWeight.Bold, + color = textColor() + ) + + IconButton( + onClick = { onNavigationOrder() } + ) { + Icon( + painter = painterResource(R.drawable.chevron_right), + contentDescription = stringResource(R.string.common_detail), + tint = textSecondaryColor() + ) + } + } + + when { + uiState.dashboardLoading -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + + uiState.dashboardError != null -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + ErrorContent( + onRetry = { viewModel.onEvent(DashboardUiEvent.RetryDashboard) }, + modifier = Modifier.height(200.dp) + ) + } + } + + uiState.orderList.isEmpty() -> { + Box( + modifier = Modifier + .fillMaxSize(), + contentAlignment = Alignment.Center + ) { + EmptyContent( + message = stringResource(R.string.order_empty_list), + modifier = Modifier.height(200.dp) + ) + } + } + + else -> { + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + items(uiState.orderList) { order -> + OrderItem( + order = order, + onClick = { onNavigateOrderDetail(order) } + ) + } + item { Spacer(Modifier.height(100.dp)) } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardUiEvent.kt new file mode 100644 index 0000000..dfe8294 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardUiEvent.kt @@ -0,0 +1,6 @@ +package com.sampoom.android.feature.dashboard.ui + +sealed interface DashboardUiEvent { + object LoadDashboard : DashboardUiEvent + object RetryDashboard : DashboardUiEvent +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardUiState.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardUiState.kt new file mode 100644 index 0000000..91da8e1 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardUiState.kt @@ -0,0 +1,9 @@ +package com.sampoom.android.feature.dashboard.ui + +import com.sampoom.android.feature.order.domain.model.Order + +data class DashboardUiState( + val orderList: List = emptyList(), + val dashboardLoading: Boolean = false, + val dashboardError: String? = null, +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt new file mode 100644 index 0000000..4ef026a --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt @@ -0,0 +1,77 @@ +package com.sampoom.android.feature.dashboard.ui + +import android.util.Log +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.feature.order.domain.usecase.GetOrderUseCase +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import javax.inject.Inject + +@HiltViewModel +class DashboardViewModel @Inject constructor( + private val getOrderListUseCase: GetOrderUseCase +): ViewModel() { + + private companion object { + private const val TAG = "DashboardViewModel" + } + + private val _uiState = MutableStateFlow(DashboardUiState()) + val uiState : StateFlow = _uiState + + private var errorLabel: String = "" + private var loadJob: Job? = null + + fun bindLabel(error: String) { + errorLabel = error + } + + init { + loadOrderList() + } + + fun onEvent(event: DashboardUiEvent) { + when (event) { + is DashboardUiEvent.LoadDashboard -> loadOrderList() + is DashboardUiEvent.RetryDashboard -> loadOrderList() + } + } + + private fun loadOrderList() { + if (loadJob?.isActive == true) return + loadJob = viewModelScope.launch { + _uiState.update { it.copy(dashboardLoading = true, dashboardError = null) } + + try { + val orderList = withContext(Dispatchers.IO) { getOrderListUseCase() } + _uiState.update { + it.copy( + orderList = orderList.items.take(5), + dashboardLoading = false, + dashboardError = null + ) + } + } catch (ce: CancellationException) { + throw ce + } catch (throwable: Throwable) { + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + dashboardLoading = false, + dashboardError = backendMessage ?: (throwable.message ?: errorLabel ) + ) + } + } + Log.d(TAG, "submit: ${_uiState.value}") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt index 4f88017..c925d13 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt @@ -38,6 +38,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.sampoom.android.R import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent +import com.sampoom.android.core.ui.component.OrderItem import com.sampoom.android.core.ui.component.StatusChip import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor @@ -152,53 +153,4 @@ fun OrderListScreen( } } } -} - -@RequiresApi(Build.VERSION_CODES.O) -@Composable -private fun OrderItem( - order: Order, - onClick: () -> Unit -) { - Card( - onClick = { onClick() }, - modifier = Modifier.fillMaxWidth(), - colors = CardDefaults.cardColors(containerColor = backgroundCardColor()) - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Column( - modifier = Modifier - .weight(1f) - ) { - Text( - text = buildOrderTitle(order), - style = MaterialTheme.typography.bodyMedium, - maxLines = 1 - ) - Spacer(Modifier.height(4.dp)) - Text( - text = order.agencyName ?: stringResource(R.string.common_slash), - style = MaterialTheme.typography.labelMedium, - color = textSecondaryColor() - ) - } - - Spacer(Modifier.width(12.dp)) - - Column(horizontalAlignment = Alignment.End) { - Text( - text = order.createdAt?.let { formatDate(it) } ?: stringResource(R.string.common_slash), - style = MaterialTheme.typography.labelMedium, - color = textSecondaryColor() - ) - Spacer(Modifier.height(6.dp)) - StatusChip(status = order.status) - } - } - } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/mapper/AuthMappers.kt b/app/src/main/java/com/sampoom/android/feature/user/data/mapper/AuthMappers.kt index 9108f35..46bde70 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/mapper/AuthMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/mapper/AuthMappers.kt @@ -3,4 +3,4 @@ package com.sampoom.android.feature.user.data.mapper import com.sampoom.android.feature.user.data.remote.dto.LoginResponseDto import com.sampoom.android.feature.user.domain.model.User -fun LoginResponseDto.toModel(): User = User(userId, userName, role, accessToken, refreshToken, expiresIn) \ No newline at end of file +fun LoginResponseDto.toModel(): User = User(userId, userName.orEmpty(), role, accessToken, refreshToken, expiresIn) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt index 21a588d..a0f251b 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt @@ -13,11 +13,13 @@ import com.sampoom.android.feature.user.data.remote.dto.UpdateResponseDto import com.sampoom.android.feature.user.data.remote.dto.VerifyRequestDto import com.sampoom.android.feature.user.data.remote.dto.VerifyResponseDto import retrofit2.http.Body +import retrofit2.http.Headers import retrofit2.http.PATCH import retrofit2.http.POST interface AuthApi { @POST("auth/login") + @Headers("X-No-Auth: true") suspend fun login(@Body body: LoginRequestDto): ApiResponse @POST("auth/logout") @@ -26,7 +28,8 @@ interface AuthApi { @POST("auth/refresh") suspend fun refresh(@Body body: RefreshRequestDto): ApiResponse - @POST("user/signup") + @POST("auth/signup") + @Headers("X-No-Auth: true") suspend fun signUp(@Body body: SignUpRequestDto): ApiResponse @POST("user/verify") diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/LoginResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/LoginResponseDto.kt index e48ba2c..1d4dfd9 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/LoginResponseDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/LoginResponseDto.kt @@ -2,7 +2,7 @@ package com.sampoom.android.feature.user.data.remote.dto data class LoginResponseDto( val userId: Long, - val userName: String, + val userName: String?, val role: String, val accessToken: String, val refreshToken: String, diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt index 620b6e8..21d2a11 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt @@ -8,6 +8,7 @@ import com.sampoom.android.feature.user.data.remote.dto.RefreshRequestDto import com.sampoom.android.feature.user.data.remote.dto.SignUpRequestDto import com.sampoom.android.feature.user.domain.model.User import com.sampoom.android.feature.user.domain.repository.AuthRepository +import kotlinx.coroutines.CancellationException import javax.inject.Inject class AuthRepositoryImpl @Inject constructor( @@ -43,10 +44,16 @@ class AuthRepositoryImpl @Inject constructor( return user } - override suspend fun signOut() { - runCatching { api.logout() } - .onFailure { throw Exception("Failed logout") } - preferences.clear() + override suspend fun signOut() : Result { + return try { + val dto = api.logout() + if (!dto.success) throw Exception(dto.message) + Result.success(Unit) + } catch (ce: CancellationException) { + throw ce + } catch (t: Throwable) { + Result.failure(t) + } } override suspend fun refreshToken(): Result { @@ -65,8 +72,15 @@ class AuthRepositoryImpl @Inject constructor( } } - override suspend fun clearTokens() { - preferences.clear() + override suspend fun clearTokens(): Result { + return try { + preferences.clear() + Result.success(Unit) + } catch (ce: CancellationException) { + throw ce + } catch (t: Throwable) { + Result.failure(t) + } } override suspend fun isSignedIn(): Boolean = preferences.hasToken() diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt index fd8b5f9..8f4ec2f 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt @@ -13,8 +13,8 @@ interface AuthRepository { ): User suspend fun signIn(email: String, password: String): User - suspend fun signOut() + suspend fun signOut(): Result suspend fun refreshToken(): Result - suspend fun clearTokens() + suspend fun clearTokens(): Result suspend fun isSignedIn(): Boolean } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt index d81a398..66ea0cf 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt @@ -24,6 +24,9 @@ class AuthViewModel @Inject constructor( private val _isLoggedIn = MutableStateFlow(false) val isLoggedIn: StateFlow = _isLoggedIn.asStateFlow() + private val _isLoading = MutableStateFlow(true) + val isLoading: StateFlow = _isLoading.asStateFlow() + private val _logoutEvent = MutableSharedFlow( replay = 0, extraBufferCapacity = 1 @@ -33,6 +36,7 @@ class AuthViewModel @Inject constructor( init { viewModelScope.launch { _isLoggedIn.value = checkLoginStateUseCase() + _isLoading.value = false } } diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt index ee1a3b0..d655dca 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt @@ -12,9 +12,12 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.ime +import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.windowInsetsBottomHeight import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon @@ -30,9 +33,12 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel @@ -55,6 +61,14 @@ fun SignUpScreen( val positionLabel = stringResource(R.string.signup_title_position) val errorLabel = stringResource(R.string.common_error) + val focusManager = LocalFocusManager.current + val nameFocus = remember { FocusRequester() } + val branchFocus = remember { FocusRequester() } + val positionFocus = remember { FocusRequester() } + val emailFocus = remember { FocusRequester() } + val passwordFocus = remember { FocusRequester() } + val passwordCheckFocus = remember { FocusRequester() } + LaunchedEffect(nameLabel, branchLabel, positionLabel, errorLabel) { viewModel.bindLabels(nameLabel, branchLabel, positionLabel, errorLabel) } @@ -119,12 +133,14 @@ fun SignUpScreen( fontSize = labelTextSize ) CommonTextField( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier.fillMaxWidth().focusRequester(nameFocus), value = state.name, onValueChange = { viewModel.onEvent(SignUpUiEvent.NameChanged(it)) }, placeholder = stringResource(R.string.signup_placeholder_name), isError = state.nameError != null, - errorMessage = state.nameError + errorMessage = state.nameError, + imeAction = ImeAction.Next, + keyboardActions = KeyboardActions(onNext = { branchFocus.requestFocus() }) ) Spacer(Modifier.height(8.dp)) Text( @@ -132,12 +148,14 @@ fun SignUpScreen( fontSize = labelTextSize ) CommonTextField( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier.fillMaxWidth().focusRequester(branchFocus), value = state.branch, onValueChange = { viewModel.onEvent(SignUpUiEvent.BranchChanged(it)) }, placeholder = stringResource(R.string.signup_placeholder_branch), isError = state.branchError != null, - errorMessage = state.branchError + errorMessage = state.branchError, + imeAction = ImeAction.Next, + keyboardActions = KeyboardActions(onNext = { positionFocus.requestFocus() }) ) Spacer(Modifier.height(8.dp)) Text( @@ -145,12 +163,14 @@ fun SignUpScreen( fontSize = labelTextSize ) CommonTextField( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier.fillMaxWidth().focusRequester(positionFocus), value = state.position, onValueChange = { viewModel.onEvent(SignUpUiEvent.PositionChanged(it)) }, placeholder = stringResource(R.string.signup_placeholder_position), isError = state.positionError != null, - errorMessage = state.positionError + errorMessage = state.positionError, + imeAction = ImeAction.Next, + keyboardActions = KeyboardActions(onNext = { emailFocus.requestFocus() }) ) Spacer(Modifier.height(8.dp)) Text( @@ -158,12 +178,14 @@ fun SignUpScreen( fontSize = labelTextSize ) CommonTextField( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier.fillMaxWidth().focusRequester(emailFocus), value = state.email, onValueChange = { viewModel.onEvent(SignUpUiEvent.EmailChanged(it)) }, placeholder = stringResource(R.string.signup_placeholder_email), isError = state.emailError != null, - errorMessage = state.emailError + errorMessage = state.emailError, + imeAction = ImeAction.Next, + keyboardActions = KeyboardActions(onNext = { passwordFocus.requestFocus() }) ) Spacer(Modifier.height(8.dp)) Text( @@ -171,13 +193,15 @@ fun SignUpScreen( fontSize = labelTextSize ) CommonTextField( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier.fillMaxWidth().focusRequester(passwordFocus), value = state.password, onValueChange = { viewModel.onEvent(SignUpUiEvent.PasswordChanged(it)) }, placeholder = stringResource(R.string.signup_placeholder_password), isPassword = true, isError = state.passwordError != null, - errorMessage = state.passwordError + errorMessage = state.passwordError, + imeAction = ImeAction.Next, + keyboardActions = KeyboardActions(onNext = { passwordCheckFocus.requestFocus() }) ) Spacer(Modifier.height(8.dp)) Text( @@ -185,13 +209,15 @@ fun SignUpScreen( fontSize = labelTextSize ) CommonTextField( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier.fillMaxWidth().focusRequester(passwordCheckFocus) , value = state.passwordCheck, onValueChange = { viewModel.onEvent(SignUpUiEvent.PasswordCheckChanged(it)) }, placeholder = stringResource(R.string.signup_placeholder_password_check), isPassword = true, isError = state.passwordCheckError != null, - errorMessage = state.passwordCheckError + errorMessage = state.passwordCheckError, + imeAction = ImeAction.Done, + keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }) ) Spacer(Modifier.height(48.dp)) CommonButton( @@ -204,10 +230,8 @@ fun SignUpScreen( else stringResource(R.string.signup_button_signup) ) } - - // per-screen inline error removed in favor of snackbar } } - TopSnackBarHost(snackBarHostState, extraTopPadding = 16.dp) } + TopSnackBarHost(snackBarHostState, extraTopPadding = 16.dp) } \ No newline at end of file diff --git a/app/src/main/res/drawable/money.xml b/app/src/main/res/drawable/money.xml new file mode 100644 index 0000000..542612e --- /dev/null +++ b/app/src/main/res/drawable/money.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/warning.xml b/app/src/main/res/drawable/warning.xml new file mode 100644 index 0000000..bd362d8 --- /dev/null +++ b/app/src/main/res/drawable/warning.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index afe136a..6e6dc2a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -7,6 +7,8 @@ 출고목록 장바구니 주문관리 + 직원관리 + 설정 로그인 @@ -37,6 +39,17 @@ 회원가입 회원 가입 중… + + 안녕하세요, + 님! + 오늘도 효율적인 재고 관리를 시작해보세요. + 직원 관리 + 보유 부품 + 진행중 부품 + 부족 부품 + 주문 금액 + 최근 주문 + 부품조회 검색 From 416c1312a080fcd97d877015252d50ae0e218cf1 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Wed, 29 Oct 2025 11:25:50 +0900 Subject: [PATCH 65/88] =?UTF-8?q?[REFAC]=20Api=20=EB=B0=98=ED=99=98=20?= =?UTF-8?q?=EA=B0=92=20=ED=86=B5=EC=9D=BC,=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/core/datastore/AuthPreferences.kt | 20 ++++- .../data/repository/CartRepositoryImpl.kt | 18 +++-- .../cart/domain/repository/CartRepository.kt | 2 +- .../cart/domain/usecase/AddCartUseCase.kt | 2 +- .../domain/usecase/DeleteAllCartUseCase.kt | 2 +- .../cart/domain/usecase/DeleteCartUseCase.kt | 2 +- .../cart/domain/usecase/GetCartUseCase.kt | 3 +- .../usecase/UpdateCartQuantityUseCase.kt | 2 +- .../feature/cart/ui/CartListViewModel.kt | 37 +++++----- .../dashboard/ui/DashboardViewModel.kt | 35 +++++---- .../data/repository/OrderRepositoryImpl.kt | 38 ++++++---- .../domain/repository/OrderRepository.kt | 6 +- .../domain/usecase/CancelOrderUseCase.kt | 2 +- .../domain/usecase/CreateOrderUseCase.kt | 3 +- .../domain/usecase/GetOrderDetailUseCase.kt | 3 +- .../order/domain/usecase/GetOrderUseCase.kt | 3 +- .../domain/usecase/ReceiveOrderUseCase.kt | 2 +- .../feature/order/ui/OrderDetailViewModel.kt | 35 +++++---- .../feature/order/ui/OrderListViewModel.kt | 35 +++++---- .../data/repository/OutboundRepositoryImpl.kt | 30 ++++---- .../domain/repository/OutboundRepository.kt | 2 +- .../domain/usecase/AddOutboundUseCase.kt | 2 +- .../usecase/DeleteAllOutboundUseCase.kt | 2 +- .../domain/usecase/DeleteOutboundUseCase.kt | 2 +- .../domain/usecase/GetOutboundUseCase.kt | 3 +- .../domain/usecase/ProcessOutboundUseCase.kt | 2 +- .../usecase/UpdateOutboundQuantityUseCase.kt | 2 +- .../outbound/ui/OutboundListViewModel.kt | 35 +++++---- .../data/repository/PartRepositoryImpl.kt | 30 +++++--- .../part/domain/repository/PartRepository.kt | 6 +- .../part/domain/usecase/GetCategoryUseCase.kt | 2 +- .../part/domain/usecase/GetGroupUseCase.kt | 2 +- .../part/domain/usecase/GetPartUseCase.kt | 2 +- .../part/domain/usecase/SearchPartsUseCase.kt | 5 +- .../feature/part/ui/PartListViewModel.kt | 35 +++++---- .../android/feature/part/ui/PartViewModel.kt | 74 +++++++++---------- .../feature/user/data/mapper/AuthMappers.kt | 32 +++++++- .../feature/user/data/remote/api/AuthApi.kt | 30 ++++---- .../data/remote/dto/GetProfileResponseDto.kt | 9 +++ ...questDto.kt => UpdateProfileRequestDto.kt} | 2 +- ...onseDto.kt => UpdateProfileResponseDto.kt} | 3 +- .../user/data/remote/dto/VerifyRequestDto.kt | 6 -- .../user/data/remote/dto/VerifyResponseDto.kt | 8 -- .../data/repository/AuthRepositoryImpl.kt | 63 +++++++++------- .../android/feature/user/domain/model/User.kt | 5 +- .../user/domain/repository/AuthRepository.kt | 5 +- .../user/domain/usecase/ClearTokensUseCase.kt | 2 +- .../user/domain/usecase/LoginUseCase.kt | 3 +- .../user/domain/usecase/SignOutUseCase.kt | 2 +- .../user/domain/usecase/SignUpUseCase.kt | 2 +- .../android/feature/user/ui/LoginViewModel.kt | 13 +++- .../feature/user/ui/SignUpViewModel.kt | 6 +- 52 files changed, 376 insertions(+), 301 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/GetProfileResponseDto.kt rename app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/{UpdateRequestDto.kt => UpdateProfileRequestDto.kt} (81%) rename app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/{UpdateResponseDto.kt => UpdateProfileResponseDto.kt} (77%) delete mode 100644 app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/VerifyRequestDto.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/VerifyResponseDto.kt diff --git a/app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt b/app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt index 4c30920..3644489 100644 --- a/app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt +++ b/app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt @@ -11,7 +11,6 @@ import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton import kotlinx.coroutines.flow.first -import kotlinx.coroutines.runBlocking // Per official guidance, DataStore instance should be single and at top-level. private val Context.authDataStore by preferencesDataStore(name = "auth_prefs") @@ -20,7 +19,7 @@ private val Context.authDataStore by preferencesDataStore(name = "auth_prefs") class AuthPreferences @Inject constructor( @param:ApplicationContext private val context: Context, private val cryptoManager: CryptoManager -){ +) { private val dataStore = context.authDataStore private object Keys { @@ -30,6 +29,9 @@ class AuthPreferences @Inject constructor( val USER_ID: Preferences.Key = stringPreferencesKey("user_id") val USER_NAME: Preferences.Key = stringPreferencesKey("user_name") val USER_ROLE: Preferences.Key = stringPreferencesKey("user_role") + val USER_POSITION: Preferences.Key = stringPreferencesKey("user_position") + val USER_WORKSPACE: Preferences.Key = stringPreferencesKey("user_workspace") + val USER_BRANCH: Preferences.Key = stringPreferencesKey("user_branch") } suspend fun saveUser(user: User) { @@ -41,6 +43,9 @@ class AuthPreferences @Inject constructor( prefs[Keys.USER_ID] = cryptoManager.encrypt(user.userId.toString()) prefs[Keys.USER_NAME] = cryptoManager.encrypt(user.userName) prefs[Keys.USER_ROLE] = cryptoManager.encrypt(user.role) + prefs[Keys.USER_POSITION] = cryptoManager.encrypt(user.position) + prefs[Keys.USER_WORKSPACE] = cryptoManager.encrypt(user.workspace) + prefs[Keys.USER_BRANCH] = cryptoManager.encrypt(user.branch) } } @@ -61,9 +66,13 @@ class AuthPreferences @Inject constructor( val accessToken = prefs[Keys.ACCESS_TOKEN] val refreshToken = prefs[Keys.REFRESH_TOKEN] val expiresAt = prefs[Keys.TOKEN_EXPIRES_AT] + val userPosition = prefs[Keys.USER_POSITION] + val userWorkspace = prefs[Keys.USER_WORKSPACE] + val userBranch = prefs[Keys.USER_BRANCH] if (userId != null && userName != null && userRole != null && - accessToken != null && refreshToken != null) { + accessToken != null && refreshToken != null && userPosition != null && userWorkspace != null && userBranch != null + ) { try { val remaining = expiresAt?.let { kotlin.math.max(0L, (it - System.currentTimeMillis()) / 1000) @@ -75,7 +84,10 @@ class AuthPreferences @Inject constructor( cryptoManager.decrypt(userRole), cryptoManager.decrypt(accessToken), cryptoManager.decrypt(refreshToken), - remaining + remaining, + cryptoManager.decrypt(userPosition), + cryptoManager.decrypt(userWorkspace), + cryptoManager.decrypt(userBranch), ) } catch (e: Exception) { return null diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt index ddc5d07..978b4a9 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt @@ -13,10 +13,12 @@ import kotlin.Result class CartRepositoryImpl @Inject constructor( private val api: CartApi ) : CartRepository { - override suspend fun getCartList(): CartList { - val dto = api.getCartList() - val cartItems = dto.data.map { it.toModel() } - return CartList(items = cartItems) + override suspend fun getCartList(): Result { + return runCatching { + val dto = api.getCartList() + val cartItems = dto.data.map { it.toModel() } + CartList(items = cartItems) + } } override suspend fun addCart( @@ -29,7 +31,7 @@ class CartRepositoryImpl @Inject constructor( Result.success(Unit) } catch (ce: CancellationException) { throw ce - } catch (t : Throwable) { + } catch (t: Throwable) { Result.failure(t) } } @@ -41,7 +43,7 @@ class CartRepositoryImpl @Inject constructor( Result.success(Unit) } catch (ce: CancellationException) { throw ce - } catch (t : Throwable) { + } catch (t: Throwable) { Result.failure(t) } } @@ -53,7 +55,7 @@ class CartRepositoryImpl @Inject constructor( Result.success(Unit) } catch (ce: CancellationException) { throw ce - } catch (t : Throwable) { + } catch (t: Throwable) { Result.failure(t) } } @@ -68,7 +70,7 @@ class CartRepositoryImpl @Inject constructor( Result.success(Unit) } catch (ce: CancellationException) { throw ce - } catch (t : Throwable) { + } catch (t: Throwable) { Result.failure(t) } } diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/repository/CartRepository.kt b/app/src/main/java/com/sampoom/android/feature/cart/domain/repository/CartRepository.kt index 3620388..d6b9df5 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/domain/repository/CartRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/domain/repository/CartRepository.kt @@ -3,7 +3,7 @@ package com.sampoom.android.feature.cart.domain.repository import com.sampoom.android.feature.cart.domain.model.CartList interface CartRepository { - suspend fun getCartList(): CartList + suspend fun getCartList(): Result suspend fun addCart(partId: Long, quantity: Long): Result suspend fun deleteCart(cartItemId: Long): Result suspend fun deleteAllCart(): Result diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/AddCartUseCase.kt b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/AddCartUseCase.kt index 753f6f6..592e4cb 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/AddCartUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/AddCartUseCase.kt @@ -6,5 +6,5 @@ import javax.inject.Inject class AddCartUseCase @Inject constructor( private val repository: CartRepository ) { - suspend operator fun invoke(partId: Long, quantity: Long) = repository.addCart(partId, quantity) + suspend operator fun invoke(partId: Long, quantity: Long): Result = repository.addCart(partId, quantity) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteAllCartUseCase.kt b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteAllCartUseCase.kt index 53c3aff..db5089e 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteAllCartUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteAllCartUseCase.kt @@ -6,5 +6,5 @@ import javax.inject.Inject class DeleteAllCartUseCase @Inject constructor( private val repository: CartRepository ) { - suspend operator fun invoke() = repository.deleteAllCart() + suspend operator fun invoke(): Result = repository.deleteAllCart() } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteCartUseCase.kt b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteCartUseCase.kt index 9b16880..ac54c16 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteCartUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/DeleteCartUseCase.kt @@ -6,5 +6,5 @@ import javax.inject.Inject class DeleteCartUseCase @Inject constructor( private val repository: CartRepository ) { - suspend operator fun invoke(cartItemId: Long) = repository.deleteCart(cartItemId) + suspend operator fun invoke(cartItemId: Long): Result = repository.deleteCart(cartItemId) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/GetCartUseCase.kt b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/GetCartUseCase.kt index 5c71e2b..129615b 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/GetCartUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/GetCartUseCase.kt @@ -1,10 +1,11 @@ package com.sampoom.android.feature.cart.domain.usecase +import com.sampoom.android.feature.cart.domain.model.CartList import com.sampoom.android.feature.cart.domain.repository.CartRepository import javax.inject.Inject class GetCartUseCase @Inject constructor( private val repository: CartRepository ) { - suspend operator fun invoke() = repository.getCartList() + suspend operator fun invoke(): Result = repository.getCartList() } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/UpdateCartQuantityUseCase.kt b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/UpdateCartQuantityUseCase.kt index 0c26680..e6169b6 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/UpdateCartQuantityUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/domain/usecase/UpdateCartQuantityUseCase.kt @@ -6,5 +6,5 @@ import javax.inject.Inject class UpdateCartQuantityUseCase @Inject constructor( private val repository: CartRepository ) { - suspend operator fun invoke(cartItemId: Long, quantity: Long) = repository.updateCartQuantity(cartItemId, quantity) + suspend operator fun invoke(cartItemId: Long, quantity: Long): Result = repository.updateCartQuantity(cartItemId, quantity) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt index 80506ab..0d424c2 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt @@ -61,26 +61,25 @@ class CartListViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(cartLoading = true, cartError = null) } - try { - val cartList = getCartListUseCase() - _uiState.update { - it.copy( - cartList = cartList.items, - cartLoading = false, - cartError = null - ) + getCartListUseCase() + .onSuccess { cartList -> + _uiState.update { + it.copy( + cartList = cartList.items, + cartLoading = false, + cartError = null + ) + } } - } catch (ce: CancellationException) { - throw ce - } catch (throwable: Throwable) { - val backendMessage = throwable.serverMessageOrNull() - _uiState.update { - it.copy( - cartLoading = false, - cartError = backendMessage ?: (throwable.message ?: errorLabel) - ) + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + cartLoading = false, + cartError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } } - } Log.d(TAG, "submit: ${_uiState.value}") } } @@ -89,7 +88,7 @@ class CartListViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(isProcessing = true, processError = null) } - runCatching { createOrderUseCase() } + createOrderUseCase() .onSuccess { orderList -> _uiState.update { it.copy(isProcessing = false, processedOrder = orderList.items) } loadCartList() diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt index 4ef026a..1a7e717 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt @@ -51,26 +51,25 @@ class DashboardViewModel @Inject constructor( loadJob = viewModelScope.launch { _uiState.update { it.copy(dashboardLoading = true, dashboardError = null) } - try { - val orderList = withContext(Dispatchers.IO) { getOrderListUseCase() } - _uiState.update { - it.copy( - orderList = orderList.items.take(5), - dashboardLoading = false, - dashboardError = null - ) + getOrderListUseCase() + .onSuccess { orderList -> + _uiState.update { + it.copy( + orderList = orderList.items.take(5), + dashboardLoading = false, + dashboardError = null + ) + } } - } catch (ce: CancellationException) { - throw ce - } catch (throwable: Throwable) { - val backendMessage = throwable.serverMessageOrNull() - _uiState.update { - it.copy( - dashboardLoading = false, - dashboardError = backendMessage ?: (throwable.message ?: errorLabel ) - ) + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + dashboardLoading = false, + dashboardError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } } - } Log.d(TAG, "submit: ${_uiState.value}") } } diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt index f43065a..86b5da1 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt @@ -10,16 +10,20 @@ import kotlin.coroutines.cancellation.CancellationException class OrderRepositoryImpl @Inject constructor( private val api: OrderApi ) : OrderRepository { - override suspend fun getOrderList(): OrderList { - val dto = api.getOrderList() - val orderItems = dto.data.map { it.toModel() } - return OrderList(items = orderItems) + override suspend fun getOrderList(): Result { + return runCatching { + val dto = api.getOrderList() + val orderItems = dto.data.map { it.toModel() } + OrderList(items = orderItems) + } } - override suspend fun createOrder(): OrderList { - val dto = api.createOrder() - val orderItems = dto.data.map { it.toModel() } - return OrderList(items = orderItems) + override suspend fun createOrder(): Result { + return runCatching { + val dto = api.createOrder() + val orderItems = dto.data.map { it.toModel() } + OrderList(items = orderItems) + } } override suspend fun receiveOrder(orderId: Long): Result { @@ -27,17 +31,19 @@ class OrderRepositoryImpl @Inject constructor( val dto = api.receiveOrder(orderId) if (!dto.success) throw Exception(dto.message) Result.success(Unit) - } catch (ce : CancellationException) { + } catch (ce: CancellationException) { throw ce - } catch (t : Throwable) { + } catch (t: Throwable) { Result.failure(t) } } - override suspend fun getOrderDetail(orderId: Long): OrderList { - val dto = api.getOrderDetail(orderId) - val orderItems = dto.data.map { it.toModel() } - return OrderList(items = orderItems) + override suspend fun getOrderDetail(orderId: Long): Result { + return runCatching { + val dto = api.getOrderDetail(orderId) + val orderItems = dto.data.map { it.toModel() } + OrderList(items = orderItems) + } } override suspend fun cancelOrder(orderId: Long): Result { @@ -45,9 +51,9 @@ class OrderRepositoryImpl @Inject constructor( val dto = api.cancelOrder(orderId) if (!dto.success) throw Exception(dto.message) Result.success(Unit) - } catch (ce : CancellationException) { + } catch (ce: CancellationException) { throw ce - } catch (t : Throwable) { + } catch (t: Throwable) { Result.failure(t) } } diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt index 871b70a..3d3d000 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt @@ -3,9 +3,9 @@ package com.sampoom.android.feature.order.domain.repository import com.sampoom.android.feature.order.domain.model.OrderList interface OrderRepository { - suspend fun getOrderList(): OrderList - suspend fun createOrder(): OrderList + suspend fun getOrderList(): Result + suspend fun createOrder(): Result suspend fun receiveOrder(orderId: Long): Result - suspend fun getOrderDetail(orderId: Long): OrderList + suspend fun getOrderDetail(orderId: Long): Result suspend fun cancelOrder(orderId: Long): Result } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CancelOrderUseCase.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CancelOrderUseCase.kt index e3e8f86..a3c393d 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CancelOrderUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CancelOrderUseCase.kt @@ -6,5 +6,5 @@ import javax.inject.Inject class CancelOrderUseCase @Inject constructor( private val repository: OrderRepository ){ - suspend operator fun invoke(orderId: Long) = repository.cancelOrder(orderId) + suspend operator fun invoke(orderId: Long): Result = repository.cancelOrder(orderId) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CreateOrderUseCase.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CreateOrderUseCase.kt index c26aafe..b74db85 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CreateOrderUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CreateOrderUseCase.kt @@ -1,10 +1,11 @@ package com.sampoom.android.feature.order.domain.usecase +import com.sampoom.android.feature.order.domain.model.OrderList import com.sampoom.android.feature.order.domain.repository.OrderRepository import javax.inject.Inject class CreateOrderUseCase @Inject constructor( private val repository: OrderRepository ){ - suspend operator fun invoke() = repository.createOrder() + suspend operator fun invoke(): Result = repository.createOrder() } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderDetailUseCase.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderDetailUseCase.kt index 1898e1b..a3656d4 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderDetailUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderDetailUseCase.kt @@ -1,10 +1,11 @@ package com.sampoom.android.feature.order.domain.usecase +import com.sampoom.android.feature.order.domain.model.OrderList import com.sampoom.android.feature.order.domain.repository.OrderRepository import javax.inject.Inject class GetOrderDetailUseCase @Inject constructor( private val repository: OrderRepository ) { - suspend operator fun invoke(orderId: Long) = repository.getOrderDetail(orderId) + suspend operator fun invoke(orderId: Long): Result = repository.getOrderDetail(orderId) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderUseCase.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderUseCase.kt index ad20ec3..02bc766 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderUseCase.kt @@ -1,10 +1,11 @@ package com.sampoom.android.feature.order.domain.usecase +import com.sampoom.android.feature.order.domain.model.OrderList import com.sampoom.android.feature.order.domain.repository.OrderRepository import javax.inject.Inject class GetOrderUseCase @Inject constructor( private val repository: OrderRepository ){ - suspend operator fun invoke() = repository.getOrderList() + suspend operator fun invoke(): Result = repository.getOrderList() } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/ReceiveOrderUseCase.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/ReceiveOrderUseCase.kt index 76ce9b1..5a05f03 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/ReceiveOrderUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/ReceiveOrderUseCase.kt @@ -6,5 +6,5 @@ import javax.inject.Inject class ReceiveOrderUseCase @Inject constructor( private val repository: OrderRepository ) { - suspend operator fun invoke(orderId: Long) = repository.receiveOrder(orderId) + suspend operator fun invoke(orderId: Long): Result = repository.receiveOrder(orderId) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt index a0bd0af..d4b57a4 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt @@ -70,26 +70,25 @@ class OrderDetailViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(orderDetailLoading = true, orderDetailError = null) } - try { - val orderList = getOrderDetailUseCase(orderId) - _uiState.update { - it.copy( - orderDetail = orderList.items, - orderDetailLoading = false, - orderDetailError = null - ) + getOrderDetailUseCase(orderId) + .onSuccess { orderList -> + _uiState.update { + it.copy( + orderDetail = orderList.items, + orderDetailLoading = false, + orderDetailError = null + ) + } } - } catch (ce : CancellationException) { - throw ce - } catch (throwable : Throwable) { - val backendMessage = throwable.serverMessageOrNull() - _uiState.update { - it.copy( - orderDetailLoading = false, - orderDetailError = backendMessage ?: (throwable.message ?: errorLabel) - ) + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + orderDetailLoading = false, + orderDetailError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } } - } Log.d(TAG, "submit: ${_uiState.value}") } } diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt index 0a4fab1..4f2d1f9 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt @@ -51,26 +51,25 @@ class OrderListViewModel @Inject constructor( loadJob = viewModelScope.launch { _uiState.update { it.copy(orderLoading = true, orderError = null) } - try { - val orderList = withContext(Dispatchers.IO) { getOrderListUseCase() } - _uiState.update { - it.copy( - orderList = orderList.items, - orderLoading = false, - orderError = null - ) + getOrderListUseCase() + .onSuccess { orderList -> + _uiState.update { + it.copy( + orderList = orderList.items, + orderLoading = false, + orderError = null + ) + } } - } catch (ce: CancellationException) { - throw ce - } catch (throwable: Throwable) { - val backendMessage = throwable.serverMessageOrNull() - _uiState.update { - it.copy( - orderLoading = false, - orderError = backendMessage ?: (throwable.message ?: errorLabel ) - ) + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + orderLoading = false, + orderError = backendMessage ?: (throwable.message ?: errorLabel ) + ) + } } - } Log.d(TAG, "submit: ${_uiState.value}") } } diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt index 71f3245..353ec6d 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt @@ -12,10 +12,12 @@ import kotlin.coroutines.cancellation.CancellationException class OutboundRepositoryImpl @Inject constructor( private val api: OutboundApi ) : OutboundRepository { - override suspend fun getOutboundList(): OutboundList { - val dto = api.getOutboundList() - val outboundItems = dto.data.map { it.toModel() } - return OutboundList(items = outboundItems) + override suspend fun getOutboundList(): Result { + return runCatching { + val dto = api.getOutboundList() + val outboundItems = dto.data.map { it.toModel() } + OutboundList(items = outboundItems) + } } override suspend fun processOutbound(): Result { @@ -23,9 +25,9 @@ class OutboundRepositoryImpl @Inject constructor( val dto = api.processOutbound() if (!dto.success) throw Exception(dto.message) Result.success(Unit) - } catch (ce : CancellationException) { + } catch (ce: CancellationException) { throw ce - } catch (t : Throwable) { + } catch (t: Throwable) { Result.failure(t) } } @@ -38,9 +40,9 @@ class OutboundRepositoryImpl @Inject constructor( val dto = api.addOutbound(AddOutboundRequestDto(partId, quantity)) if (!dto.success) throw Exception(dto.message) Result.success(Unit) - } catch (ce : CancellationException) { + } catch (ce: CancellationException) { throw ce - } catch (t : Throwable) { + } catch (t: Throwable) { Result.failure(t) } } @@ -50,9 +52,9 @@ class OutboundRepositoryImpl @Inject constructor( val dto = api.deleteOutbound(outboundId) if (!dto.success) throw Exception(dto.message) Result.success(Unit) - } catch (ce : CancellationException) { + } catch (ce: CancellationException) { throw ce - } catch (t : Throwable) { + } catch (t: Throwable) { Result.failure(t) } } @@ -62,9 +64,9 @@ class OutboundRepositoryImpl @Inject constructor( val dto = api.deleteAllOutbound() if (!dto.success) throw Exception(dto.message) Result.success(Unit) - } catch (ce : CancellationException) { + } catch (ce: CancellationException) { throw ce - } catch (t : Throwable) { + } catch (t: Throwable) { Result.failure(t) } } @@ -77,9 +79,9 @@ class OutboundRepositoryImpl @Inject constructor( val dto = api.updateOutbound(outboundId, UpdateOutboundRequestDto(quantity)) if (!dto.success) throw Exception(dto.message) Result.success(Unit) - } catch (ce : CancellationException) { + } catch (ce: CancellationException) { throw ce - } catch (t : Throwable) { + } catch (t: Throwable) { Result.failure(t) } } diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/repository/OutboundRepository.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/repository/OutboundRepository.kt index 8633113..cbe897b 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/domain/repository/OutboundRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/repository/OutboundRepository.kt @@ -3,7 +3,7 @@ package com.sampoom.android.feature.outbound.domain.repository import com.sampoom.android.feature.outbound.domain.model.OutboundList interface OutboundRepository { - suspend fun getOutboundList(): OutboundList + suspend fun getOutboundList(): Result suspend fun processOutbound(): Result suspend fun addOutbound(partId: Long, quantity: Long): Result suspend fun deleteOutbound(outboundId: Long): Result diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/AddOutboundUseCase.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/AddOutboundUseCase.kt index d00c5d8..d119f92 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/AddOutboundUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/AddOutboundUseCase.kt @@ -6,5 +6,5 @@ import javax.inject.Inject class AddOutboundUseCase @Inject constructor( private val repository: OutboundRepository ) { - suspend operator fun invoke(partId: Long, quantity: Long) = repository.addOutbound(partId, quantity) + suspend operator fun invoke(partId: Long, quantity: Long): Result = repository.addOutbound(partId, quantity) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteAllOutboundUseCase.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteAllOutboundUseCase.kt index 5bbaef5..0db5a79 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteAllOutboundUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteAllOutboundUseCase.kt @@ -6,5 +6,5 @@ import javax.inject.Inject class DeleteAllOutboundUseCase @Inject constructor( private val repository: OutboundRepository ){ - suspend operator fun invoke() = repository.deleteAllOutbound() + suspend operator fun invoke(): Result = repository.deleteAllOutbound() } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteOutboundUseCase.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteOutboundUseCase.kt index 9c3a12f..93eb3df 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteOutboundUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/DeleteOutboundUseCase.kt @@ -6,5 +6,5 @@ import javax.inject.Inject class DeleteOutboundUseCase @Inject constructor( private val repository: OutboundRepository ){ - suspend operator fun invoke(outboundId: Long) = repository.deleteOutbound(outboundId) + suspend operator fun invoke(outboundId: Long): Result = repository.deleteOutbound(outboundId) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/GetOutboundUseCase.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/GetOutboundUseCase.kt index 20047c4..7189715 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/GetOutboundUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/GetOutboundUseCase.kt @@ -1,10 +1,11 @@ package com.sampoom.android.feature.outbound.domain.usecase +import com.sampoom.android.feature.outbound.domain.model.OutboundList import com.sampoom.android.feature.outbound.domain.repository.OutboundRepository import javax.inject.Inject class GetOutboundUseCase @Inject constructor( private val repository: OutboundRepository ) { - suspend operator fun invoke() = repository.getOutboundList() + suspend operator fun invoke(): Result = repository.getOutboundList() } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/ProcessOutboundUseCase.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/ProcessOutboundUseCase.kt index 221570a..ab54b7d 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/ProcessOutboundUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/ProcessOutboundUseCase.kt @@ -6,5 +6,5 @@ import javax.inject.Inject class ProcessOutboundUseCase @Inject constructor( private val repository: OutboundRepository ){ - suspend operator fun invoke() = repository.processOutbound() + suspend operator fun invoke(): Result = repository.processOutbound() } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/UpdateOutboundQuantityUseCase.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/UpdateOutboundQuantityUseCase.kt index 31166db..dcf4cf7 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/UpdateOutboundQuantityUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/usecase/UpdateOutboundQuantityUseCase.kt @@ -6,5 +6,5 @@ import javax.inject.Inject class UpdateOutboundQuantityUseCase @Inject constructor( private val repository: OutboundRepository ) { - suspend operator fun invoke(outboundId: Long, quantity: Long) = repository.updateOutboundQuantity(outboundId, quantity) + suspend operator fun invoke(outboundId: Long, quantity: Long): Result = repository.updateOutboundQuantity(outboundId, quantity) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt index 8a49c79..90bae80 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt @@ -60,26 +60,25 @@ class OutboundListViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(outboundLoading = true, outboundError = null) } - try { - val outboundList = getOutboundUseCase() - _uiState.update { - it.copy( - outboundList = outboundList.items, - outboundLoading = false, - outboundError = null - ) + getOutboundUseCase() + .onSuccess { outboundList -> + _uiState.update { + it.copy( + outboundList = outboundList.items, + outboundLoading = false, + outboundError = null + ) + } } - } catch (ce: CancellationException) { - throw ce - } catch (throwable: Throwable) { - val backendMessage = throwable.serverMessageOrNull() - _uiState.update { - it.copy( - outboundLoading = false, - outboundError = backendMessage ?: (throwable.message ?: errorLabel) - ) + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + outboundLoading = false, + outboundError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } } - } Log.d(TAG, "submit: ${_uiState.value}") } } diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt index cd0694a..51e0a18 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt @@ -18,22 +18,28 @@ class PartRepositoryImpl @Inject constructor( private val api: PartApi, private val pagingSourceFactory: PartPagingSource.Factory ) : PartRepository { - override suspend fun getCategoryList(): CategoryList { - val dto = api.getCategoryList() - val categoryItems = dto.data.map { it.toModel() } - return CategoryList(items = categoryItems) + override suspend fun getCategoryList(): Result { + return runCatching { + val dto = api.getCategoryList() + val categoryItems = dto.data.map { it.toModel() } + CategoryList(items = categoryItems) + } } - override suspend fun getGroupList(categoryId: Long): GroupList { - val response = api.getGroupList(categoryId) - val groupItems = response.data.map { it.toModel() } - return GroupList(items = groupItems) + override suspend fun getGroupList(categoryId: Long): Result { + return runCatching { + val response = api.getGroupList(categoryId) + val groupItems = response.data.map { it.toModel() } + GroupList(items = groupItems) + } } - override suspend fun getPartList(groupId: Long): PartList { - val response = api.getPartList(groupId) - val partItems = response.data.map { it.toModel() } - return PartList(items = partItems) + override suspend fun getPartList(groupId: Long): Result { + return runCatching { + val response = api.getPartList(groupId) + val partItems = response.data.map { it.toModel() } + PartList(items = partItems) + } } override fun searchParts(keyword: String): Flow> { diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt index d5fbdd1..5947b52 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/repository/PartRepository.kt @@ -8,8 +8,8 @@ import com.sampoom.android.feature.part.domain.model.SearchResult import kotlinx.coroutines.flow.Flow interface PartRepository { - suspend fun getCategoryList(): CategoryList - suspend fun getGroupList(categoryId: Long): GroupList - suspend fun getPartList(groupId: Long): PartList + suspend fun getCategoryList(): Result + suspend fun getGroupList(categoryId: Long): Result + suspend fun getPartList(groupId: Long): Result fun searchParts(keyword: String): Flow> } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetCategoryUseCase.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetCategoryUseCase.kt index 3029262..c9aeaa6 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetCategoryUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetCategoryUseCase.kt @@ -7,5 +7,5 @@ import javax.inject.Inject class GetCategoryUseCase @Inject constructor( private val repository: PartRepository ) { - suspend operator fun invoke(): CategoryList = repository.getCategoryList() + suspend operator fun invoke(): Result = repository.getCategoryList() } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetGroupUseCase.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetGroupUseCase.kt index 256be21..4d57546 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetGroupUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetGroupUseCase.kt @@ -7,5 +7,5 @@ import javax.inject.Inject class GetGroupUseCase @Inject constructor( private val repository: PartRepository ) { - suspend operator fun invoke(categoryId: Long): GroupList = repository.getGroupList(categoryId) + suspend operator fun invoke(categoryId: Long): Result = repository.getGroupList(categoryId) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetPartUseCase.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetPartUseCase.kt index 93ca316..211c2ac 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetPartUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/GetPartUseCase.kt @@ -7,5 +7,5 @@ import javax.inject.Inject class GetPartUseCase @Inject constructor( private val repository: PartRepository ) { - suspend operator fun invoke(groupId: Long): PartList = repository.getPartList(groupId) + suspend operator fun invoke(groupId: Long): Result = repository.getPartList(groupId) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/SearchPartsUseCase.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/SearchPartsUseCase.kt index dd13cef..9dfe67c 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/SearchPartsUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/usecase/SearchPartsUseCase.kt @@ -9,7 +9,6 @@ import javax.inject.Inject class SearchPartsUseCase @Inject constructor( private val repository: PartRepository ) { - operator fun invoke(keyword: String): Flow> { - return repository.searchParts(keyword) - } + operator fun invoke(keyword: String): Flow> = repository.searchParts(keyword) + } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt index 80897f3..bd8e9b8 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt @@ -55,26 +55,25 @@ class PartListViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(partListLoading = true, partListError = null) } - try { - val partList = getPartListUseCase(groupId) - _uiState.update { - it.copy( - partList = partList.items, - partListLoading = false, - partListError = null - ) + getPartListUseCase(groupId) + .onSuccess { partList -> + _uiState.update { + it.copy( + partList = partList.items, + partListLoading = false, + partListError = null + ) + } } - } catch (ce: CancellationException) { - throw ce - } catch (throwable: Throwable) { - val backendMessage = throwable.serverMessageOrNull() - _uiState.update { - it.copy( - partListLoading = false, - partListError = backendMessage ?: (throwable.message ?: errorLabel) - ) + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + partListLoading = false, + partListError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } } - } Log.d(TAG, "submit: ${_uiState.value}") } } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt index c51775b..474a463 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt @@ -87,26 +87,25 @@ class PartViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(categoryLoading = true, categoryError = null) } - try { - val categoryList = getCategoryUseCase() - _uiState.update { - it.copy( - categoryList = categoryList.items, - categoryLoading = false, - categoryError = null - ) + getCategoryUseCase() + .onSuccess { categoryList -> + _uiState.update { + it.copy( + categoryList = categoryList.items, + categoryLoading = false, + categoryError = null + ) + } } - } catch (ce: CancellationException) { - throw ce - } catch (throwable: Throwable) { - val backendMessage = throwable.serverMessageOrNull() - _uiState.update { - it.copy( - categoryLoading = false, - categoryError = backendMessage ?: (throwable.message ?: errorLabel) - ) + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + _uiState.update { + it.copy( + categoryLoading = false, + categoryError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } } - } Log.d(TAG, "loadCategory: ${_uiState.value}") } } @@ -124,29 +123,26 @@ class PartViewModel @Inject constructor( groupLoadJob = viewModelScope.launch { _uiState.update { it.copy(groupLoading = true, groupError = null) } - try { - val groupList = getGroupUseCase(categoryId) - // 최신 선택과 불일치하면 무시 - if (_uiState.value.selectedCategory?.id != categoryId) return@launch - _uiState.update { - it.copy( - groupList = groupList.items, - groupLoading = false, - groupError = null - ) + getGroupUseCase(categoryId) + .onSuccess { groupList -> + _uiState.update { + it.copy( + groupList = groupList.items, + groupLoading = false, + groupError = null + ) + } } - } catch (ce: CancellationException) { - throw ce - } catch (throwable: Throwable) { - val backendMessage = throwable.serverMessageOrNull() - if (_uiState.value.selectedCategory?.id != categoryId) return@launch - _uiState.update { - it.copy( - groupLoading = false, - groupError = backendMessage ?: (throwable.message ?: errorLabel) - ) + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + if (_uiState.value.selectedCategory?.id != categoryId) return@launch + _uiState.update { + it.copy( + groupLoading = false, + groupError = backendMessage ?: (throwable.message ?: errorLabel) + ) + } } - } Log.d(TAG, "loadGroup: ${_uiState.value}") } } diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/mapper/AuthMappers.kt b/app/src/main/java/com/sampoom/android/feature/user/data/mapper/AuthMappers.kt index 46bde70..2e39f15 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/mapper/AuthMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/mapper/AuthMappers.kt @@ -1,6 +1,36 @@ package com.sampoom.android.feature.user.data.mapper +import com.sampoom.android.feature.user.data.remote.dto.GetProfileResponseDto import com.sampoom.android.feature.user.data.remote.dto.LoginResponseDto import com.sampoom.android.feature.user.domain.model.User -fun LoginResponseDto.toModel(): User = User(userId, userName.orEmpty(), role, accessToken, refreshToken, expiresIn) \ No newline at end of file +fun LoginResponseDto.toModel(): User = User( + userId = userId, + userName = "", + role = role, + accessToken = accessToken, + refreshToken = refreshToken, + expiresIn = expiresIn, + position = "", + workspace = "", + branch = "" +) + +fun GetProfileResponseDto.toModel(): User = User( + userId = userId, + userName = userName, + role = "", + accessToken = "", + refreshToken = "", + expiresIn = 0L, + position = position, + workspace = workspace, + branch = branch +) + +fun User.mergeWith(profile: User): User = this.copy( + userName = profile.userName, + position = profile.position, + workspace = profile.workspace, + branch = profile.branch +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt index a0f251b..b6d6ec9 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt @@ -8,33 +8,33 @@ import com.sampoom.android.feature.user.data.remote.dto.SignUpResponseDto import com.sampoom.android.feature.user.data.remote.dto.LoginResponseDto import com.sampoom.android.feature.user.data.remote.dto.RefreshRequestDto import com.sampoom.android.feature.user.data.remote.dto.RefreshResponseDto -import com.sampoom.android.feature.user.data.remote.dto.UpdateRequestDto -import com.sampoom.android.feature.user.data.remote.dto.UpdateResponseDto -import com.sampoom.android.feature.user.data.remote.dto.VerifyRequestDto -import com.sampoom.android.feature.user.data.remote.dto.VerifyResponseDto +import com.sampoom.android.feature.user.data.remote.dto.UpdateProfileRequestDto +import com.sampoom.android.feature.user.data.remote.dto.UpdateProfileResponseDto +import com.sampoom.android.feature.user.data.remote.dto.GetProfileResponseDto import retrofit2.http.Body +import retrofit2.http.GET import retrofit2.http.Headers import retrofit2.http.PATCH import retrofit2.http.POST interface AuthApi { - @POST("auth/login") + @POST("auth/signup") @Headers("X-No-Auth: true") - suspend fun login(@Body body: LoginRequestDto): ApiResponse - - @POST("auth/logout") - suspend fun logout(): ApiSuccessResponse + suspend fun signUp(@Body body: SignUpRequestDto): ApiResponse @POST("auth/refresh") suspend fun refresh(@Body body: RefreshRequestDto): ApiResponse - @POST("auth/signup") + @POST("auth/logout") + suspend fun logout(): ApiSuccessResponse + + @POST("auth/login") @Headers("X-No-Auth: true") - suspend fun signUp(@Body body: SignUpRequestDto): ApiResponse + suspend fun login(@Body body: LoginRequestDto): ApiResponse - @POST("user/verify") - suspend fun verify(@Body body: VerifyRequestDto): ApiResponse + @GET("user/profile") + suspend fun getProfile(): ApiResponse - @PATCH("user/update") - suspend fun update(@Body body: UpdateRequestDto): ApiResponse + @PATCH("user/profile") + suspend fun updateProfile(@Body body: UpdateProfileRequestDto): ApiResponse } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/GetProfileResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/GetProfileResponseDto.kt new file mode 100644 index 0000000..6f6e20f --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/GetProfileResponseDto.kt @@ -0,0 +1,9 @@ +package com.sampoom.android.feature.user.data.remote.dto + +data class GetProfileResponseDto( + val userId: Long, + val userName: String, + val workspace: String, + val branch: String, + val position: String +) diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateProfileRequestDto.kt similarity index 81% rename from app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateRequestDto.kt rename to app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateProfileRequestDto.kt index 24b7a03..b627e64 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateRequestDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateProfileRequestDto.kt @@ -1,6 +1,6 @@ package com.sampoom.android.feature.user.data.remote.dto -data class UpdateRequestDto( +data class UpdateProfileRequestDto( val userName: String, val position: String, val workspace: String, diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateProfileResponseDto.kt similarity index 77% rename from app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateResponseDto.kt rename to app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateProfileResponseDto.kt index b5b2cd5..e877859 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateResponseDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateProfileResponseDto.kt @@ -1,8 +1,7 @@ package com.sampoom.android.feature.user.data.remote.dto -data class UpdateResponseDto( +data class UpdateProfileResponseDto( val userId: Long, - val email: String, val userName: String, val position: String, val workspace: String, diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/VerifyRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/VerifyRequestDto.kt deleted file mode 100644 index 0ee23f1..0000000 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/VerifyRequestDto.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.sampoom.android.feature.user.data.remote.dto - -data class VerifyRequestDto( - val email: String, - val password: String -) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/VerifyResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/VerifyResponseDto.kt deleted file mode 100644 index 9d061f6..0000000 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/VerifyResponseDto.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.sampoom.android.feature.user.data.remote.dto - -data class VerifyResponseDto( - val userId: Long, - val email: String, - val userName: String, - val role: String -) diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt index 21d2a11..2bccb96 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt @@ -1,6 +1,8 @@ package com.sampoom.android.feature.user.data.repository +import android.R.attr.password import com.sampoom.android.core.datastore.AuthPreferences +import com.sampoom.android.feature.user.data.mapper.mergeWith import com.sampoom.android.feature.user.data.mapper.toModel import com.sampoom.android.feature.user.data.remote.api.AuthApi import com.sampoom.android.feature.user.data.remote.dto.LoginRequestDto @@ -10,6 +12,7 @@ import com.sampoom.android.feature.user.domain.model.User import com.sampoom.android.feature.user.domain.repository.AuthRepository import kotlinx.coroutines.CancellationException import javax.inject.Inject +import kotlin.math.log class AuthRepositoryImpl @Inject constructor( private val api: AuthApi, @@ -22,37 +25,44 @@ class AuthRepositoryImpl @Inject constructor( branch: String, userName: String, position: String - ): User { - api.signUp(SignUpRequestDto( - email = email, - password = password, - workspace = workspace, - branch = branch, - userName = userName, - position = position - )) - return signIn(email, password) + ): Result { + return runCatching { + api.signUp(SignUpRequestDto( + email = email, + password = password, + workspace = workspace, + branch = branch, + userName = userName, + position = position + )) + signIn(email, password).getOrThrow() + } } override suspend fun signIn( email: String, password: String - ): User { - val dto = api.login(LoginRequestDto(email, password)) - val user = dto.data.toModel() - preferences.saveUser(user) - return user + ): Result { + return runCatching { + val loginDto = api.login(LoginRequestDto(email, password)) + val loginUser = loginDto.data.toModel() + preferences.saveUser(loginUser) + + val profileDto = getProfile() + val profileUser = profileDto.getOrThrow() + + val user = loginUser.mergeWith(profileUser) + + preferences.saveUser(user) + user + } } override suspend fun signOut() : Result { - return try { + return runCatching { val dto = api.logout() if (!dto.success) throw Exception(dto.message) Result.success(Unit) - } catch (ce: CancellationException) { - throw ce - } catch (t: Throwable) { - Result.failure(t) } } @@ -73,15 +83,18 @@ class AuthRepositoryImpl @Inject constructor( } override suspend fun clearTokens(): Result { - return try { + return runCatching { preferences.clear() Result.success(Unit) - } catch (ce: CancellationException) { - throw ce - } catch (t: Throwable) { - Result.failure(t) } } override suspend fun isSignedIn(): Boolean = preferences.hasToken() + + override suspend fun getProfile(): Result { + return runCatching { + val dto = api.getProfile() + dto.data.toModel() + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/model/User.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/model/User.kt index 84be2f9..0baf0d1 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/model/User.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/model/User.kt @@ -6,5 +6,8 @@ data class User( val role: String, val accessToken: String, val refreshToken: String, - val expiresIn: Long + val expiresIn: Long, + val position: String, + val workspace: String, + val branch: String ) diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt index 8f4ec2f..6fb920b 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt @@ -10,11 +10,12 @@ interface AuthRepository { branch: String, userName: String, position: String - ): User + ): Result - suspend fun signIn(email: String, password: String): User + suspend fun signIn(email: String, password: String): Result suspend fun signOut(): Result suspend fun refreshToken(): Result suspend fun clearTokens(): Result suspend fun isSignedIn(): Boolean + suspend fun getProfile(): Result } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/ClearTokensUseCase.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/ClearTokensUseCase.kt index c46ace8..496279c 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/ClearTokensUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/ClearTokensUseCase.kt @@ -6,5 +6,5 @@ import javax.inject.Inject class ClearTokensUseCase @Inject constructor( private val repository: AuthRepository ) { - suspend operator fun invoke() = repository.clearTokens() + suspend operator fun invoke(): Result = repository.clearTokens() } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/LoginUseCase.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/LoginUseCase.kt index 1f01e3d..e8edc19 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/LoginUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/LoginUseCase.kt @@ -7,6 +7,5 @@ import javax.inject.Inject class LoginUseCase @Inject constructor( private val repository: AuthRepository ) { - suspend operator fun invoke(email: String, password: String): User = - repository.signIn(email, password) + suspend operator fun invoke(email: String, password: String): Result = repository.signIn(email, password) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignOutUseCase.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignOutUseCase.kt index fb896b4..7603a8b 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignOutUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignOutUseCase.kt @@ -6,5 +6,5 @@ import javax.inject.Inject class SignOutUseCase @Inject constructor( private val repository: AuthRepository ) { - suspend operator fun invoke() = repository.signOut() + suspend operator fun invoke(): Result = repository.signOut() } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignUpUseCase.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignUpUseCase.kt index f64e7f6..2e020ce 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignUpUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignUpUseCase.kt @@ -14,7 +14,7 @@ class SignUpUseCase @Inject constructor( branch: String, userName: String, position: String - ): User = repository.signUp( + ): Result = repository.signUp( email = email, password = password, workspace = workspace, diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/LoginViewModel.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/LoginViewModel.kt index 0c0f1a9..cf23ca4 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/LoginViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/LoginViewModel.kt @@ -43,10 +43,12 @@ class LoginViewModel @Inject constructor( _uiState.value = _uiState.value.copy(email = e.email) validateEmail() } + is LoginUiEvent.PasswordChanged -> { _uiState.value = _uiState.value.copy(password = e.password) validatePassword() } + LoginUiEvent.Submit -> submit() } @@ -81,11 +83,18 @@ class LoginViewModel @Inject constructor( val s = _uiState.value _uiState.update { it.copy(loading = true, error = null) } runCatching { singIn(s.email, s.password) } - .onSuccess { _uiState.update { it.copy(loading = false, success = true) } } + .onSuccess { + _uiState.update { + it.copy(loading = false, success = true) + } + } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() _uiState.update { - it.copy(loading = false, error = backendMessage ?: (throwable.message ?: errorLabel)) + it.copy( + loading = false, + error = backendMessage ?: (throwable.message ?: errorLabel) + ) } } Log.d(TAG, "submit: ${_uiState.value}") diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpViewModel.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpViewModel.kt index 15a5704..7757d6a 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpViewModel.kt @@ -145,7 +145,11 @@ class SignUpViewModel @Inject constructor( position = s.position ) } - .onSuccess { _state.update { it.copy(loading = false, success = true) } } + .onSuccess { + _state.update { + it.copy(loading = false, success = true) + } + } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() _state.update { From 6b5a7b4578c83f7f1f6658c04c7795a42954cbc7 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Wed, 29 Oct 2025 12:18:37 +0900 Subject: [PATCH 66/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 4 ++ .../java/com/sampoom/android/MainActivity.kt | 1 - .../android/app/navigation/AppNavHost.kt | 14 ++---- .../data/repository/CartRepositoryImpl.kt | 40 ++++++---------- .../feature/dashboard/ui/DashboardScreen.kt | 3 +- .../data/repository/OrderRepositoryImpl.kt | 24 +++++----- .../data/repository/OutboundRepositoryImpl.kt | 47 +++++++------------ .../data/repository/PartRepositoryImpl.kt | 7 +++ .../android/feature/part/ui/PartViewModel.kt | 1 + .../data/repository/AuthRepositoryImpl.kt | 17 +++++-- gradle/libs.versions.toml | 2 + 11 files changed, 77 insertions(+), 83 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 67ba62b..334c43d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -51,6 +51,7 @@ android { compileOptions { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 + isCoreLibraryDesugaringEnabled = true } buildFeatures { compose = true @@ -88,6 +89,9 @@ dependencies { // Paging implementation(libs.androidx.paging.runtime) implementation(libs.androidx.paging.compose) + + coreLibraryDesugaring(libs.desugar.jdk.libs) + implementation(libs.androidx.core.splashscreen) implementation(libs.androidx.material) implementation(libs.androidx.material.icons.core) diff --git a/app/src/main/java/com/sampoom/android/MainActivity.kt b/app/src/main/java/com/sampoom/android/MainActivity.kt index 593a197..fd06e83 100644 --- a/app/src/main/java/com/sampoom/android/MainActivity.kt +++ b/app/src/main/java/com/sampoom/android/MainActivity.kt @@ -15,7 +15,6 @@ class MainActivity : ComponentActivity() { @RequiresApi(Build.VERSION_CODES.O) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) -// enableEdgeToEdge() setContent { SampoomManagementTheme { AppNavHost() diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 86a49dc..2218895 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -1,15 +1,10 @@ package com.sampoom.android.app.navigation -import android.R.attr.order import android.annotation.SuppressLint import android.os.Build import androidx.activity.ComponentActivity import androidx.annotation.RequiresApi import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Button import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.NavigationBar @@ -39,7 +34,6 @@ import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import com.sampoom.android.R import com.sampoom.android.core.ui.theme.Main100 -import com.sampoom.android.core.ui.theme.Main300 import com.sampoom.android.core.ui.theme.Main500 import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.backgroundColor @@ -97,19 +91,18 @@ fun AppNavHost() { val navBackStackEntry by navController.currentBackStackEntryAsState() val currentRoute = navBackStackEntry?.destination?.route - val activity = LocalContext.current as ComponentActivity + val activity = LocalContext.current as? ComponentActivity val homeNavColor = backgroundCardColor() val elseNavColor = backgroundColor() val lightIcons = !isSystemInDarkTheme() LaunchedEffect(currentRoute, homeNavColor, lightIcons) { + val window = activity?.window ?: return@LaunchedEffect if (currentRoute == ROUTE_HOME) { - val window = activity.window window.navigationBarColor = homeNavColor.toArgb() WindowInsetsControllerCompat(window, window.decorView) .isAppearanceLightNavigationBars = lightIcons } else { - val window = activity.window window.navigationBarColor = elseNavColor.toArgb() WindowInsetsControllerCompat(window, window.decorView) .isAppearanceLightNavigationBars = lightIcons @@ -223,7 +216,8 @@ fun MainScreen( onLogoutClick = { authViewModel.signOut() parentNavController.navigate(ROUTE_LOGIN) { - popUpTo(0) { inclusive = true } + popUpTo(parentNavController.graph.startDestinationId) { inclusive = true } + launchSingleTop = true } } ) diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt index 978b4a9..53fe3a0 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt @@ -6,9 +6,9 @@ import com.sampoom.android.feature.cart.data.remote.dto.AddCartRequestDto import com.sampoom.android.feature.cart.data.remote.dto.UpdateCartRequestDto import com.sampoom.android.feature.cart.domain.model.CartList import com.sampoom.android.feature.cart.domain.repository.CartRepository -import kotlinx.coroutines.CancellationException import javax.inject.Inject import kotlin.Result +import kotlin.coroutines.cancellation.CancellationException class CartRepositoryImpl @Inject constructor( private val api: CartApi @@ -18,6 +18,8 @@ class CartRepositoryImpl @Inject constructor( val dto = api.getCartList() val cartItems = dto.data.map { it.toModel() } CartList(items = cartItems) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } @@ -25,38 +27,29 @@ class CartRepositoryImpl @Inject constructor( partId: Long, quantity: Long ): Result { - return try { + return runCatching { val dto = api.addCart(AddCartRequestDto(partId, quantity)) if (!dto.success) throw Exception(dto.message) - Result.success(Unit) - } catch (ce: CancellationException) { - throw ce - } catch (t: Throwable) { - Result.failure(t) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } override suspend fun deleteCart(cartItemId: Long): Result { - return try { + return runCatching { val dto = api.deleteCart(cartItemId) if (!dto.success) throw Exception(dto.message) - Result.success(Unit) - } catch (ce: CancellationException) { - throw ce - } catch (t: Throwable) { - Result.failure(t) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } override suspend fun deleteAllCart(): Result { - return try { + return runCatching { val dto = api.deleteAllCart() if (!dto.success) throw Exception(dto.message) - Result.success(Unit) - } catch (ce: CancellationException) { - throw ce - } catch (t: Throwable) { - Result.failure(t) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } @@ -64,14 +57,11 @@ class CartRepositoryImpl @Inject constructor( cartItemId: Long, quantity: Long ): Result { - return try { + return runCatching { val dto = api.updateCart(cartItemId, UpdateCartRequestDto(quantity)) if (!dto.success) throw Exception(dto.message) - Result.success(Unit) - } catch (ce: CancellationException) { - throw ce - } catch (t: Throwable) { - Result.failure(t) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt index d567e14..dcc94e9 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt @@ -38,7 +38,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.Painter -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.SpanStyle @@ -171,7 +170,7 @@ fun DashboardScreen( fun TitleSection() { Column( modifier = Modifier - .fillMaxSize() + .fillMaxWidth() .padding(vertical = 24.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt index 86b5da1..31b8cba 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt @@ -15,6 +15,8 @@ class OrderRepositoryImpl @Inject constructor( val dto = api.getOrderList() val orderItems = dto.data.map { it.toModel() } OrderList(items = orderItems) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } @@ -23,18 +25,17 @@ class OrderRepositoryImpl @Inject constructor( val dto = api.createOrder() val orderItems = dto.data.map { it.toModel() } OrderList(items = orderItems) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } override suspend fun receiveOrder(orderId: Long): Result { - return try { + return runCatching { val dto = api.receiveOrder(orderId) if (!dto.success) throw Exception(dto.message) - Result.success(Unit) - } catch (ce: CancellationException) { - throw ce - } catch (t: Throwable) { - Result.failure(t) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } @@ -43,18 +44,17 @@ class OrderRepositoryImpl @Inject constructor( val dto = api.getOrderDetail(orderId) val orderItems = dto.data.map { it.toModel() } OrderList(items = orderItems) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } override suspend fun cancelOrder(orderId: Long): Result { - return try { + return runCatching { val dto = api.cancelOrder(orderId) if (!dto.success) throw Exception(dto.message) - Result.success(Unit) - } catch (ce: CancellationException) { - throw ce - } catch (t: Throwable) { - Result.failure(t) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt index 353ec6d..2ca541c 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt @@ -17,18 +17,17 @@ class OutboundRepositoryImpl @Inject constructor( val dto = api.getOutboundList() val outboundItems = dto.data.map { it.toModel() } OutboundList(items = outboundItems) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } override suspend fun processOutbound(): Result { - return try { + return runCatching { val dto = api.processOutbound() if (!dto.success) throw Exception(dto.message) - Result.success(Unit) - } catch (ce: CancellationException) { - throw ce - } catch (t: Throwable) { - Result.failure(t) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } @@ -36,38 +35,29 @@ class OutboundRepositoryImpl @Inject constructor( partId: Long, quantity: Long ): Result { - return try { + return runCatching { val dto = api.addOutbound(AddOutboundRequestDto(partId, quantity)) if (!dto.success) throw Exception(dto.message) - Result.success(Unit) - } catch (ce: CancellationException) { - throw ce - } catch (t: Throwable) { - Result.failure(t) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } override suspend fun deleteOutbound(outboundId: Long): Result { - return try { + return runCatching { val dto = api.deleteOutbound(outboundId) if (!dto.success) throw Exception(dto.message) - Result.success(Unit) - } catch (ce: CancellationException) { - throw ce - } catch (t: Throwable) { - Result.failure(t) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } override suspend fun deleteAllOutbound(): Result { - return try { + return runCatching { val dto = api.deleteAllOutbound() if (!dto.success) throw Exception(dto.message) - Result.success(Unit) - } catch (ce: CancellationException) { - throw ce - } catch (t: Throwable) { - Result.failure(t) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } @@ -75,14 +65,11 @@ class OutboundRepositoryImpl @Inject constructor( outboundId: Long, quantity: Long ): Result { - return try { + return runCatching { val dto = api.updateOutbound(outboundId, UpdateOutboundRequestDto(quantity)) if (!dto.success) throw Exception(dto.message) - Result.success(Unit) - } catch (ce: CancellationException) { - throw ce - } catch (t: Throwable) { - Result.failure(t) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt index 51e0a18..254419e 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt @@ -13,6 +13,7 @@ import com.sampoom.android.feature.part.domain.model.SearchResult import com.sampoom.android.feature.part.domain.repository.PartRepository import kotlinx.coroutines.flow.Flow import javax.inject.Inject +import kotlin.coroutines.cancellation.CancellationException class PartRepositoryImpl @Inject constructor( private val api: PartApi, @@ -23,6 +24,8 @@ class PartRepositoryImpl @Inject constructor( val dto = api.getCategoryList() val categoryItems = dto.data.map { it.toModel() } CategoryList(items = categoryItems) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } @@ -31,6 +34,8 @@ class PartRepositoryImpl @Inject constructor( val response = api.getGroupList(categoryId) val groupItems = response.data.map { it.toModel() } GroupList(items = groupItems) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } @@ -39,6 +44,8 @@ class PartRepositoryImpl @Inject constructor( val response = api.getPartList(groupId) val partItems = response.data.map { it.toModel() } PartList(items = partItems) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt index 474a463..5ecfc99 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt @@ -125,6 +125,7 @@ class PartViewModel @Inject constructor( getGroupUseCase(categoryId) .onSuccess { groupList -> + if (_uiState.value.selectedCategory?.id != categoryId) return@launch _uiState.update { it.copy( groupList = groupList.items, diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt index 2bccb96..11b3993 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt @@ -27,7 +27,7 @@ class AuthRepositoryImpl @Inject constructor( position: String ): Result { return runCatching { - api.signUp(SignUpRequestDto( + val signUpRes = api.signUp(SignUpRequestDto( email = email, password = password, workspace = workspace, @@ -35,7 +35,10 @@ class AuthRepositoryImpl @Inject constructor( userName = userName, position = position )) + if (!signUpRes.success) throw Exception(signUpRes.message) signIn(email, password).getOrThrow() + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } @@ -55,6 +58,8 @@ class AuthRepositoryImpl @Inject constructor( preferences.saveUser(user) user + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } @@ -62,7 +67,8 @@ class AuthRepositoryImpl @Inject constructor( return runCatching { val dto = api.logout() if (!dto.success) throw Exception(dto.message) - Result.success(Unit) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } @@ -79,13 +85,16 @@ class AuthRepositoryImpl @Inject constructor( ) preferences.saveUser(updatedUser) updatedUser + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } override suspend fun clearTokens(): Result { return runCatching { preferences.clear() - Result.success(Unit) + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } @@ -95,6 +104,8 @@ class AuthRepositoryImpl @Inject constructor( return runCatching { val dto = api.getProfile() dto.data.toModel() + }.onFailure { exception -> + if (exception is CancellationException) throw exception } } } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 740e32f..a1a524e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,6 +2,7 @@ agp = "8.13.0" coreSplashscreen = "1.0.1" datastorePreferences = "1.1.7" +desugar_jdk_libs = "2.1.5" hiltAndroid = "2.57.2" hiltNavigationCompose = "1.3.0" kotlin = "2.2.20" @@ -30,6 +31,7 @@ androidx-material = { module = "androidx.compose.material:material", version.ref androidx-material-icons-core = { module = "androidx.compose.material:material-icons-core", version.ref = "materialIconsCore" } androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended" } converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofitVersion" } +desugar_jdk_libs = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugar_jdk_libs" } hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" } hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hiltAndroid" } junit = { group = "junit", name = "junit", version.ref = "junit" } From aaece3f80fca5b74e14d5cca5e8185b50774e92e Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Wed, 29 Oct 2025 15:33:07 +0900 Subject: [PATCH 67/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 2 +- .../main/java/com/sampoom/android/MainActivity.kt | 1 - .../sampoom/android/app/navigation/AppNavHost.kt | 14 +++++++++++++- .../feature/dashboard/ui/DashboardScreen.kt | 11 +++++++---- .../user/data/repository/AuthRepositoryImpl.kt | 1 - 5 files changed, 21 insertions(+), 8 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 334c43d..7d05d41 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -30,7 +30,7 @@ android { defaultConfig { applicationId = "com.sampoom.android" - minSdk = 24 + minSdk = 26 targetSdk = 36 versionCode = 2 versionName = "1.0.1" diff --git a/app/src/main/java/com/sampoom/android/MainActivity.kt b/app/src/main/java/com/sampoom/android/MainActivity.kt index fd06e83..f219d46 100644 --- a/app/src/main/java/com/sampoom/android/MainActivity.kt +++ b/app/src/main/java/com/sampoom/android/MainActivity.kt @@ -4,7 +4,6 @@ import android.os.Build import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge import androidx.annotation.RequiresApi import com.sampoom.android.app.navigation.AppNavHost import com.sampoom.android.core.ui.theme.SampoomManagementTheme diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 2218895..ec4ad45 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -24,6 +24,10 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.core.view.WindowInsetsControllerCompat import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.ui.Alignment import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.navigation.NavHostController import androidx.navigation.NavType @@ -109,7 +113,15 @@ fun AppNavHost() { } } - if (isLoading) { return } + if (isLoading) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + return + } NavHost( navController = navController, diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt index dcc94e9..cb32d7a 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt @@ -369,7 +369,8 @@ fun OrderListSection( uiState.dashboardLoading -> { Box( modifier = Modifier - .fillMaxSize(), + .fillMaxWidth() + .padding(vertical = 32.dp), contentAlignment = Alignment.Center ) { CircularProgressIndicator() @@ -379,7 +380,8 @@ fun OrderListSection( uiState.dashboardError != null -> { Box( modifier = Modifier - .fillMaxSize(), + .fillMaxWidth() + .padding(vertical = 32.dp), contentAlignment = Alignment.Center ) { ErrorContent( @@ -392,7 +394,8 @@ fun OrderListSection( uiState.orderList.isEmpty() -> { Box( modifier = Modifier - .fillMaxSize(), + .fillMaxWidth() + .padding(vertical = 32.dp), contentAlignment = Alignment.Center ) { EmptyContent( @@ -405,7 +408,7 @@ fun OrderListSection( else -> { LazyColumn( modifier = Modifier - .fillMaxSize() + .fillMaxWidth() .padding(horizontal = 16.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt index 11b3993..0f80c7f 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt @@ -49,7 +49,6 @@ class AuthRepositoryImpl @Inject constructor( return runCatching { val loginDto = api.login(LoginRequestDto(email, password)) val loginUser = loginDto.data.toModel() - preferences.saveUser(loginUser) val profileDto = getProfile() val profileUser = profileDto.getOrThrow() From a3a769e7c34e8c7a96c5d828d933f728917f7eee Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Wed, 29 Oct 2025 17:20:58 +0900 Subject: [PATCH 68/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sampoom/android/MainActivity.kt | 3 -- .../android/app/navigation/AppNavHost.kt | 1 - .../android/core/network/NetworkModule.kt | 12 +++---- .../android/core/ui/component/CommonButton.kt | 3 -- .../core/ui/component/CommonTextField.kt | 3 -- .../android/core/ui/component/ErrorContent.kt | 1 - .../android/core/ui/component/OrderItem.kt | 3 -- .../sampoom/android/core/util/FormatDate.kt | 3 -- .../android/feature/cart/ui/CartListScreen.kt | 1 - .../feature/dashboard/ui/DashboardScreen.kt | 1 - .../dashboard/ui/DashboardViewModel.kt | 3 -- .../feature/order/ui/OrderListScreen.kt | 10 ------ .../android/feature/part/ui/PartScreen.kt | 33 ++++++++++++++++--- .../data/repository/AuthRepositoryImpl.kt | 4 +++ .../android/feature/user/ui/LoginViewModel.kt | 2 +- .../android/feature/user/ui/SignUpScreen.kt | 4 --- .../feature/user/ui/SignUpViewModel.kt | 2 +- 17 files changed, 41 insertions(+), 48 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/MainActivity.kt b/app/src/main/java/com/sampoom/android/MainActivity.kt index f219d46..fd1d58f 100644 --- a/app/src/main/java/com/sampoom/android/MainActivity.kt +++ b/app/src/main/java/com/sampoom/android/MainActivity.kt @@ -1,17 +1,14 @@ package com.sampoom.android -import android.os.Build import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.annotation.RequiresApi import com.sampoom.android.app.navigation.AppNavHost import com.sampoom.android.core.ui.theme.SampoomManagementTheme import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint class MainActivity : ComponentActivity() { - @RequiresApi(Build.VERSION_CODES.O) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index ec4ad45..49b41ec 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -196,7 +196,6 @@ fun AppNavHost() { } } -@RequiresApi(Build.VERSION_CODES.O) @Composable fun MainScreen( parentNavController: NavHostController, diff --git a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt index cf79aeb..428827b 100644 --- a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt +++ b/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt @@ -1,19 +1,19 @@ package com.sampoom.android.core.network +import com.google.gson.FieldNamingPolicy +import com.google.gson.GsonBuilder +import com.sampoom.android.BuildConfig +import com.sampoom.android.core.datastore.AuthPreferences import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory -import javax.inject.Singleton -import com.google.gson.GsonBuilder -import com.google.gson.FieldNamingPolicy -import com.sampoom.android.BuildConfig -import com.sampoom.android.core.datastore.AuthPreferences -import okhttp3.logging.HttpLoggingInterceptor import java.util.concurrent.TimeUnit +import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt b/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt index 0765410..ce4ed82 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/CommonButton.kt @@ -1,6 +1,5 @@ package com.sampoom.android.core.ui.component -import android.R.attr.enabled import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.height @@ -13,9 +12,7 @@ import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Text import androidx.compose.material3.TextButton 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.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt b/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt index 9044fd7..0b4867c 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt @@ -1,14 +1,11 @@ package com.sampoom.android.core.ui.component -import android.R.attr.singleLine -import android.R.attr.text import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.foundation.text.input.InputTransformation.Companion.keyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Visibility import androidx.compose.material.icons.filled.VisibilityOff diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/ErrorContent.kt b/app/src/main/java/com/sampoom/android/core/ui/component/ErrorContent.kt index 6e102cb..201be9b 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/ErrorContent.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/ErrorContent.kt @@ -3,7 +3,6 @@ package com.sampoom.android.core.ui.component import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.material3.Button import androidx.compose.material3.Text diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/OrderItem.kt b/app/src/main/java/com/sampoom/android/core/ui/component/OrderItem.kt index ef8dec0..e971cc9 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/OrderItem.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/OrderItem.kt @@ -1,7 +1,5 @@ package com.sampoom.android.core.ui.component -import android.os.Build -import androidx.annotation.RequiresApi import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -25,7 +23,6 @@ import com.sampoom.android.core.util.buildOrderTitle import com.sampoom.android.core.util.formatDate import com.sampoom.android.feature.order.domain.model.Order -@RequiresApi(Build.VERSION_CODES.O) @Composable fun OrderItem( order: Order, diff --git a/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt b/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt index 7684ba3..b064f67 100644 --- a/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt +++ b/app/src/main/java/com/sampoom/android/core/util/FormatDate.kt @@ -1,10 +1,7 @@ package com.sampoom.android.core.util -import android.os.Build -import androidx.annotation.RequiresApi import java.time.format.DateTimeFormatter -@RequiresApi(Build.VERSION_CODES.O) fun formatDate(dateString: String): String { return runCatching { val out = DateTimeFormatter.ISO_LOCAL_DATE diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt index 96a3913..1c66a5b 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt @@ -48,7 +48,6 @@ import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.cart.domain.model.CartPart import com.sampoom.android.feature.order.ui.OrderResultBottomSheet -import kotlin.collections.forEach @Composable fun CartListScreen( diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt index cb32d7a..e976c7f 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt @@ -57,7 +57,6 @@ import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.order.domain.model.Order -@RequiresApi(Build.VERSION_CODES.O) @Composable fun DashboardScreen( paddingValues: PaddingValues, diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt index 1a7e717..676d6ec 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt @@ -6,14 +6,11 @@ import androidx.lifecycle.viewModelScope import com.sampoom.android.core.network.serverMessageOrNull import com.sampoom.android.feature.order.domain.usecase.GetOrderUseCase import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.CancellationException -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import javax.inject.Inject @HiltViewModel diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt index c925d13..dd5069b 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt @@ -1,7 +1,5 @@ package com.sampoom.android.feature.order.ui -import android.os.Build -import androidx.annotation.RequiresApi import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -12,13 +10,10 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.items import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -39,15 +34,10 @@ import com.sampoom.android.R import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent import com.sampoom.android.core.ui.component.OrderItem -import com.sampoom.android.core.ui.component.StatusChip -import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor -import com.sampoom.android.core.ui.theme.textSecondaryColor -import com.sampoom.android.core.util.buildOrderTitle import com.sampoom.android.core.util.formatDate import com.sampoom.android.feature.order.domain.model.Order -@RequiresApi(Build.VERSION_CODES.O) @OptIn(ExperimentalMaterialApi::class) @Composable fun OrderListScreen( diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index 94f9257..b1eb17b 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -1,15 +1,41 @@ package com.sampoom.android.feature.part.ui -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Clear -import androidx.compose.material3.* -import androidx.compose.runtime.* +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.OutlinedTextFieldDefaults +import androidx.compose.material3.SearchBar +import androidx.compose.material3.SearchBarDefaults +import androidx.compose.material3.Text +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment @@ -44,7 +70,6 @@ import com.sampoom.android.feature.part.domain.model.SearchResult import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import kotlin.collections.forEach @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt index 0f80c7f..0162745 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt @@ -48,8 +48,11 @@ class AuthRepositoryImpl @Inject constructor( ): Result { return runCatching { val loginDto = api.login(LoginRequestDto(email, password)) + if (!loginDto.success) throw Exception(loginDto.message) val loginUser = loginDto.data.toModel() + preferences.saveUser(loginUser) + val profileDto = getProfile() val profileUser = profileDto.getOrThrow() @@ -102,6 +105,7 @@ class AuthRepositoryImpl @Inject constructor( override suspend fun getProfile(): Result { return runCatching { val dto = api.getProfile() + if (!dto.success) throw Exception(dto.message) dto.data.toModel() }.onFailure { exception -> if (exception is CancellationException) throw exception diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/LoginViewModel.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/LoginViewModel.kt index cf23ca4..0b51d6c 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/LoginViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/LoginViewModel.kt @@ -4,10 +4,10 @@ import android.app.Application import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.sampoom.android.core.network.serverMessageOrNull import com.sampoom.android.feature.user.domain.AuthValidator import com.sampoom.android.feature.user.domain.ValidationResult import com.sampoom.android.feature.user.domain.usecase.LoginUseCase -import com.sampoom.android.core.network.serverMessageOrNull import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt index d655dca..5f80e76 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt @@ -7,15 +7,11 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.ime -import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.windowInsetsBottomHeight import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.verticalScroll diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpViewModel.kt b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpViewModel.kt index 7757d6a..21754e7 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpViewModel.kt @@ -4,10 +4,10 @@ import android.app.Application import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.sampoom.android.core.network.serverMessageOrNull import com.sampoom.android.feature.user.domain.AuthValidator import com.sampoom.android.feature.user.domain.ValidationResult import com.sampoom.android.feature.user.domain.usecase.SignUpUseCase -import com.sampoom.android.core.network.serverMessageOrNull import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow From 0d8e4243e9c5e678060735df390f19e1edfa7c5b Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Wed, 29 Oct 2025 17:50:14 +0900 Subject: [PATCH 69/88] =?UTF-8?q?[FIX]=20=EB=8C=80=EC=8B=9C=EB=B3=B4?= =?UTF-8?q?=EB=93=9C=20=ED=95=98=EB=93=9C=EC=BD=94=EB=94=A9=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/dashboard/ui/DashboardScreen.kt | 12 ++++++++---- .../feature/dashboard/ui/DashboardViewModel.kt | 11 ++++++++++- .../user/domain/usecase/GetStoredUserUseCase.kt | 13 +++++++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/feature/user/domain/usecase/GetStoredUserUseCase.kt diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt index e976c7f..fc7aea3 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt @@ -56,6 +56,7 @@ import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.order.domain.model.Order +import com.sampoom.android.feature.user.domain.model.User @Composable fun DashboardScreen( @@ -69,6 +70,7 @@ fun DashboardScreen( val uiState by viewModel.uiState.collectAsStateWithLifecycle() val pullRefreshState = rememberPullToRefreshState() val isManager = true // TODO: Role 검증 + val user by viewModel.user.collectAsStateWithLifecycle() LaunchedEffect(errorLabel) { viewModel.bindLabel(errorLabel) @@ -144,7 +146,7 @@ fun DashboardScreen( } } - item { TitleSection() } + item { TitleSection(user) } item { ButtonSection(isManager) } @@ -166,7 +168,9 @@ fun DashboardScreen( } @Composable -fun TitleSection() { +fun TitleSection( + user: User? +) { Column( modifier = Modifier .fillMaxWidth() @@ -174,7 +178,7 @@ fun TitleSection() { verticalArrangement = Arrangement.spacedBy(16.dp) ) { Text( - text = "가산디지털단지점", // TODO: Agency Id 받아오기 + text = user?.branch ?: "", // TODO: Agency Id 받아오기 style = MaterialTheme.typography.headlineMedium, fontWeight = FontWeight.Bold, color = textColor() @@ -185,7 +189,7 @@ fun TitleSection() { pushStringAnnotation(tag = "NAME", annotation = "name") withStyle(style = SpanStyle(color = Main500)) { - append("홍길동") // TODO : 이름 받아오기 + append(user?.userName ?: "") // TODO : 이름 받아오기 } append(stringResource(R.string.dashboard_title_hello_sir)) pop() diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt index 676d6ec..078baf5 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt @@ -5,6 +5,8 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sampoom.android.core.network.serverMessageOrNull import com.sampoom.android.feature.order.domain.usecase.GetOrderUseCase +import com.sampoom.android.feature.user.domain.model.User +import com.sampoom.android.feature.user.domain.usecase.GetStoredUserUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow @@ -15,7 +17,8 @@ import javax.inject.Inject @HiltViewModel class DashboardViewModel @Inject constructor( - private val getOrderListUseCase: GetOrderUseCase + private val getOrderListUseCase: GetOrderUseCase, + private val getStoredUserUseCase: GetStoredUserUseCase ): ViewModel() { private companion object { @@ -25,6 +28,9 @@ class DashboardViewModel @Inject constructor( private val _uiState = MutableStateFlow(DashboardUiState()) val uiState : StateFlow = _uiState + private val _user = MutableStateFlow(null) + val user: StateFlow = _user + private var errorLabel: String = "" private var loadJob: Job? = null @@ -33,6 +39,9 @@ class DashboardViewModel @Inject constructor( } init { + viewModelScope.launch { + _user.value = getStoredUserUseCase() + } loadOrderList() } diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/GetStoredUserUseCase.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/GetStoredUserUseCase.kt new file mode 100644 index 0000000..dcb9a0e --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/GetStoredUserUseCase.kt @@ -0,0 +1,13 @@ +package com.sampoom.android.feature.user.domain.usecase + +import com.sampoom.android.core.datastore.AuthPreferences +import com.sampoom.android.feature.user.domain.model.User +import javax.inject.Inject + +class GetStoredUserUseCase @Inject constructor( + private val preferences: AuthPreferences +) { + suspend operator fun invoke(): User? = preferences.getStoredUser() +} + + From 9ac62e57642691af24f940758dee4caa99aebcae Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Fri, 31 Oct 2025 17:58:30 +0900 Subject: [PATCH 70/88] =?UTF-8?q?[REFAC]=20=EC=A3=BC=EB=AC=B8=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20API=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/cart/ui/CartListViewModel.kt | 5 +++-- .../feature/order/data/remote/api/OrderApi.kt | 8 ++++++- .../order/data/remote/dto/OrderRequestDto.kt | 12 +++++++++++ .../data/repository/OrderRepositoryImpl.kt | 21 ++++++++++++++++--- .../domain/repository/OrderRepository.kt | 3 ++- .../domain/usecase/CreateOrderUseCase.kt | 3 ++- .../domain/usecase/GetStoredUserUseCase.kt | 1 + 7 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderRequestDto.kt diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt index 0d424c2..6972a1a 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt @@ -4,13 +4,13 @@ import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.feature.cart.domain.model.CartList import com.sampoom.android.feature.cart.domain.usecase.DeleteAllCartUseCase import com.sampoom.android.feature.cart.domain.usecase.DeleteCartUseCase import com.sampoom.android.feature.cart.domain.usecase.GetCartUseCase import com.sampoom.android.feature.cart.domain.usecase.UpdateCartQuantityUseCase import com.sampoom.android.feature.order.domain.usecase.CreateOrderUseCase import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.CancellationException import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update @@ -88,7 +88,8 @@ class CartListViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(isProcessing = true, processError = null) } - createOrderUseCase() + val cartList = CartList(items = _uiState.value.cartList) + createOrderUseCase(cartList) .onSuccess { orderList -> _uiState.update { it.copy(isProcessing = false, processedOrder = orderList.items) } loadCartList() diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt b/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt index 6785d0c..769155a 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt @@ -3,6 +3,8 @@ package com.sampoom.android.feature.order.data.remote.api import com.sampoom.android.core.network.ApiResponse import com.sampoom.android.core.network.ApiSuccessResponse import com.sampoom.android.feature.order.data.remote.dto.OrderDto +import com.sampoom.android.feature.order.data.remote.dto.OrderRequestDto +import retrofit2.http.Body import retrofit2.http.DELETE import retrofit2.http.GET import retrofit2.http.PATCH @@ -15,10 +17,14 @@ interface OrderApi { @GET("agency/1/orders") suspend fun getOrderList(): ApiResponse> - // 주문 생성 + // 주문 생성 TODO: Deprecated API @POST("agency/1/orders") suspend fun createOrder(): ApiResponse> + // 주문 생성 + @POST("order/") + suspend fun createOrder(@Body orderRequestDto: OrderRequestDto): ApiResponse> + // 주문 입고 처리 @PATCH("agency/1/orders/{orderId}/receive") suspend fun receiveOrder(@Path("orderId") orderId: Long): ApiSuccessResponse diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderRequestDto.kt new file mode 100644 index 0000000..2d57960 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderRequestDto.kt @@ -0,0 +1,12 @@ +package com.sampoom.android.feature.order.data.remote.dto + +data class OrderRequestDto( + val requester: String, + val branch: String, + val items: List +) + +data class OrderItems( + val code: String, + val quantity: Long +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt index 31b8cba..abd3d33 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt @@ -1,14 +1,19 @@ package com.sampoom.android.feature.order.data.repository +import com.sampoom.android.core.datastore.AuthPreferences +import com.sampoom.android.feature.cart.domain.model.CartList import com.sampoom.android.feature.order.data.mapper.toModel import com.sampoom.android.feature.order.data.remote.api.OrderApi +import com.sampoom.android.feature.order.data.remote.dto.OrderItems +import com.sampoom.android.feature.order.data.remote.dto.OrderRequestDto import com.sampoom.android.feature.order.domain.model.OrderList import com.sampoom.android.feature.order.domain.repository.OrderRepository import javax.inject.Inject import kotlin.coroutines.cancellation.CancellationException class OrderRepositoryImpl @Inject constructor( - private val api: OrderApi + private val api: OrderApi, + private val preferences: AuthPreferences ) : OrderRepository { override suspend fun getOrderList(): Result { return runCatching { @@ -20,9 +25,19 @@ class OrderRepositoryImpl @Inject constructor( } } - override suspend fun createOrder(): Result { + override suspend fun createOrder(cartList: CartList): Result { return runCatching { - val dto = api.createOrder() + val user = preferences.getStoredUser() ?: throw Exception("No user information available") + val items = cartList.items + .flatMap { it.groups } + .flatMap { it.parts } + .map { part -> OrderItems(code = part.code, quantity = part.quantity) } + val request = OrderRequestDto( + requester = "대리점", + branch = user.branch, + items = items + ) + val dto = api.createOrder(request) val orderItems = dto.data.map { it.toModel() } OrderList(items = orderItems) }.onFailure { exception -> diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt index 3d3d000..80cd1d2 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt @@ -1,10 +1,11 @@ package com.sampoom.android.feature.order.domain.repository +import com.sampoom.android.feature.cart.domain.model.CartList import com.sampoom.android.feature.order.domain.model.OrderList interface OrderRepository { suspend fun getOrderList(): Result - suspend fun createOrder(): Result + suspend fun createOrder(cartList: CartList): Result suspend fun receiveOrder(orderId: Long): Result suspend fun getOrderDetail(orderId: Long): Result suspend fun cancelOrder(orderId: Long): Result diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CreateOrderUseCase.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CreateOrderUseCase.kt index b74db85..f94d1c4 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CreateOrderUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CreateOrderUseCase.kt @@ -1,5 +1,6 @@ package com.sampoom.android.feature.order.domain.usecase +import com.sampoom.android.feature.cart.domain.model.CartList import com.sampoom.android.feature.order.domain.model.OrderList import com.sampoom.android.feature.order.domain.repository.OrderRepository import javax.inject.Inject @@ -7,5 +8,5 @@ import javax.inject.Inject class CreateOrderUseCase @Inject constructor( private val repository: OrderRepository ){ - suspend operator fun invoke(): Result = repository.createOrder() + suspend operator fun invoke(cartList: CartList): Result = repository.createOrder(cartList) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/GetStoredUserUseCase.kt b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/GetStoredUserUseCase.kt index dcb9a0e..5e74eaa 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/GetStoredUserUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/GetStoredUserUseCase.kt @@ -11,3 +11,4 @@ class GetStoredUserUseCase @Inject constructor( } + From c2424a14af53d5d8ed7e180aa3e0e55c88676757 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Fri, 31 Oct 2025 18:20:56 +0900 Subject: [PATCH 71/88] =?UTF-8?q?[REFAC]=20=EC=A3=BC=EB=AC=B8=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20API=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sampoom/android/feature/order/data/remote/api/OrderApi.kt | 4 ---- .../android/feature/order/data/remote/dto/OrderRequestDto.kt | 1 - .../feature/order/data/repository/OrderRepositoryImpl.kt | 1 - 3 files changed, 6 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt b/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt index 769155a..c0dedb5 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt @@ -17,10 +17,6 @@ interface OrderApi { @GET("agency/1/orders") suspend fun getOrderList(): ApiResponse> - // 주문 생성 TODO: Deprecated API - @POST("agency/1/orders") - suspend fun createOrder(): ApiResponse> - // 주문 생성 @POST("order/") suspend fun createOrder(@Body orderRequestDto: OrderRequestDto): ApiResponse> diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderRequestDto.kt index 2d57960..62ec9a3 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderRequestDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderRequestDto.kt @@ -1,7 +1,6 @@ package com.sampoom.android.feature.order.data.remote.dto data class OrderRequestDto( - val requester: String, val branch: String, val items: List ) diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt index abd3d33..cf0c399 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt @@ -33,7 +33,6 @@ class OrderRepositoryImpl @Inject constructor( .flatMap { it.parts } .map { part -> OrderItems(code = part.code, quantity = part.quantity) } val request = OrderRequestDto( - requester = "대리점", branch = user.branch, items = items ) From fdf67c8b9ac79120aa4c19baf0b6fa83888685d1 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Sun, 2 Nov 2025 12:51:31 +0900 Subject: [PATCH 72/88] =?UTF-8?q?[REFAC]=20=EC=A3=BC=EB=AC=B8=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95,=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=A0=84=EC=97=AD=20=EC=8A=A4=EB=82=B5?= =?UTF-8?q?=EB=B0=94=20=EC=A0=81=EC=9A=A9,=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=20=EA=B5=AC=EC=A1=B0=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sampoom/android/MainActivity.kt | 1 + .../sampoom/android/MainActivityViewModel.kt | 11 +++ .../android/app/navigation/AppNavHost.kt | 53 ++++++++--- .../core/{network => di}/NetworkModule.kt | 7 +- .../com/sampoom/android/core/di/UiModule.kt | 16 ++++ .../core/{network => model}/ApiResponse.kt | 7 +- .../android/core/model/SnackBarMessage.kt | 6 ++ .../android/core/network/ErrorHandling.kt | 7 +- .../core/network/TokenAuthenticator.kt | 2 +- .../android/core/network/TokenInterceptor.kt | 2 +- .../core/network/TokenRefreshService.kt | 8 +- .../AuthPreferences.kt | 4 +- .../CryptoManager.kt | 2 +- .../core/ui/component/CommonSnackBar.kt | 81 ++++++---------- .../android/core/util/GlobalMessageHandler.kt | 21 +++++ .../{user => auth}/data/mapper/AuthMappers.kt | 8 +- .../{user => auth}/data/remote/api/AuthApi.kt | 24 ++--- .../data/remote/dto/GetProfileResponseDto.kt | 2 +- .../data/remote/dto/LoginRequestDto.kt | 2 +- .../data/remote/dto/LoginResponseDto.kt | 2 +- .../data/remote/dto/RefreshRequestDto.kt | 2 +- .../data/remote/dto/RefreshResponseDto.kt | 2 +- .../data/remote/dto/SignUpRequestDto.kt | 2 +- .../data/remote/dto/SignUpResponseDto.kt | 2 +- .../remote/dto/UpdateProfileRequestDto.kt | 2 +- .../remote/dto/UpdateProfileResponseDto.kt | 2 +- .../data/repository/AuthRepositoryImpl.kt | 35 ++----- .../feature/{user => auth}/di/AuthModules.kt | 8 +- .../{user => auth}/domain/AuthValidator.kt | 2 +- .../{user => auth}/domain/model/User.kt | 2 +- .../domain/repository/AuthRepository.kt | 4 +- .../domain/usecase/CheckLoginStateUseCase.kt | 4 +- .../domain/usecase/ClearTokensUseCase.kt | 4 +- .../domain/usecase/GetStoredUserUseCase.kt | 6 +- .../domain/usecase/LoginUseCase.kt | 6 +- .../domain/usecase/SignOutUseCase.kt | 4 +- .../domain/usecase/SignUpUseCase.kt | 6 +- .../{user => auth}/ui/AuthViewModel.kt | 8 +- .../feature/{user => auth}/ui/LoginScreen.kt | 17 +--- .../feature/{user => auth}/ui/LoginUiEvent.kt | 2 +- .../feature/{user => auth}/ui/LoginUiState.kt | 3 +- .../{user => auth}/ui/LoginViewModel.kt | 26 +++-- .../feature/{user => auth}/ui/SignUpScreen.kt | 13 +-- .../{user => auth}/ui/SignUpUiEvent.kt | 2 +- .../{user => auth}/ui/SignUpUiState.kt | 5 +- .../{user => auth}/ui/SignUpViewModel.kt | 39 ++++---- .../feature/cart/data/remote/api/CartApi.kt | 4 +- .../data/repository/CartRepositoryImpl.kt | 12 --- .../android/feature/cart/ui/CartListScreen.kt | 5 +- .../feature/cart/ui/CartListUiEvent.kt | 2 - .../feature/cart/ui/CartListUiState.kt | 2 +- .../feature/cart/ui/CartListViewModel.kt | 33 +++++-- .../feature/dashboard/ui/DashboardScreen.kt | 74 ++++++++------- .../dashboard/ui/DashboardViewModel.kt | 75 ++++++++------- .../order/data/paging/OrderPagingSource.kt | 47 ++++++++++ .../feature/order/data/remote/api/OrderApi.kt | 23 +++-- .../order/data/remote/dto/OrderListDto.kt | 8 ++ .../order/data/remote/dto/OrderRequestDto.kt | 9 +- .../data/repository/OrderRepositoryImpl.kt | 80 +++++++++------- .../domain/repository/OrderRepository.kt | 10 +- .../domain/usecase/CreateOrderUseCase.kt | 4 +- .../domain/usecase/GetOrderDetailUseCase.kt | 4 +- .../order/domain/usecase/GetOrderUseCase.kt | 5 +- .../feature/order/ui/OrderDetailContent.kt | 42 ++++----- .../feature/order/ui/OrderDetailScreen.kt | 51 +++++----- .../feature/order/ui/OrderDetailUiEvent.kt | 1 - .../feature/order/ui/OrderDetailUiState.kt | 3 +- .../feature/order/ui/OrderDetailViewModel.kt | 47 ++++++---- .../feature/order/ui/OrderListScreen.kt | 94 ++++++++++++++----- .../feature/order/ui/OrderListViewModel.kt | 52 ++-------- .../order/ui/OrderResultBottomSheet.kt | 19 +--- .../outbound/data/remote/api/OutboundApi.kt | 4 +- .../data/repository/OutboundRepositoryImpl.kt | 13 --- .../feature/outbound/ui/OutboundListScreen.kt | 5 +- .../outbound/ui/OutboundListUiEvent.kt | 2 - .../outbound/ui/OutboundListUiState.kt | 2 - .../outbound/ui/OutboundListViewModel.kt | 55 ++++++----- .../feature/part/data/remote/api/PartApi.kt | 2 +- .../data/repository/PartRepositoryImpl.kt | 7 -- .../feature/part/ui/PartDetailBottomSheet.kt | 26 +++-- .../feature/part/ui/PartDetailUiEvent.kt | 1 - .../feature/part/ui/PartDetailViewModel.kt | 35 ++++--- .../android/feature/part/ui/PartListScreen.kt | 31 ++++-- .../feature/part/ui/PartListViewModel.kt | 7 +- .../android/feature/part/ui/PartScreen.kt | 28 ++++-- .../android/feature/part/ui/PartViewModel.kt | 12 ++- app/src/main/res/values/strings.xml | 4 +- 87 files changed, 775 insertions(+), 639 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/MainActivityViewModel.kt rename app/src/main/java/com/sampoom/android/core/{network => di}/NetworkModule.kt (89%) create mode 100644 app/src/main/java/com/sampoom/android/core/di/UiModule.kt rename app/src/main/java/com/sampoom/android/core/{network => model}/ApiResponse.kt (63%) create mode 100644 app/src/main/java/com/sampoom/android/core/model/SnackBarMessage.kt rename app/src/main/java/com/sampoom/android/core/{datastore => preferences}/AuthPreferences.kt (98%) rename app/src/main/java/com/sampoom/android/core/{datastore => preferences}/CryptoManager.kt (98%) create mode 100644 app/src/main/java/com/sampoom/android/core/util/GlobalMessageHandler.kt rename app/src/main/java/com/sampoom/android/feature/{user => auth}/data/mapper/AuthMappers.kt (74%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/data/remote/api/AuthApi.kt (56%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/data/remote/dto/GetProfileResponseDto.kt (73%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/data/remote/dto/LoginRequestDto.kt (57%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/data/remote/dto/LoginResponseDto.kt (76%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/data/remote/dto/RefreshRequestDto.kt (52%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/data/remote/dto/RefreshResponseDto.kt (67%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/data/remote/dto/SignUpRequestDto.kt (76%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/data/remote/dto/SignUpResponseDto.kt (64%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/data/remote/dto/UpdateProfileRequestDto.kt (71%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/data/remote/dto/UpdateProfileResponseDto.kt (74%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/data/repository/AuthRepositoryImpl.kt (67%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/di/AuthModules.kt (71%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/domain/AuthValidator.kt (98%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/domain/model/User.kt (82%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/domain/repository/AuthRepository.kt (81%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/domain/usecase/CheckLoginStateUseCase.kt (63%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/domain/usecase/ClearTokensUseCase.kt (63%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/domain/usecase/GetStoredUserUseCase.kt (53%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/domain/usecase/LoginUseCase.kt (57%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/domain/usecase/SignOutUseCase.kt (62%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/domain/usecase/SignUpUseCase.kt (74%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/ui/AuthViewModel.kt (87%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/ui/LoginScreen.kt (90%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/ui/LoginUiEvent.kt (82%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/ui/LoginUiState.kt (85%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/ui/LoginViewModel.kt (81%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/ui/SignUpScreen.kt (94%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/ui/SignUpUiEvent.kt (91%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/ui/SignUpUiState.kt (89%) rename app/src/main/java/com/sampoom/android/feature/{user => auth}/ui/SignUpViewModel.kt (85%) create mode 100644 app/src/main/java/com/sampoom/android/feature/order/data/paging/OrderPagingSource.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderListDto.kt diff --git a/app/src/main/java/com/sampoom/android/MainActivity.kt b/app/src/main/java/com/sampoom/android/MainActivity.kt index fd1d58f..8350fe5 100644 --- a/app/src/main/java/com/sampoom/android/MainActivity.kt +++ b/app/src/main/java/com/sampoom/android/MainActivity.kt @@ -3,6 +3,7 @@ package com.sampoom.android import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.lifecycle.viewmodel.compose.viewModel import com.sampoom.android.app.navigation.AppNavHost import com.sampoom.android.core.ui.theme.SampoomManagementTheme import dagger.hilt.android.AndroidEntryPoint diff --git a/app/src/main/java/com/sampoom/android/MainActivityViewModel.kt b/app/src/main/java/com/sampoom/android/MainActivityViewModel.kt new file mode 100644 index 0000000..e32eb23 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/MainActivityViewModel.kt @@ -0,0 +1,11 @@ +package com.sampoom.android + +import androidx.lifecycle.ViewModel +import com.sampoom.android.core.util.GlobalMessageHandler +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class MainActivityViewModel @Inject constructor( + val messageHandler: GlobalMessageHandler +) : ViewModel() \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 49b41ec..344559c 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -1,21 +1,28 @@ package com.sampoom.android.app.navigation import android.annotation.SuppressLint -import android.os.Build import androidx.activity.ComponentActivity -import androidx.annotation.RequiresApi import androidx.compose.foundation.background +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.NavigationBarItemDefaults import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarDuration import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb @@ -23,11 +30,6 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.core.view.WindowInsetsControllerCompat -import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.ui.Alignment import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.navigation.NavHostController import androidx.navigation.NavType @@ -36,15 +38,19 @@ import androidx.navigation.compose.composable import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument +import com.sampoom.android.MainActivityViewModel import com.sampoom.android.R +import com.sampoom.android.core.model.SnackBarMessage +import com.sampoom.android.core.ui.component.TopSnackBarHost +import com.sampoom.android.core.ui.component.rememberCommonSnackBarHostState import com.sampoom.android.core.ui.theme.Main100 import com.sampoom.android.core.ui.theme.Main500 import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.backgroundColor import com.sampoom.android.core.ui.theme.textColor -import com.sampoom.android.feature.user.ui.AuthViewModel -import com.sampoom.android.feature.user.ui.LoginScreen -import com.sampoom.android.feature.user.ui.SignUpScreen +import com.sampoom.android.feature.auth.ui.AuthViewModel +import com.sampoom.android.feature.auth.ui.LoginScreen +import com.sampoom.android.feature.auth.ui.SignUpScreen import com.sampoom.android.feature.cart.ui.CartListScreen import com.sampoom.android.feature.dashboard.ui.DashboardScreen import com.sampoom.android.feature.order.ui.OrderDetailScreen @@ -52,7 +58,9 @@ import com.sampoom.android.feature.order.ui.OrderListScreen import com.sampoom.android.feature.outbound.ui.OutboundListScreen import com.sampoom.android.feature.part.ui.PartListScreen import com.sampoom.android.feature.part.ui.PartScreen +import kotlinx.coroutines.flow.filterNotNull +// Auth Screen const val ROUTE_LOGIN = "login" const val ROUTE_SIGNUP = "signup" const val ROUTE_HOME = "home" @@ -69,7 +77,6 @@ const val ROUTE_PART_LIST = "parts/{agencyId}/group/{groupId}" fun routePartList(agencyId: Long, groupId: Long): String = "parts/$agencyId/group/$groupId" const val ROUTE_ORDER_DETAIL = "orders/{agencyId}/orders/{orderId}" fun routeOrderDetail(agencyId: Long, orderId: Long): String = "orders/$agencyId/orders/$orderId" -const val ROUTE_SEARCH = "search" const val ROUTE_EMPLOYEE = "employee" const val ROUTE_SETTINGS = "settings" @@ -85,9 +92,10 @@ sealed class BottomNavItem( } @SuppressLint("ContextCastToActivity") -@RequiresApi(Build.VERSION_CODES.O) @Composable -fun AppNavHost() { +fun AppNavHost( + viewModel: MainActivityViewModel = hiltViewModel() +) { val navController = rememberNavController() val authViewModel: AuthViewModel = hiltViewModel() val isLoggedIn by authViewModel.isLoggedIn.collectAsState() @@ -100,6 +108,22 @@ fun AppNavHost() { val elseNavColor = backgroundColor() val lightIcons = !isSystemInDarkTheme() + val snackBarHostState = rememberCommonSnackBarHostState() + var currentMessage by remember { mutableStateOf(null) } + + // 전역 에러 수집 + LaunchedEffect(viewModel.messageHandler) { + viewModel.messageHandler.message + .filterNotNull() + .collect { message -> + currentMessage = message + snackBarHostState.showSnackbar( + message = message.message, + duration = SnackbarDuration.Short + ) + } + } + LaunchedEffect(currentRoute, homeNavColor, lightIcons) { val window = activity?.window ?: return@LaunchedEffect if (currentRoute == ROUTE_HOME) { @@ -125,7 +149,7 @@ fun AppNavHost() { NavHost( navController = navController, -// startDestination = ROUTE_HOME, +// startDestination = ROUTE_HOME, startDestination = if (isLoggedIn) ROUTE_HOME else ROUTE_LOGIN, modifier = Modifier.background(backgroundColor()) ) { @@ -194,6 +218,7 @@ fun AppNavHost() { ) } } + TopSnackBarHost(hostState = snackBarHostState, isError = currentMessage?.isError ?: false) } @Composable diff --git a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt b/app/src/main/java/com/sampoom/android/core/di/NetworkModule.kt similarity index 89% rename from app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt rename to app/src/main/java/com/sampoom/android/core/di/NetworkModule.kt index 428827b..31dff36 100644 --- a/app/src/main/java/com/sampoom/android/core/network/NetworkModule.kt +++ b/app/src/main/java/com/sampoom/android/core/di/NetworkModule.kt @@ -1,9 +1,12 @@ -package com.sampoom.android.core.network +package com.sampoom.android.core.di import com.google.gson.FieldNamingPolicy import com.google.gson.GsonBuilder import com.sampoom.android.BuildConfig -import com.sampoom.android.core.datastore.AuthPreferences +import com.sampoom.android.core.preferences.AuthPreferences +import com.sampoom.android.core.network.TokenAuthenticator +import com.sampoom.android.core.network.TokenInterceptor +import com.sampoom.android.core.network.TokenRefreshService import dagger.Module import dagger.Provides import dagger.hilt.InstallIn diff --git a/app/src/main/java/com/sampoom/android/core/di/UiModule.kt b/app/src/main/java/com/sampoom/android/core/di/UiModule.kt new file mode 100644 index 0000000..696142c --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/di/UiModule.kt @@ -0,0 +1,16 @@ +package com.sampoom.android.core.di + +import com.sampoom.android.core.util.GlobalMessageHandler +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +object UiModule { + @Provides + @Singleton + fun provideGlobalErrorHandler(): GlobalMessageHandler = GlobalMessageHandler() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/network/ApiResponse.kt b/app/src/main/java/com/sampoom/android/core/model/ApiResponse.kt similarity index 63% rename from app/src/main/java/com/sampoom/android/core/network/ApiResponse.kt rename to app/src/main/java/com/sampoom/android/core/model/ApiResponse.kt index a0b1c1a..2d5959e 100644 --- a/app/src/main/java/com/sampoom/android/core/network/ApiResponse.kt +++ b/app/src/main/java/com/sampoom/android/core/model/ApiResponse.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.core.network +package com.sampoom.android.core.model data class ApiResponse( val status: Int, @@ -11,4 +11,9 @@ data class ApiSuccessResponse( val status: Int, val success: Boolean, val message: String +) + +data class ApiErrorResponse( + val code: Int? = null, + val message: String? = null ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/model/SnackBarMessage.kt b/app/src/main/java/com/sampoom/android/core/model/SnackBarMessage.kt new file mode 100644 index 0000000..d27c21e --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/model/SnackBarMessage.kt @@ -0,0 +1,6 @@ +package com.sampoom.android.core.model + +data class SnackBarMessage( + val message: String, + val isError: Boolean = false +) diff --git a/app/src/main/java/com/sampoom/android/core/network/ErrorHandling.kt b/app/src/main/java/com/sampoom/android/core/network/ErrorHandling.kt index e0a43ca..2dd7892 100644 --- a/app/src/main/java/com/sampoom/android/core/network/ErrorHandling.kt +++ b/app/src/main/java/com/sampoom/android/core/network/ErrorHandling.kt @@ -3,12 +3,9 @@ package com.sampoom.android.core.network import android.util.Log import com.google.gson.Gson import com.google.gson.JsonSyntaxException +import com.sampoom.android.core.model.ApiErrorResponse import retrofit2.HttpException - -data class ApiErrorResponse( - val code: Int? = null, - val message: String? = null -) +import kotlin.jvm.java fun Throwable.serverMessageOrNull(): String? { if (this is HttpException) { diff --git a/app/src/main/java/com/sampoom/android/core/network/TokenAuthenticator.kt b/app/src/main/java/com/sampoom/android/core/network/TokenAuthenticator.kt index ea4d018..731fe0a 100644 --- a/app/src/main/java/com/sampoom/android/core/network/TokenAuthenticator.kt +++ b/app/src/main/java/com/sampoom/android/core/network/TokenAuthenticator.kt @@ -1,6 +1,6 @@ package com.sampoom.android.core.network -import com.sampoom.android.core.datastore.AuthPreferences +import com.sampoom.android.core.preferences.AuthPreferences import kotlinx.coroutines.runBlocking import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock diff --git a/app/src/main/java/com/sampoom/android/core/network/TokenInterceptor.kt b/app/src/main/java/com/sampoom/android/core/network/TokenInterceptor.kt index 7971e86..4e79a97 100644 --- a/app/src/main/java/com/sampoom/android/core/network/TokenInterceptor.kt +++ b/app/src/main/java/com/sampoom/android/core/network/TokenInterceptor.kt @@ -1,6 +1,6 @@ package com.sampoom.android.core.network -import com.sampoom.android.core.datastore.AuthPreferences +import com.sampoom.android.core.preferences.AuthPreferences import kotlinx.coroutines.runBlocking import okhttp3.Interceptor import okhttp3.Response diff --git a/app/src/main/java/com/sampoom/android/core/network/TokenRefreshService.kt b/app/src/main/java/com/sampoom/android/core/network/TokenRefreshService.kt index d95f9dc..d2db843 100644 --- a/app/src/main/java/com/sampoom/android/core/network/TokenRefreshService.kt +++ b/app/src/main/java/com/sampoom/android/core/network/TokenRefreshService.kt @@ -1,9 +1,9 @@ package com.sampoom.android.core.network -import com.sampoom.android.core.datastore.AuthPreferences -import com.sampoom.android.feature.user.data.remote.api.AuthApi -import com.sampoom.android.feature.user.data.remote.dto.RefreshRequestDto -import com.sampoom.android.feature.user.domain.model.User +import com.sampoom.android.core.preferences.AuthPreferences +import com.sampoom.android.feature.auth.data.remote.api.AuthApi +import com.sampoom.android.feature.auth.data.remote.dto.RefreshRequestDto +import com.sampoom.android.feature.auth.domain.model.User import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import javax.inject.Inject diff --git a/app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt b/app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt similarity index 98% rename from app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt rename to app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt index 3644489..8f7fb59 100644 --- a/app/src/main/java/com/sampoom/android/core/datastore/AuthPreferences.kt +++ b/app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.core.datastore +package com.sampoom.android.core.preferences import android.content.Context import androidx.datastore.preferences.core.Preferences @@ -6,7 +6,7 @@ import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.longPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore -import com.sampoom.android.feature.user.domain.model.User +import com.sampoom.android.feature.auth.domain.model.User import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton diff --git a/app/src/main/java/com/sampoom/android/core/datastore/CryptoManager.kt b/app/src/main/java/com/sampoom/android/core/preferences/CryptoManager.kt similarity index 98% rename from app/src/main/java/com/sampoom/android/core/datastore/CryptoManager.kt rename to app/src/main/java/com/sampoom/android/core/preferences/CryptoManager.kt index 36d0704..7d63e67 100644 --- a/app/src/main/java/com/sampoom/android/core/datastore/CryptoManager.kt +++ b/app/src/main/java/com/sampoom/android/core/preferences/CryptoManager.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.core.datastore +package com.sampoom.android.core.preferences import android.content.Context import android.security.keystore.KeyGenParameterSpec diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/CommonSnackBar.kt b/app/src/main/java/com/sampoom/android/core/ui/component/CommonSnackBar.kt index 34bfee0..8eadee9 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/CommonSnackBar.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/CommonSnackBar.kt @@ -1,70 +1,46 @@ package com.sampoom.android.core.ui.component -import androidx.compose.material3.SnackbarDuration -import androidx.compose.material3.SnackbarHost -import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.SnackbarResult -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.remember import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.Dp +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBars -import com.sampoom.android.core.ui.theme.backgroundCardColor -import com.sampoom.android.core.ui.theme.textColor -import androidx.compose.material3.Surface -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.IconButton import androidx.compose.material3.Icon -import androidx.compose.ui.res.painterResource -import com.sampoom.android.R +import androidx.compose.material3.IconButton +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import com.sampoom.android.R +import com.sampoom.android.core.ui.theme.FailRed +import com.sampoom.android.core.ui.theme.White +import com.sampoom.android.core.ui.theme.backgroundCardColor +import com.sampoom.android.core.ui.theme.textColor @Composable fun rememberCommonSnackBarHostState(): SnackbarHostState = remember { SnackbarHostState() } -@Composable -fun ShowErrorSnackBar( - errorMessage: String?, - snackBarHostState: SnackbarHostState, - onConsumed: () -> Unit, - actionLabel: String? = null, - onAction: (() -> Unit)? = null, - duration: SnackbarDuration = SnackbarDuration.Short -) { - LaunchedEffect(errorMessage) { - val message = errorMessage ?: return@LaunchedEffect - val result = snackBarHostState.showSnackbar( - message = message, - actionLabel = actionLabel, - withDismissAction = true, - duration = duration - ) - if (result == SnackbarResult.ActionPerformed) { - onAction?.invoke() - } - onConsumed() - } -} - @Composable fun TopSnackBarHost( hostState: SnackbarHostState, - extraTopPadding: Dp = 0.dp, - showDismissButton: Boolean = true + extraTopPadding: Dp = 16.dp, + showDismissButton: Boolean = true, + isError: Boolean = false ) { Box(modifier = Modifier.fillMaxSize()) { val statusBarTop = WindowInsets.statusBars.asPaddingValues().calculateTopPadding() @@ -75,8 +51,13 @@ fun TopSnackBarHost( .padding(top = statusBarTop + extraTopPadding, start = 16.dp, end = 16.dp), snackbar = { data -> Surface( - color = backgroundCardColor(), - contentColor = textColor(), + color = if (isError) { + FailRed + } else { + backgroundCardColor() + }, + contentColor = if (isError) White else textColor(), + shadowElevation = 4.dp, shape = RoundedCornerShape(12.dp), tonalElevation = 6.dp, ) { @@ -100,7 +81,7 @@ fun TopSnackBarHost( Icon( painter = painterResource(id = R.drawable.outline_close), contentDescription = stringResource(R.string.common_close), - tint = textColor() + tint = if (isError) White else textColor() ) } } diff --git a/app/src/main/java/com/sampoom/android/core/util/GlobalMessageHandler.kt b/app/src/main/java/com/sampoom/android/core/util/GlobalMessageHandler.kt new file mode 100644 index 0000000..c8caa05 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/util/GlobalMessageHandler.kt @@ -0,0 +1,21 @@ +package com.sampoom.android.core.util + +import com.sampoom.android.core.model.SnackBarMessage +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.asSharedFlow +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GlobalMessageHandler @Inject constructor() { + private val _message = MutableStateFlow(null) + val message: SharedFlow = _message.asSharedFlow() + + suspend fun showMessage(message: String, isError: Boolean = false) { + _message.value = SnackBarMessage(message, isError) + delay(100) + _message.value = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/mapper/AuthMappers.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt similarity index 74% rename from app/src/main/java/com/sampoom/android/feature/user/data/mapper/AuthMappers.kt rename to app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt index 2e39f15..73d6d4c 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/mapper/AuthMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt @@ -1,8 +1,8 @@ -package com.sampoom.android.feature.user.data.mapper +package com.sampoom.android.feature.auth.data.mapper -import com.sampoom.android.feature.user.data.remote.dto.GetProfileResponseDto -import com.sampoom.android.feature.user.data.remote.dto.LoginResponseDto -import com.sampoom.android.feature.user.domain.model.User +import com.sampoom.android.feature.auth.data.remote.dto.GetProfileResponseDto +import com.sampoom.android.feature.auth.data.remote.dto.LoginResponseDto +import com.sampoom.android.feature.auth.domain.model.User fun LoginResponseDto.toModel(): User = User( userId = userId, diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt similarity index 56% rename from app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt rename to app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt index b6d6ec9..233274a 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/api/AuthApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt @@ -1,16 +1,16 @@ -package com.sampoom.android.feature.user.data.remote.api +package com.sampoom.android.feature.auth.data.remote.api -import com.sampoom.android.core.network.ApiResponse -import com.sampoom.android.core.network.ApiSuccessResponse -import com.sampoom.android.feature.user.data.remote.dto.LoginRequestDto -import com.sampoom.android.feature.user.data.remote.dto.SignUpRequestDto -import com.sampoom.android.feature.user.data.remote.dto.SignUpResponseDto -import com.sampoom.android.feature.user.data.remote.dto.LoginResponseDto -import com.sampoom.android.feature.user.data.remote.dto.RefreshRequestDto -import com.sampoom.android.feature.user.data.remote.dto.RefreshResponseDto -import com.sampoom.android.feature.user.data.remote.dto.UpdateProfileRequestDto -import com.sampoom.android.feature.user.data.remote.dto.UpdateProfileResponseDto -import com.sampoom.android.feature.user.data.remote.dto.GetProfileResponseDto +import com.sampoom.android.core.model.ApiResponse +import com.sampoom.android.core.model.ApiSuccessResponse +import com.sampoom.android.feature.auth.data.remote.dto.LoginRequestDto +import com.sampoom.android.feature.auth.data.remote.dto.SignUpRequestDto +import com.sampoom.android.feature.auth.data.remote.dto.SignUpResponseDto +import com.sampoom.android.feature.auth.data.remote.dto.LoginResponseDto +import com.sampoom.android.feature.auth.data.remote.dto.RefreshRequestDto +import com.sampoom.android.feature.auth.data.remote.dto.RefreshResponseDto +import com.sampoom.android.feature.auth.data.remote.dto.UpdateProfileRequestDto +import com.sampoom.android.feature.auth.data.remote.dto.UpdateProfileResponseDto +import com.sampoom.android.feature.auth.data.remote.dto.GetProfileResponseDto import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.Headers diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/GetProfileResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/GetProfileResponseDto.kt similarity index 73% rename from app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/GetProfileResponseDto.kt rename to app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/GetProfileResponseDto.kt index 6f6e20f..ff0c29b 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/GetProfileResponseDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/GetProfileResponseDto.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.user.data.remote.dto +package com.sampoom.android.feature.auth.data.remote.dto data class GetProfileResponseDto( val userId: Long, diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/LoginRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginRequestDto.kt similarity index 57% rename from app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/LoginRequestDto.kt rename to app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginRequestDto.kt index 95427ab..136b9ac 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/LoginRequestDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginRequestDto.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.user.data.remote.dto +package com.sampoom.android.feature.auth.data.remote.dto data class LoginRequestDto( val email: String, diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/LoginResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginResponseDto.kt similarity index 76% rename from app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/LoginResponseDto.kt rename to app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginResponseDto.kt index 1d4dfd9..8743a70 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/LoginResponseDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginResponseDto.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.user.data.remote.dto +package com.sampoom.android.feature.auth.data.remote.dto data class LoginResponseDto( val userId: Long, diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/RefreshRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/RefreshRequestDto.kt similarity index 52% rename from app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/RefreshRequestDto.kt rename to app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/RefreshRequestDto.kt index 667e6c6..9589dad 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/RefreshRequestDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/RefreshRequestDto.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.user.data.remote.dto +package com.sampoom.android.feature.auth.data.remote.dto data class RefreshRequestDto( val refreshToken: String diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/RefreshResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/RefreshResponseDto.kt similarity index 67% rename from app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/RefreshResponseDto.kt rename to app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/RefreshResponseDto.kt index e9cfd8b..9b12851 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/RefreshResponseDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/RefreshResponseDto.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.user.data.remote.dto +package com.sampoom.android.feature.auth.data.remote.dto data class RefreshResponseDto( val accessToken: String, diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/SignUpRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpRequestDto.kt similarity index 76% rename from app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/SignUpRequestDto.kt rename to app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpRequestDto.kt index 2f611f8..50cc02b 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/SignUpRequestDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpRequestDto.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.user.data.remote.dto +package com.sampoom.android.feature.auth.data.remote.dto data class SignUpRequestDto( val email: String, diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/SignUpResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpResponseDto.kt similarity index 64% rename from app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/SignUpResponseDto.kt rename to app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpResponseDto.kt index f300491..d683a69 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/SignUpResponseDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/SignUpResponseDto.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.user.data.remote.dto +package com.sampoom.android.feature.auth.data.remote.dto data class SignUpResponseDto( val userId: Long, diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateProfileRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UpdateProfileRequestDto.kt similarity index 71% rename from app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateProfileRequestDto.kt rename to app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UpdateProfileRequestDto.kt index b627e64..8db66be 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateProfileRequestDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UpdateProfileRequestDto.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.user.data.remote.dto +package com.sampoom.android.feature.auth.data.remote.dto data class UpdateProfileRequestDto( val userName: String, diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateProfileResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UpdateProfileResponseDto.kt similarity index 74% rename from app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateProfileResponseDto.kt rename to app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UpdateProfileResponseDto.kt index e877859..12e2ab6 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/remote/dto/UpdateProfileResponseDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/UpdateProfileResponseDto.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.user.data.remote.dto +package com.sampoom.android.feature.auth.data.remote.dto data class UpdateProfileResponseDto( val userId: Long, diff --git a/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt similarity index 67% rename from app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt rename to app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt index 0162745..747122d 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/data/repository/AuthRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt @@ -1,18 +1,15 @@ -package com.sampoom.android.feature.user.data.repository +package com.sampoom.android.feature.auth.data.repository -import android.R.attr.password -import com.sampoom.android.core.datastore.AuthPreferences -import com.sampoom.android.feature.user.data.mapper.mergeWith -import com.sampoom.android.feature.user.data.mapper.toModel -import com.sampoom.android.feature.user.data.remote.api.AuthApi -import com.sampoom.android.feature.user.data.remote.dto.LoginRequestDto -import com.sampoom.android.feature.user.data.remote.dto.RefreshRequestDto -import com.sampoom.android.feature.user.data.remote.dto.SignUpRequestDto -import com.sampoom.android.feature.user.domain.model.User -import com.sampoom.android.feature.user.domain.repository.AuthRepository -import kotlinx.coroutines.CancellationException +import com.sampoom.android.core.preferences.AuthPreferences +import com.sampoom.android.feature.auth.data.mapper.mergeWith +import com.sampoom.android.feature.auth.data.mapper.toModel +import com.sampoom.android.feature.auth.data.remote.api.AuthApi +import com.sampoom.android.feature.auth.data.remote.dto.LoginRequestDto +import com.sampoom.android.feature.auth.data.remote.dto.RefreshRequestDto +import com.sampoom.android.feature.auth.data.remote.dto.SignUpRequestDto +import com.sampoom.android.feature.auth.domain.model.User +import com.sampoom.android.feature.auth.domain.repository.AuthRepository import javax.inject.Inject -import kotlin.math.log class AuthRepositoryImpl @Inject constructor( private val api: AuthApi, @@ -37,8 +34,6 @@ class AuthRepositoryImpl @Inject constructor( )) if (!signUpRes.success) throw Exception(signUpRes.message) signIn(email, password).getOrThrow() - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } @@ -60,8 +55,6 @@ class AuthRepositoryImpl @Inject constructor( preferences.saveUser(user) user - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } @@ -69,8 +62,6 @@ class AuthRepositoryImpl @Inject constructor( return runCatching { val dto = api.logout() if (!dto.success) throw Exception(dto.message) - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } @@ -87,16 +78,12 @@ class AuthRepositoryImpl @Inject constructor( ) preferences.saveUser(updatedUser) updatedUser - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } override suspend fun clearTokens(): Result { return runCatching { preferences.clear() - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } @@ -107,8 +94,6 @@ class AuthRepositoryImpl @Inject constructor( val dto = api.getProfile() if (!dto.success) throw Exception(dto.message) dto.data.toModel() - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/di/AuthModules.kt b/app/src/main/java/com/sampoom/android/feature/auth/di/AuthModules.kt similarity index 71% rename from app/src/main/java/com/sampoom/android/feature/user/di/AuthModules.kt rename to app/src/main/java/com/sampoom/android/feature/auth/di/AuthModules.kt index 0be2f12..87b7f09 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/di/AuthModules.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/di/AuthModules.kt @@ -1,8 +1,8 @@ -package com.sampoom.android.feature.user.di +package com.sampoom.android.feature.auth.di -import com.sampoom.android.feature.user.data.remote.api.AuthApi -import com.sampoom.android.feature.user.data.repository.AuthRepositoryImpl -import com.sampoom.android.feature.user.domain.repository.AuthRepository +import com.sampoom.android.feature.auth.data.remote.api.AuthApi +import com.sampoom.android.feature.auth.data.repository.AuthRepositoryImpl +import com.sampoom.android.feature.auth.domain.repository.AuthRepository import dagger.Binds import dagger.Module import dagger.Provides diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/AuthValidator.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/AuthValidator.kt similarity index 98% rename from app/src/main/java/com/sampoom/android/feature/user/domain/AuthValidator.kt rename to app/src/main/java/com/sampoom/android/feature/auth/domain/AuthValidator.kt index 5b3bc1e..b7c4516 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/AuthValidator.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/AuthValidator.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.user.domain +package com.sampoom.android.feature.auth.domain import com.sampoom.android.R diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/model/User.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt similarity index 82% rename from app/src/main/java/com/sampoom/android/feature/user/domain/model/User.kt rename to app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt index 0baf0d1..266d05b 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/model/User.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.user.domain.model +package com.sampoom.android.feature.auth.domain.model data class User( val userId: Long, diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt similarity index 81% rename from app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt rename to app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt index 6fb920b..a54529d 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/repository/AuthRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt @@ -1,6 +1,6 @@ -package com.sampoom.android.feature.user.domain.repository +package com.sampoom.android.feature.auth.domain.repository -import com.sampoom.android.feature.user.domain.model.User +import com.sampoom.android.feature.auth.domain.model.User interface AuthRepository { suspend fun signUp( diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/CheckLoginStateUseCase.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/CheckLoginStateUseCase.kt similarity index 63% rename from app/src/main/java/com/sampoom/android/feature/user/domain/usecase/CheckLoginStateUseCase.kt rename to app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/CheckLoginStateUseCase.kt index f63ad59..4d2cb89 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/CheckLoginStateUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/CheckLoginStateUseCase.kt @@ -1,6 +1,6 @@ -package com.sampoom.android.feature.user.domain.usecase +package com.sampoom.android.feature.auth.domain.usecase -import com.sampoom.android.feature.user.domain.repository.AuthRepository +import com.sampoom.android.feature.auth.domain.repository.AuthRepository import javax.inject.Inject class CheckLoginStateUseCase @Inject constructor( diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/ClearTokensUseCase.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/ClearTokensUseCase.kt similarity index 63% rename from app/src/main/java/com/sampoom/android/feature/user/domain/usecase/ClearTokensUseCase.kt rename to app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/ClearTokensUseCase.kt index 496279c..a0cc0ff 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/ClearTokensUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/ClearTokensUseCase.kt @@ -1,6 +1,6 @@ -package com.sampoom.android.feature.user.domain.usecase +package com.sampoom.android.feature.auth.domain.usecase -import com.sampoom.android.feature.user.domain.repository.AuthRepository +import com.sampoom.android.feature.auth.domain.repository.AuthRepository import javax.inject.Inject class ClearTokensUseCase @Inject constructor( diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/GetStoredUserUseCase.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/GetStoredUserUseCase.kt similarity index 53% rename from app/src/main/java/com/sampoom/android/feature/user/domain/usecase/GetStoredUserUseCase.kt rename to app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/GetStoredUserUseCase.kt index 5e74eaa..9401624 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/GetStoredUserUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/GetStoredUserUseCase.kt @@ -1,7 +1,7 @@ -package com.sampoom.android.feature.user.domain.usecase +package com.sampoom.android.feature.auth.domain.usecase -import com.sampoom.android.core.datastore.AuthPreferences -import com.sampoom.android.feature.user.domain.model.User +import com.sampoom.android.core.preferences.AuthPreferences +import com.sampoom.android.feature.auth.domain.model.User import javax.inject.Inject class GetStoredUserUseCase @Inject constructor( diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/LoginUseCase.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/LoginUseCase.kt similarity index 57% rename from app/src/main/java/com/sampoom/android/feature/user/domain/usecase/LoginUseCase.kt rename to app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/LoginUseCase.kt index e8edc19..4c47220 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/LoginUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/LoginUseCase.kt @@ -1,7 +1,7 @@ -package com.sampoom.android.feature.user.domain.usecase +package com.sampoom.android.feature.auth.domain.usecase -import com.sampoom.android.feature.user.domain.model.User -import com.sampoom.android.feature.user.domain.repository.AuthRepository +import com.sampoom.android.feature.auth.domain.model.User +import com.sampoom.android.feature.auth.domain.repository.AuthRepository import javax.inject.Inject class LoginUseCase @Inject constructor( diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignOutUseCase.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignOutUseCase.kt similarity index 62% rename from app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignOutUseCase.kt rename to app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignOutUseCase.kt index 7603a8b..026cef0 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignOutUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignOutUseCase.kt @@ -1,6 +1,6 @@ -package com.sampoom.android.feature.user.domain.usecase +package com.sampoom.android.feature.auth.domain.usecase -import com.sampoom.android.feature.user.domain.repository.AuthRepository +import com.sampoom.android.feature.auth.domain.repository.AuthRepository import javax.inject.Inject class SignOutUseCase @Inject constructor( diff --git a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignUpUseCase.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignUpUseCase.kt similarity index 74% rename from app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignUpUseCase.kt rename to app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignUpUseCase.kt index 2e020ce..9e5ec23 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/domain/usecase/SignUpUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/SignUpUseCase.kt @@ -1,7 +1,7 @@ -package com.sampoom.android.feature.user.domain.usecase +package com.sampoom.android.feature.auth.domain.usecase -import com.sampoom.android.feature.user.domain.model.User -import com.sampoom.android.feature.user.domain.repository.AuthRepository +import com.sampoom.android.feature.auth.domain.model.User +import com.sampoom.android.feature.auth.domain.repository.AuthRepository import javax.inject.Inject class SignUpUseCase @Inject constructor( diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/AuthViewModel.kt similarity index 87% rename from app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt rename to app/src/main/java/com/sampoom/android/feature/auth/ui/AuthViewModel.kt index 66ea0cf..efb1e6a 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/AuthViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/AuthViewModel.kt @@ -1,10 +1,10 @@ -package com.sampoom.android.feature.user.ui +package com.sampoom.android.feature.auth.ui import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sampoom.android.feature.user.domain.usecase.CheckLoginStateUseCase -import com.sampoom.android.feature.user.domain.usecase.ClearTokensUseCase -import com.sampoom.android.feature.user.domain.usecase.SignOutUseCase +import com.sampoom.android.feature.auth.domain.usecase.CheckLoginStateUseCase +import com.sampoom.android.feature.auth.domain.usecase.ClearTokensUseCase +import com.sampoom.android.feature.auth.domain.usecase.SignOutUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/LoginScreen.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt similarity index 90% rename from app/src/main/java/com/sampoom/android/feature/user/ui/LoginScreen.kt rename to app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt index 3f0bd19..4be3eb4 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/LoginScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginScreen.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.user.ui +package com.sampoom.android.feature.auth.ui import androidx.compose.foundation.Image import androidx.compose.foundation.clickable @@ -37,9 +37,6 @@ import com.sampoom.android.R import com.sampoom.android.core.ui.component.CommonButton import com.sampoom.android.core.ui.component.CommonTextField import com.sampoom.android.core.ui.theme.Main500 -import com.sampoom.android.core.ui.component.ShowErrorSnackBar -import com.sampoom.android.core.ui.component.rememberCommonSnackBarHostState -import com.sampoom.android.core.ui.component.TopSnackBarHost @Composable fun LoginScreen( @@ -61,15 +58,8 @@ fun LoginScreen( if (uiState.success) onSuccess() } - val snackBarHostState = rememberCommonSnackBarHostState() - ShowErrorSnackBar( - errorMessage = uiState.error, - snackBarHostState = snackBarHostState, - onConsumed = { viewModel.consumeError() } - ) Scaffold( - contentWindowInsets = ScaffoldDefaults.contentWindowInsets, -// snackbarHost = { CommonSnackBarHost(snackBarHostState) } + contentWindowInsets = ScaffoldDefaults.contentWindowInsets ) { innerPadding -> val focusManager = LocalFocusManager.current Box( // 터치 감지용 컨테이너 @@ -159,10 +149,7 @@ fun LoginScreen( style = MaterialTheme.typography.bodyMedium.copy(textAlign = TextAlign.Center), ) } - - // per-screen inline error removed in favor of snackbar } } - TopSnackBarHost(snackBarHostState, extraTopPadding = 16.dp) } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/LoginUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiEvent.kt similarity index 82% rename from app/src/main/java/com/sampoom/android/feature/user/ui/LoginUiEvent.kt rename to app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiEvent.kt index 7b68d9d..ea2af9a 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/LoginUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiEvent.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.user.ui +package com.sampoom.android.feature.auth.ui sealed interface LoginUiEvent { data class EmailChanged(val email: String) : LoginUiEvent diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/LoginUiState.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiState.kt similarity index 85% rename from app/src/main/java/com/sampoom/android/feature/user/ui/LoginUiState.kt rename to app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiState.kt index fb34a74..9fcb9ee 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/LoginUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginUiState.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.user.ui +package com.sampoom.android.feature.auth.ui data class LoginUiState( val email: String = "", @@ -9,7 +9,6 @@ data class LoginUiState( val passwordError: String? = null, val loading: Boolean = false, - val error: String? = null, val success: Boolean = false ) { val isValid: Boolean diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/LoginViewModel.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt similarity index 81% rename from app/src/main/java/com/sampoom/android/feature/user/ui/LoginViewModel.kt rename to app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt index 0b51d6c..a5d59fd 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/LoginViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt @@ -1,13 +1,14 @@ -package com.sampoom.android.feature.user.ui +package com.sampoom.android.feature.auth.ui import android.app.Application import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sampoom.android.core.network.serverMessageOrNull -import com.sampoom.android.feature.user.domain.AuthValidator -import com.sampoom.android.feature.user.domain.ValidationResult -import com.sampoom.android.feature.user.domain.usecase.LoginUseCase +import com.sampoom.android.core.util.GlobalMessageHandler +import com.sampoom.android.feature.auth.domain.AuthValidator +import com.sampoom.android.feature.auth.domain.ValidationResult +import com.sampoom.android.feature.auth.domain.usecase.LoginUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -17,6 +18,7 @@ import javax.inject.Inject @HiltViewModel class LoginViewModel @Inject constructor( + private val messageHandler: GlobalMessageHandler, private val singIn: LoginUseCase, private val application: Application ) : ViewModel() { @@ -81,8 +83,8 @@ class LoginViewModel @Inject constructor( if (!_uiState.value.isValid) return@launch val s = _uiState.value - _uiState.update { it.copy(loading = true, error = null) } - runCatching { singIn(s.email, s.password) } + _uiState.update { it.copy(loading = true) } + singIn(s.email, s.password) .onSuccess { _uiState.update { it.copy(loading = false, success = true) @@ -90,17 +92,13 @@ class LoginViewModel @Inject constructor( } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { - it.copy( - loading = false, - error = backendMessage ?: (throwable.message ?: errorLabel) - ) + it.copy(loading = false) } } Log.d(TAG, "submit: ${_uiState.value}") } - - fun consumeError() { - _uiState.update { it.copy(error = null) } - } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt similarity index 94% rename from app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt rename to app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt index 5f80e76..8123ed3 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.user.ui +package com.sampoom.android.feature.auth.ui import androidx.compose.foundation.Image import androidx.compose.foundation.clickable @@ -41,9 +41,6 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import com.sampoom.android.R import com.sampoom.android.core.ui.component.CommonButton import com.sampoom.android.core.ui.component.CommonTextField -import com.sampoom.android.core.ui.component.ShowErrorSnackBar -import com.sampoom.android.core.ui.component.rememberCommonSnackBarHostState -import com.sampoom.android.core.ui.component.TopSnackBarHost @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -57,7 +54,6 @@ fun SignUpScreen( val positionLabel = stringResource(R.string.signup_title_position) val errorLabel = stringResource(R.string.common_error) - val focusManager = LocalFocusManager.current val nameFocus = remember { FocusRequester() } val branchFocus = remember { FocusRequester() } val positionFocus = remember { FocusRequester() } @@ -76,12 +72,6 @@ fun SignUpScreen( if (state.success) onSuccess() } - val snackBarHostState = rememberCommonSnackBarHostState() - ShowErrorSnackBar( - errorMessage = state.error, - snackBarHostState = snackBarHostState, - onConsumed = { viewModel.consumeError() } - ) Scaffold( topBar = { TopAppBar( @@ -229,5 +219,4 @@ fun SignUpScreen( } } } - TopSnackBarHost(snackBarHostState, extraTopPadding = 16.dp) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt similarity index 91% rename from app/src/main/java/com/sampoom/android/feature/user/ui/SignUpUiEvent.kt rename to app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt index 2f355e0..eb8e77b 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt @@ -1,4 +1,4 @@ -package com.sampoom.android.feature.user.ui +package com.sampoom.android.feature.auth.ui sealed interface SignUpUiEvent { data class NameChanged(val name: String) : SignUpUiEvent diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpUiState.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt similarity index 89% rename from app/src/main/java/com/sampoom/android/feature/user/ui/SignUpUiState.kt rename to app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt index 754be8e..d274bf1 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt @@ -1,8 +1,8 @@ -package com.sampoom.android.feature.user.ui +package com.sampoom.android.feature.auth.ui data class SignUpUiState( val name: String = "", - val workspace: String = "대리점", + val workspace: String = "AGENCY", val branch: String = "", val position: String = "", val email: String = "", @@ -18,7 +18,6 @@ data class SignUpUiState( val passwordCheckError: String? = null, val loading: Boolean = false, - val error: String? = null, val success: Boolean = false ) { val isValid: Boolean diff --git a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpViewModel.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt similarity index 85% rename from app/src/main/java/com/sampoom/android/feature/user/ui/SignUpViewModel.kt rename to app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt index 21754e7..68a3fdb 100644 --- a/app/src/main/java/com/sampoom/android/feature/user/ui/SignUpViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt @@ -1,13 +1,14 @@ -package com.sampoom.android.feature.user.ui +package com.sampoom.android.feature.auth.ui import android.app.Application import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sampoom.android.core.network.serverMessageOrNull -import com.sampoom.android.feature.user.domain.AuthValidator -import com.sampoom.android.feature.user.domain.ValidationResult -import com.sampoom.android.feature.user.domain.usecase.SignUpUseCase +import com.sampoom.android.core.util.GlobalMessageHandler +import com.sampoom.android.feature.auth.domain.AuthValidator +import com.sampoom.android.feature.auth.domain.ValidationResult +import com.sampoom.android.feature.auth.domain.usecase.SignUpUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -17,6 +18,7 @@ import javax.inject.Inject @HiltViewModel class SignUpViewModel @Inject constructor( + private val messageHandler: GlobalMessageHandler, private val singUp: SignUpUseCase, private val application: Application ) : ViewModel() { @@ -134,17 +136,15 @@ class SignUpViewModel @Inject constructor( if (!_state.value.isValid) return@launch val s = _state.value - _state.update { it.copy(loading = true, error = null) } - runCatching { - singUp( - email = s.email, - password = s.password, - workspace = s.workspace, - branch = s.branch, - userName = s.name, - position = s.position - ) - } + _state.update { it.copy(loading = true) } + singUp( + email = s.email, + password = s.password, + workspace = s.workspace, + branch = s.branch, + userName = s.name, + position = s.position + ) .onSuccess { _state.update { it.copy(loading = false, success = true) @@ -152,14 +152,13 @@ class SignUpViewModel @Inject constructor( } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _state.update { - it.copy(loading = false, error = backendMessage ?: (throwable.message ?: errorLabel)) + it.copy(loading = false, ) } } Log.d(TAG, "submit: ${_state.value}") } - - fun consumeError() { - _state.update { it.copy(error = null) } - } } diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt index 06bacec..4e798e9 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt @@ -1,7 +1,7 @@ package com.sampoom.android.feature.cart.data.remote.api -import com.sampoom.android.core.network.ApiResponse -import com.sampoom.android.core.network.ApiSuccessResponse +import com.sampoom.android.core.model.ApiResponse +import com.sampoom.android.core.model.ApiSuccessResponse import com.sampoom.android.feature.cart.data.remote.dto.AddCartRequestDto import com.sampoom.android.feature.cart.data.remote.dto.CartDto import com.sampoom.android.feature.cart.data.remote.dto.UpdateCartRequestDto diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt index 53fe3a0..87cf54c 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt @@ -7,8 +7,6 @@ import com.sampoom.android.feature.cart.data.remote.dto.UpdateCartRequestDto import com.sampoom.android.feature.cart.domain.model.CartList import com.sampoom.android.feature.cart.domain.repository.CartRepository import javax.inject.Inject -import kotlin.Result -import kotlin.coroutines.cancellation.CancellationException class CartRepositoryImpl @Inject constructor( private val api: CartApi @@ -18,8 +16,6 @@ class CartRepositoryImpl @Inject constructor( val dto = api.getCartList() val cartItems = dto.data.map { it.toModel() } CartList(items = cartItems) - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } @@ -30,8 +26,6 @@ class CartRepositoryImpl @Inject constructor( return runCatching { val dto = api.addCart(AddCartRequestDto(partId, quantity)) if (!dto.success) throw Exception(dto.message) - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } @@ -39,8 +33,6 @@ class CartRepositoryImpl @Inject constructor( return runCatching { val dto = api.deleteCart(cartItemId) if (!dto.success) throw Exception(dto.message) - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } @@ -48,8 +40,6 @@ class CartRepositoryImpl @Inject constructor( return runCatching { val dto = api.deleteAllCart() if (!dto.success) throw Exception(dto.message) - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } @@ -60,8 +50,6 @@ class CartRepositoryImpl @Inject constructor( return runCatching { val dto = api.updateCart(cartItemId, UpdateCartRequestDto(quantity)) if (!dto.success) throw Exception(dto.message) - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt index 1c66a5b..28acaaf 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt @@ -65,9 +65,9 @@ fun CartListScreen( viewModel.onEvent(CartListUiEvent.LoadCartList) } - uiState.processedOrder?.let { orders -> + uiState.processedOrder?.let { order -> OrderResultBottomSheet( - order = orders, + order = order, onDismiss = { viewModel.onEvent(CartListUiEvent.DismissOrderResult)} ) } @@ -121,7 +121,6 @@ fun CartListScreen( } } - when { uiState.cartLoading -> { Box( diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiEvent.kt index 15682c9..c240749 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiEvent.kt @@ -7,7 +7,5 @@ sealed interface CartListUiEvent { data class UpdateQuantity(val cartItemId: Long, val quantity: Long) : CartListUiEvent data class DeleteCart(val cartItemId: Long) : CartListUiEvent object DeleteAllCart : CartListUiEvent - object ClearUpdateError : CartListUiEvent - object ClearDeleteError : CartListUiEvent object DismissOrderResult : CartListUiEvent } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt index d005b17..37e10e5 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt @@ -14,5 +14,5 @@ data class CartListUiState( val deleteError: String? = null, val isProcessing: Boolean = false, val processError: String? = null, - val processedOrder: List? = null + val processedOrder: Order? = null ) diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt index 6972a1a..090a5b1 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt @@ -4,6 +4,7 @@ import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.core.util.GlobalMessageHandler import com.sampoom.android.feature.cart.domain.model.CartList import com.sampoom.android.feature.cart.domain.usecase.DeleteAllCartUseCase import com.sampoom.android.feature.cart.domain.usecase.DeleteCartUseCase @@ -19,6 +20,7 @@ import javax.inject.Inject @HiltViewModel class CartListViewModel @Inject constructor( + private val messageHandler: GlobalMessageHandler, private val getCartListUseCase: GetCartUseCase, private val updateCartQuantityUseCase: UpdateCartQuantityUseCase, private val deleteCartUseCase: DeleteCartUseCase, @@ -51,8 +53,6 @@ class CartListViewModel @Inject constructor( is CartListUiEvent.UpdateQuantity -> updateQuantity(event.cartItemId, event.quantity) is CartListUiEvent.DeleteCart -> deleteCart(event.cartItemId) is CartListUiEvent.DeleteAllCart -> deleteAllCart() - is CartListUiEvent.ClearUpdateError -> _uiState.update { it.copy(updateError = null) } - is CartListUiEvent.ClearDeleteError -> _uiState.update { it.copy(deleteError = null) } is CartListUiEvent.DismissOrderResult -> _uiState.update { it.copy(processedOrder = null) } } } @@ -73,10 +73,13 @@ class CartListViewModel @Inject constructor( } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { it.copy( cartLoading = false, - cartError = backendMessage ?: (throwable.message ?: errorLabel) + cartError = error ) } } @@ -90,16 +93,19 @@ class CartListViewModel @Inject constructor( val cartList = CartList(items = _uiState.value.cartList) createOrderUseCase(cartList) - .onSuccess { orderList -> - _uiState.update { it.copy(isProcessing = false, processedOrder = orderList.items) } + .onSuccess { order -> + _uiState.update { it.copy(isProcessing = false, processedOrder = order) } loadCartList() } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { it.copy( isProcessing = false, - processError = backendMessage ?: (throwable.message ?: errorLabel) + processError = error ) } } @@ -118,10 +124,13 @@ class CartListViewModel @Inject constructor( } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { it.copy( isUpdating = false, - updateError = backendMessage ?: (throwable.message ?: errorLabel) + updateError = error ) } } @@ -161,10 +170,13 @@ class CartListViewModel @Inject constructor( } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { it.copy( isDeleting = false, - deleteError = backendMessage ?: (throwable.message ?: errorLabel) + deleteError = error ) } } @@ -183,10 +195,13 @@ class CartListViewModel @Inject constructor( } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { it.copy( isDeleting = false, - deleteError = backendMessage ?: (throwable.message ?: errorLabel) + deleteError = error ) } } diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt index fc7aea3..208de19 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt @@ -1,7 +1,5 @@ package com.sampoom.android.feature.dashboard.ui -import android.os.Build -import androidx.annotation.RequiresApi import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -16,7 +14,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CornerSize import androidx.compose.foundation.shape.RoundedCornerShape @@ -47,6 +44,8 @@ import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.paging.LoadState +import androidx.paging.compose.collectAsLazyPagingItems import com.sampoom.android.R import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent @@ -55,8 +54,8 @@ import com.sampoom.android.core.ui.theme.Main500 import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.feature.auth.domain.model.User import com.sampoom.android.feature.order.domain.model.Order -import com.sampoom.android.feature.user.domain.model.User @Composable fun DashboardScreen( @@ -68,9 +67,9 @@ fun DashboardScreen( ) { val errorLabel = stringResource(R.string.common_error) val uiState by viewModel.uiState.collectAsStateWithLifecycle() - val pullRefreshState = rememberPullToRefreshState() - val isManager = true // TODO: Role 검증 val user by viewModel.user.collectAsStateWithLifecycle() + val pullRefreshState = rememberPullToRefreshState() + val isManager = user?.role == "ADMIN" LaunchedEffect(errorLabel) { viewModel.bindLabel(errorLabel) @@ -162,6 +161,8 @@ fun DashboardScreen( } ) } + + item { Spacer(Modifier.height(100.dp)) } } } } @@ -334,7 +335,6 @@ fun ButtonCard( } } -@RequiresApi(Build.VERSION_CODES.O) @Composable fun OrderListSection( viewModel: DashboardViewModel, @@ -342,6 +342,8 @@ fun OrderListSection( onNavigateOrderDetail: (Order) -> Unit, onNavigationOrder: () -> Unit ) { + val orderListPaged = viewModel.orderListPaged.collectAsLazyPagingItems() + Column( modifier = Modifier.fillMaxWidth() ) { @@ -368,8 +370,8 @@ fun OrderListSection( } } - when { - uiState.dashboardLoading -> { + when (orderListPaged.loadState.refresh) { + is LoadState.Loading -> { Box( modifier = Modifier .fillMaxWidth() @@ -380,7 +382,7 @@ fun OrderListSection( } } - uiState.dashboardError != null -> { + is LoadState.Error -> { Box( modifier = Modifier .fillMaxWidth() @@ -394,34 +396,36 @@ fun OrderListSection( } } - uiState.orderList.isEmpty() -> { - Box( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 32.dp), - contentAlignment = Alignment.Center - ) { - EmptyContent( - message = stringResource(R.string.order_empty_list), - modifier = Modifier.height(200.dp) - ) - } - } - else -> { - LazyColumn( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - items(uiState.orderList) { order -> - OrderItem( - order = order, - onClick = { onNavigateOrderDetail(order) } + if (orderListPaged.itemCount == 0) { + Box( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 32.dp), + contentAlignment = Alignment.Center + ) { + EmptyContent( + message = stringResource(R.string.order_empty_list), + modifier = Modifier.height(200.dp) ) } - item { Spacer(Modifier.height(100.dp)) } + } else { + Column( + modifier = Modifier + .fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + // 처음 5개만 표시 + repeat(minOf(orderListPaged.itemCount, 5)) { index -> + val order = orderListPaged[index] + if (order != null) { + OrderItem( + order = order, + onClick = { onNavigateOrderDetail(order) } + ) + } + } + } } } } diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt index 078baf5..0504236 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt @@ -1,22 +1,25 @@ package com.sampoom.android.feature.dashboard.ui -import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sampoom.android.core.network.serverMessageOrNull +import androidx.paging.PagingData +import androidx.paging.cachedIn +import com.sampoom.android.core.util.GlobalMessageHandler import com.sampoom.android.feature.order.domain.usecase.GetOrderUseCase -import com.sampoom.android.feature.user.domain.model.User -import com.sampoom.android.feature.user.domain.usecase.GetStoredUserUseCase +import com.sampoom.android.feature.auth.domain.model.User +import com.sampoom.android.feature.auth.domain.usecase.GetStoredUserUseCase +import com.sampoom.android.feature.order.domain.model.Order import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class DashboardViewModel @Inject constructor( + private val messageHandler: GlobalMessageHandler, private val getOrderListUseCase: GetOrderUseCase, private val getStoredUserUseCase: GetStoredUserUseCase ): ViewModel() { @@ -31,6 +34,9 @@ class DashboardViewModel @Inject constructor( private val _user = MutableStateFlow(null) val user: StateFlow = _user + val orderListPaged: Flow> = getOrderListUseCase() + .cachedIn(viewModelScope) + private var errorLabel: String = "" private var loadJob: Job? = null @@ -42,41 +48,40 @@ class DashboardViewModel @Inject constructor( viewModelScope.launch { _user.value = getStoredUserUseCase() } - loadOrderList() } fun onEvent(event: DashboardUiEvent) { when (event) { - is DashboardUiEvent.LoadDashboard -> loadOrderList() - is DashboardUiEvent.RetryDashboard -> loadOrderList() + is DashboardUiEvent.LoadDashboard -> {}//loadOrderList() + is DashboardUiEvent.RetryDashboard -> {}//loadOrderList() } } - private fun loadOrderList() { - if (loadJob?.isActive == true) return - loadJob = viewModelScope.launch { - _uiState.update { it.copy(dashboardLoading = true, dashboardError = null) } - - getOrderListUseCase() - .onSuccess { orderList -> - _uiState.update { - it.copy( - orderList = orderList.items.take(5), - dashboardLoading = false, - dashboardError = null - ) - } - } - .onFailure { throwable -> - val backendMessage = throwable.serverMessageOrNull() - _uiState.update { - it.copy( - dashboardLoading = false, - dashboardError = backendMessage ?: (throwable.message ?: errorLabel) - ) - } - } - Log.d(TAG, "submit: ${_uiState.value}") - } - } +// private fun loadOrderList() { +// if (loadJob?.isActive == true) return +// loadJob = viewModelScope.launch { +// _uiState.update { it.copy(dashboardLoading = true, dashboardError = null) } +// +// getOrderListUseCase() +// .onSuccess { orderList -> +// _uiState.update { +// it.copy( +// orderList = orderList.items.take(5), +// dashboardLoading = false, +// dashboardError = null +// ) +// } +// } +// .onFailure { throwable -> +// val backendMessage = throwable.serverMessageOrNull() +// _uiState.update { +// it.copy( +// dashboardLoading = false, +// dashboardError = backendMessage ?: (throwable.message ?: errorLabel) +// ) +// } +// } +// Log.d(TAG, "submit: ${_uiState.value}") +// } +// } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/paging/OrderPagingSource.kt b/app/src/main/java/com/sampoom/android/feature/order/data/paging/OrderPagingSource.kt new file mode 100644 index 0000000..d631e83 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/data/paging/OrderPagingSource.kt @@ -0,0 +1,47 @@ +package com.sampoom.android.feature.order.data.paging + +import androidx.paging.PagingSource +import androidx.paging.PagingState +import com.sampoom.android.core.preferences.AuthPreferences +import com.sampoom.android.feature.order.data.mapper.toModel +import com.sampoom.android.feature.order.data.remote.api.OrderApi +import com.sampoom.android.feature.order.domain.model.Order +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +class OrderPagingSource @AssistedInject constructor( + private val api: OrderApi, + private val authPreferences: AuthPreferences +) : PagingSource() { + + @AssistedFactory + interface Factory { + fun create(): OrderPagingSource + } + + override fun getRefreshKey(state: PagingState): Int? { + return state.anchorPosition?.let { anchorPosition -> + state.closestPageToPosition(anchorPosition)?.prevKey?.plus(1) + ?: state.closestPageToPosition(anchorPosition)?.nextKey?.minus(1) + } + } + + override suspend fun load(params: LoadParams): LoadResult { + return try { + val agencyName = authPreferences.getStoredUser()?.branch ?: "" + val page = params.key ?: 0 + val pageSize = params.loadSize + val response = api.getOrderList(agencyName, page, pageSize) + + val orders = response.data.content.map { it.toModel() } + + LoadResult.Page( + data = orders, + prevKey = if (page == 0) null else page - 1, + nextKey = if (page < response.data.totalPages - 1) page + 1 else null + ) + } catch (e: Exception) { + LoadResult.Error(e) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt b/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt index c0dedb5..11496b1 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt @@ -1,35 +1,40 @@ package com.sampoom.android.feature.order.data.remote.api -import com.sampoom.android.core.network.ApiResponse -import com.sampoom.android.core.network.ApiSuccessResponse +import com.sampoom.android.core.model.ApiResponse +import com.sampoom.android.core.model.ApiSuccessResponse import com.sampoom.android.feature.order.data.remote.dto.OrderDto +import com.sampoom.android.feature.order.data.remote.dto.OrderListDto import com.sampoom.android.feature.order.data.remote.dto.OrderRequestDto import retrofit2.http.Body -import retrofit2.http.DELETE import retrofit2.http.GET import retrofit2.http.PATCH import retrofit2.http.POST import retrofit2.http.Path +import retrofit2.http.Query // TODO: AgencyId 동적 주입 interface OrderApi { // 주문 목록 조회 - @GET("agency/1/orders") - suspend fun getOrderList(): ApiResponse> + @GET("order/requested") + suspend fun getOrderList( + @Query("from") agencyName: String, + @Query("page") page: Int = 0, + @Query("size") size: Int = 20 + ): ApiResponse // 주문 생성 @POST("order/") - suspend fun createOrder(@Body orderRequestDto: OrderRequestDto): ApiResponse> + suspend fun createOrder(@Body orderRequestDto: OrderRequestDto): ApiResponse // 주문 입고 처리 @PATCH("agency/1/orders/{orderId}/receive") suspend fun receiveOrder(@Path("orderId") orderId: Long): ApiSuccessResponse // 주문 상세 조회 - @GET("agency/1/orders/{orderId}") - suspend fun getOrderDetail(@Path("orderId") orderId: Long): ApiResponse> + @GET("order/{orderId}") + suspend fun getOrderDetail(@Path("orderId") orderId: Long): ApiResponse // 주문 취소 - @DELETE("agency/1/orders/{orderId}") + @PATCH("order/cancel/{orderId}") suspend fun cancelOrder(@Path("orderId") orderId: Long): ApiSuccessResponse } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderListDto.kt b/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderListDto.kt new file mode 100644 index 0000000..8859d14 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderListDto.kt @@ -0,0 +1,8 @@ +package com.sampoom.android.feature.order.data.remote.dto + +data class OrderListDto( + val content: List, + val totalElements: Int, + val totalPages: Int, + val currentPage: Int +) diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderRequestDto.kt index 62ec9a3..abee6e4 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderRequestDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderRequestDto.kt @@ -1,11 +1,6 @@ package com.sampoom.android.feature.order.data.remote.dto data class OrderRequestDto( - val branch: String, - val items: List -) - -data class OrderItems( - val code: String, - val quantity: Long + val agencyName: String, // branch + val items: List ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt index cf0c399..9f07890 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt @@ -1,46 +1,66 @@ package com.sampoom.android.feature.order.data.repository -import com.sampoom.android.core.datastore.AuthPreferences +import androidx.paging.Pager +import androidx.paging.PagingConfig +import androidx.paging.PagingData +import com.sampoom.android.core.preferences.AuthPreferences import com.sampoom.android.feature.cart.domain.model.CartList import com.sampoom.android.feature.order.data.mapper.toModel +import com.sampoom.android.feature.order.data.paging.OrderPagingSource import com.sampoom.android.feature.order.data.remote.api.OrderApi -import com.sampoom.android.feature.order.data.remote.dto.OrderItems +import com.sampoom.android.feature.order.data.remote.dto.OrderCategoryDto +import com.sampoom.android.feature.order.data.remote.dto.OrderGroupDto +import com.sampoom.android.feature.order.data.remote.dto.OrderPartDto import com.sampoom.android.feature.order.data.remote.dto.OrderRequestDto -import com.sampoom.android.feature.order.domain.model.OrderList +import com.sampoom.android.feature.order.domain.model.Order import com.sampoom.android.feature.order.domain.repository.OrderRepository +import kotlinx.coroutines.flow.Flow import javax.inject.Inject -import kotlin.coroutines.cancellation.CancellationException class OrderRepositoryImpl @Inject constructor( private val api: OrderApi, - private val preferences: AuthPreferences + private val preferences: AuthPreferences, + private val pagingSourceFactory: OrderPagingSource.Factory ) : OrderRepository { - override suspend fun getOrderList(): Result { - return runCatching { - val dto = api.getOrderList() - val orderItems = dto.data.map { it.toModel() } - OrderList(items = orderItems) - }.onFailure { exception -> - if (exception is CancellationException) throw exception - } + override fun getOrderList(): Flow> { + return Pager( + config = PagingConfig(pageSize = 20), + pagingSourceFactory = { pagingSourceFactory.create() } + ).flow } - override suspend fun createOrder(cartList: CartList): Result { + override suspend fun createOrder(cartList: CartList): Result { return runCatching { - val user = preferences.getStoredUser() ?: throw Exception("No user information available") - val items = cartList.items - .flatMap { it.groups } - .flatMap { it.parts } - .map { part -> OrderItems(code = part.code, quantity = part.quantity) } + val agencyName = preferences.getStoredUser()?.branch ?: throw Exception() + val items = cartList.items.map { cart -> + OrderCategoryDto( + categoryId = cart.categoryId, + categoryName = cart.categoryName, + groups = cart.groups.map { group -> + OrderGroupDto( + groupId = group.groupId, + groupName = group.groupName, + parts = group.parts.map { part -> + OrderPartDto( + partId = part.partId, + code = part.code, + name = part.name, + quantity = part.quantity + ) + } + ) + } + ) + } + val request = OrderRequestDto( - branch = user.branch, + agencyName = agencyName, items = items ) + val dto = api.createOrder(request) - val orderItems = dto.data.map { it.toModel() } - OrderList(items = orderItems) - }.onFailure { exception -> - if (exception is CancellationException) throw exception + if (!dto.success) throw Exception(dto.message) + dto.data.toModel() } } @@ -48,18 +68,14 @@ class OrderRepositoryImpl @Inject constructor( return runCatching { val dto = api.receiveOrder(orderId) if (!dto.success) throw Exception(dto.message) - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } - override suspend fun getOrderDetail(orderId: Long): Result { + override suspend fun getOrderDetail(orderId: Long): Result { return runCatching { val dto = api.getOrderDetail(orderId) - val orderItems = dto.data.map { it.toModel() } - OrderList(items = orderItems) - }.onFailure { exception -> - if (exception is CancellationException) throw exception + if (!dto.success) throw Exception(dto.message) + dto.data.toModel() } } @@ -67,8 +83,6 @@ class OrderRepositoryImpl @Inject constructor( return runCatching { val dto = api.cancelOrder(orderId) if (!dto.success) throw Exception(dto.message) - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt index 80cd1d2..edf9adf 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt @@ -1,12 +1,16 @@ package com.sampoom.android.feature.order.domain.repository +import androidx.paging.PagingData import com.sampoom.android.feature.cart.domain.model.CartList +import com.sampoom.android.feature.order.domain.model.Order import com.sampoom.android.feature.order.domain.model.OrderList +import kotlinx.coroutines.flow.Flow interface OrderRepository { - suspend fun getOrderList(): Result - suspend fun createOrder(cartList: CartList): Result +// suspend fun getOrderList(): Result + fun getOrderList(): Flow> + suspend fun createOrder(cartList: CartList): Result suspend fun receiveOrder(orderId: Long): Result - suspend fun getOrderDetail(orderId: Long): Result + suspend fun getOrderDetail(orderId: Long): Result suspend fun cancelOrder(orderId: Long): Result } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CreateOrderUseCase.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CreateOrderUseCase.kt index f94d1c4..868c772 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CreateOrderUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CreateOrderUseCase.kt @@ -1,12 +1,12 @@ package com.sampoom.android.feature.order.domain.usecase import com.sampoom.android.feature.cart.domain.model.CartList -import com.sampoom.android.feature.order.domain.model.OrderList +import com.sampoom.android.feature.order.domain.model.Order import com.sampoom.android.feature.order.domain.repository.OrderRepository import javax.inject.Inject class CreateOrderUseCase @Inject constructor( private val repository: OrderRepository ){ - suspend operator fun invoke(cartList: CartList): Result = repository.createOrder(cartList) + suspend operator fun invoke(cartList: CartList): Result = repository.createOrder(cartList) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderDetailUseCase.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderDetailUseCase.kt index a3656d4..3e3b73c 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderDetailUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderDetailUseCase.kt @@ -1,11 +1,11 @@ package com.sampoom.android.feature.order.domain.usecase -import com.sampoom.android.feature.order.domain.model.OrderList +import com.sampoom.android.feature.order.domain.model.Order import com.sampoom.android.feature.order.domain.repository.OrderRepository import javax.inject.Inject class GetOrderDetailUseCase @Inject constructor( private val repository: OrderRepository ) { - suspend operator fun invoke(orderId: Long): Result = repository.getOrderDetail(orderId) + suspend operator fun invoke(orderId: Long): Result = repository.getOrderDetail(orderId) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderUseCase.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderUseCase.kt index 02bc766..9b8afa2 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderUseCase.kt @@ -1,11 +1,14 @@ package com.sampoom.android.feature.order.domain.usecase +import androidx.paging.PagingData +import com.sampoom.android.feature.order.domain.model.Order import com.sampoom.android.feature.order.domain.model.OrderList import com.sampoom.android.feature.order.domain.repository.OrderRepository +import kotlinx.coroutines.flow.Flow import javax.inject.Inject class GetOrderUseCase @Inject constructor( private val repository: OrderRepository ){ - suspend operator fun invoke(): Result = repository.getOrderList() + operator fun invoke(): Flow> = repository.getOrderList() } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailContent.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailContent.kt index f30e900..f9d0c00 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailContent.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailContent.kt @@ -28,7 +28,7 @@ import kotlin.collections.forEach @Composable fun OrderDetailContent( - order: List, + order: Order, modifier: Modifier = Modifier ) { LazyColumn( @@ -37,27 +37,25 @@ fun OrderDetailContent( .padding(horizontal = 16.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { - order.forEach { order -> - item { - OrderInfoCard(order = order) - } - item { - Text( - text = stringResource(R.string.order_detail_order_items_title), - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold, - color = textColor() - ) - } - order.items.forEach { category -> - category.groups.forEach { group -> - item { - OrderSection( - categoryName = category.categoryName, - groupName = group.groupName, - parts = group.parts - ) - } + item { + OrderInfoCard(order = order) + } + item { + Text( + text = stringResource(R.string.order_detail_order_items_title), + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold, + color = textColor() + ) + } + order.items.forEach { category -> + category.groups.forEach { group -> + item { + OrderSection( + categoryName = category.categoryName, + groupName = group.groupName, + parts = group.parts + ) } } } diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt index d67385d..e5aba2d 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt @@ -1,12 +1,12 @@ package com.sampoom.android.feature.order.ui -import android.widget.Toast import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.material3.AlertDialog @@ -30,7 +30,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp @@ -39,7 +38,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.sampoom.android.R import com.sampoom.android.core.ui.component.ButtonVariant import com.sampoom.android.core.ui.component.CommonButton -import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent import com.sampoom.android.feature.order.domain.model.OrderStatus @@ -49,16 +47,21 @@ fun OrderDetailScreen( onNavigateBack: () -> Unit = {}, viewModel: OrderDetailViewModel = hiltViewModel() ) { + val errorLabel = stringResource(R.string.common_error) + val cancelLabel = stringResource(R.string.order_detail_toast_order_cancel) + val receiveLabel = stringResource(R.string.order_detail_toast_order_receive) val uiState by viewModel.uiState.collectAsStateWithLifecycle() val pullRefreshState = rememberPullToRefreshState() var showCancelOrderDialog by remember { mutableStateOf(false) } var showReceiveOrderDialog by remember { mutableStateOf(false) } - val context = LocalContext.current + + LaunchedEffect(errorLabel, cancelLabel, receiveLabel) { + viewModel.bindLabel(errorLabel, cancelLabel, receiveLabel) + } // 성공 시 Toast 표시 후 다이얼로그 닫기 LaunchedEffect(uiState.isProcessingCancelSuccess) { if (uiState.isProcessingCancelSuccess) { - Toast.makeText(context, context.getString(R.string.order_detail_toast_order_cancel), Toast.LENGTH_SHORT).show() viewModel.clearSuccess() viewModel.onEvent(OrderDetailUiEvent.LoadOrder) } @@ -67,20 +70,11 @@ fun OrderDetailScreen( // 성공 시 Toast 표시 후 다이얼로그 닫기 LaunchedEffect(uiState.isProcessingReceiveSuccess) { if (uiState.isProcessingReceiveSuccess) { - Toast.makeText(context, context.getString(R.string.order_detail_toast_order_receive), Toast.LENGTH_SHORT).show() viewModel.clearSuccess() viewModel.onEvent(OrderDetailUiEvent.LoadOrder) } } - // 실패 시 Toast 표시 - LaunchedEffect(uiState.isProcessingError) { - uiState.isProcessingError?.let { error -> - Toast.makeText(context, error, Toast.LENGTH_LONG).show() - viewModel.onEvent(OrderDetailUiEvent.ClearError) - } - } - PullToRefreshBox( isRefreshing = false, onRefresh = { viewModel.onEvent(OrderDetailUiEvent.LoadOrder) }, @@ -111,10 +105,11 @@ fun OrderDetailScreen( ) }, bottomBar = { - val orderStatus = uiState.orderDetail.firstOrNull()?.status + val orderStatus = uiState.orderDetail?.status Row( modifier = Modifier .fillMaxWidth() + .navigationBarsPadding() .padding(16.dp) ) { CommonButton( @@ -161,20 +156,22 @@ fun OrderDetailScreen( ) } - uiState.orderDetail.isEmpty() -> { - EmptyContent( - message = stringResource(R.string.order_empty_list), - modifier = Modifier - .height(200.dp) - .fillMaxWidth() - ) - } +// uiState.orderDetail -> { +// EmptyContent( +// message = stringResource(R.string.order_empty_list), +// modifier = Modifier +// .height(200.dp) +// .fillMaxWidth() +// ) +// } else -> { - OrderDetailContent( - order = uiState.orderDetail, - modifier = Modifier.padding(innerPadding) - ) + uiState.orderDetail?.let { order -> + OrderDetailContent( + order = order, + modifier = Modifier.padding(innerPadding) + ) + } } } } diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiEvent.kt index 90e3fb5..41a3f6a 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiEvent.kt @@ -5,5 +5,4 @@ sealed interface OrderDetailUiEvent { object RetryOrder : OrderDetailUiEvent object ReceiveOrder : OrderDetailUiEvent object CancelOrder : OrderDetailUiEvent - object ClearError : OrderDetailUiEvent } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiState.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiState.kt index fd4a4a7..bfa7f3b 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailUiState.kt @@ -3,11 +3,10 @@ package com.sampoom.android.feature.order.ui import com.sampoom.android.feature.order.domain.model.Order data class OrderDetailUiState( - val orderDetail: List = emptyList(), + val orderDetail: Order? = null, val orderDetailLoading: Boolean = false, val orderDetailError: String? = null, val isProcessing: Boolean = false, val isProcessingCancelSuccess: Boolean = false, val isProcessingReceiveSuccess: Boolean = false, - val isProcessingError: String? = null ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt index d4b57a4..58eaf64 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt @@ -5,11 +5,11 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.core.util.GlobalMessageHandler import com.sampoom.android.feature.order.domain.usecase.CancelOrderUseCase import com.sampoom.android.feature.order.domain.usecase.GetOrderDetailUseCase import com.sampoom.android.feature.order.domain.usecase.ReceiveOrderUseCase import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.CancellationException import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update @@ -18,6 +18,7 @@ import javax.inject.Inject @HiltViewModel class OrderDetailViewModel @Inject constructor( + private val messageHandler: GlobalMessageHandler, private val getOrderDetailUseCase: GetOrderDetailUseCase, private val cancelOrderUseCase: CancelOrderUseCase, private val receiveOrderUseCase: ReceiveOrderUseCase, @@ -46,9 +47,13 @@ class OrderDetailViewModel @Inject constructor( } private var errorLabel: String = "" + private var cancelLabel: String = "" + private var receiveLabel: String = "" - fun bindLabel(error: String) { + fun bindLabel(error: String, cancel: String, receive: String) { errorLabel = error + cancelLabel = cancel + receiveLabel = receive } init { @@ -62,7 +67,6 @@ class OrderDetailViewModel @Inject constructor( is OrderDetailUiEvent.RetryOrder -> loadOrderDetail(getOrderId()) is OrderDetailUiEvent.CancelOrder -> cancelOrder(getOrderId()) is OrderDetailUiEvent.ReceiveOrder -> receiveOrder(getOrderId()) - is OrderDetailUiEvent.ClearError -> _uiState.update { it.copy(isProcessingError = null) } } } @@ -71,10 +75,10 @@ class OrderDetailViewModel @Inject constructor( _uiState.update { it.copy(orderDetailLoading = true, orderDetailError = null) } getOrderDetailUseCase(orderId) - .onSuccess { orderList -> + .onSuccess { order -> _uiState.update { it.copy( - orderDetail = orderList.items, + orderDetail = order, orderDetailLoading = false, orderDetailError = null ) @@ -82,10 +86,13 @@ class OrderDetailViewModel @Inject constructor( } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { it.copy( orderDetailLoading = false, - orderDetailError = backendMessage ?: (throwable.message ?: errorLabel) + orderDetailError = error ) } } @@ -95,25 +102,25 @@ class OrderDetailViewModel @Inject constructor( private fun cancelOrder(orderId: Long) { viewModelScope.launch { - _uiState.update { it.copy(isProcessing = true, isProcessingError = null) } + _uiState.update { it.copy(isProcessing = true) } cancelOrderUseCase(orderId) .onSuccess { + messageHandler.showMessage(message = cancelLabel, isError = true) _uiState.update { it.copy( isProcessing = false, - isProcessingCancelSuccess = true, - isProcessingError = null + isProcessingCancelSuccess = true ) } } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { - it.copy( - isProcessing = false, - isProcessingError = backendMessage ?: (throwable.message ?: errorLabel) - ) + it.copy(isProcessing = false) } } Log.d(TAG, "submit: ${_uiState.value}") @@ -122,25 +129,25 @@ class OrderDetailViewModel @Inject constructor( private fun receiveOrder(orderId: Long) { viewModelScope.launch { - _uiState.update { it.copy(isProcessing = true, isProcessingError = null) } + _uiState.update { it.copy(isProcessing = true) } receiveOrderUseCase(orderId) .onSuccess { + messageHandler.showMessage(message = receiveLabel, isError = true) _uiState.update { it.copy( isProcessing = false, - isProcessingReceiveSuccess = true, - isProcessingError = null + isProcessingReceiveSuccess = true ) } } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { - it.copy( - isProcessing = false, - isProcessingError = backendMessage ?: (throwable.message ?: errorLabel) - ) + it.copy(isProcessing = false) } } Log.d(TAG, "submit: ${_uiState.value}") diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt index dd5069b..b2739a7 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt @@ -30,12 +30,15 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.paging.LoadState +import androidx.paging.compose.collectAsLazyPagingItems +import androidx.paging.compose.itemKey import com.sampoom.android.R import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent import com.sampoom.android.core.ui.component.OrderItem +import com.sampoom.android.core.ui.theme.FailRed import com.sampoom.android.core.ui.theme.textColor -import com.sampoom.android.core.util.formatDate import com.sampoom.android.feature.order.domain.model.Order @OptIn(ExperimentalMaterialApi::class) @@ -47,6 +50,7 @@ fun OrderListScreen( ) { val errorLabel = stringResource(R.string.common_error) val uiState by viewModel.uiState.collectAsStateWithLifecycle() + val orderListPaged = viewModel.orderListPaged.collectAsLazyPagingItems() val pullRefreshState = rememberPullToRefreshState() val listState = rememberSaveable(saver = LazyListState.Saver) { LazyListState() } @@ -56,7 +60,7 @@ fun OrderListScreen( PullToRefreshBox( isRefreshing = false, - onRefresh = { viewModel.onEvent(OrderListUiEvent.LoadOrderList) }, + onRefresh = { orderListPaged.refresh() }, state = pullRefreshState, modifier = Modifier.fillMaxSize(), indicator = { @@ -86,8 +90,8 @@ fun OrderListScreen( ) } - when { - uiState.orderLoading -> { + when (orderListPaged.loadState.refresh) { + is LoadState.Loading -> { Box( modifier = Modifier .fillMaxSize(), @@ -97,27 +101,14 @@ fun OrderListScreen( } } - uiState.orderError != null -> { + is LoadState.Error -> { Box( modifier = Modifier .fillMaxSize(), contentAlignment = Alignment.Center ) { ErrorContent( - onRetry = { viewModel.onEvent(OrderListUiEvent.RetryOrderList) }, - modifier = Modifier.height(200.dp) - ) - } - } - - uiState.orderList.isEmpty() -> { - Box( - modifier = Modifier - .fillMaxSize(), - contentAlignment = Alignment.Center - ) { - EmptyContent( - message = stringResource(R.string.order_empty_list), + onRetry = { orderListPaged.retry() }, modifier = Modifier.height(200.dp) ) } @@ -125,18 +116,71 @@ fun OrderListScreen( else -> { LazyColumn( - state = listState, modifier = Modifier .fillMaxSize() .padding(horizontal = 16.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { - items(uiState.orderList) { order -> - OrderItem( - order = order, - onClick = { onNavigateOrderDetail(order) } - ) + items( + count = orderListPaged.itemCount, + key = orderListPaged.itemKey { it.orderId } + ) { index -> + val order = orderListPaged[index] + if (order != null) { + OrderItem( + order = order, + onClick = { onNavigateOrderDetail(order) } + ) + } + } + + // 로딩 상태 처리 + item { + when (orderListPaged.loadState.append) { + is LoadState.Loading -> { + Box( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + is LoadState.Error -> { + Box( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + contentAlignment = Alignment.Center + ) { + Text( + text = stringResource(R.string.common_error), + color = FailRed + ) + } + } + else -> {} + } } + + // 빈 상태 처리 + if (orderListPaged.loadState.refresh !is LoadState.Loading && orderListPaged.itemCount == 0) { + item { + Box( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + contentAlignment = Alignment.Center + ) { + EmptyContent( + message = stringResource(R.string.order_empty_list), + modifier = Modifier.height(200.dp) + ) + } + } + } + item { Spacer(Modifier.height(100.dp)) } } } diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt index 4f2d1f9..c7bc0b4 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListViewModel.kt @@ -1,23 +1,21 @@ package com.sampoom.android.feature.order.ui -import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sampoom.android.core.network.serverMessageOrNull +import androidx.paging.PagingData +import androidx.paging.cachedIn +import com.sampoom.android.core.util.GlobalMessageHandler +import com.sampoom.android.feature.order.domain.model.Order import com.sampoom.android.feature.order.domain.usecase.GetOrderUseCase import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.CancellationException -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import javax.inject.Inject @HiltViewModel class OrderListViewModel @Inject constructor( + private val messageHandler: GlobalMessageHandler, private val getOrderListUseCase: GetOrderUseCase ) : ViewModel() { @@ -29,48 +27,18 @@ class OrderListViewModel @Inject constructor( val uiState: StateFlow = _uiState private var errorLabel: String = "" - private var loadJob: Job? = null fun bindLabel(error: String) { errorLabel = error } - init { - loadOrderList() - } + val orderListPaged: Flow> = getOrderListUseCase() + .cachedIn(viewModelScope) fun onEvent(event: OrderListUiEvent) { when (event) { - is OrderListUiEvent.LoadOrderList -> loadOrderList() - is OrderListUiEvent.RetryOrderList -> loadOrderList() - } - } - - private fun loadOrderList() { - if (loadJob?.isActive == true) return - loadJob = viewModelScope.launch { - _uiState.update { it.copy(orderLoading = true, orderError = null) } - - getOrderListUseCase() - .onSuccess { orderList -> - _uiState.update { - it.copy( - orderList = orderList.items, - orderLoading = false, - orderError = null - ) - } - } - .onFailure { throwable -> - val backendMessage = throwable.serverMessageOrNull() - _uiState.update { - it.copy( - orderLoading = false, - orderError = backendMessage ?: (throwable.message ?: errorLabel ) - ) - } - } - Log.d(TAG, "submit: ${_uiState.value}") + is OrderListUiEvent.LoadOrderList -> {}//loadOrderList() + is OrderListUiEvent.RetryOrderList -> {}//loadOrderList() } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt index e859080..6269c33 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt @@ -46,7 +46,7 @@ import com.sampoom.android.feature.order.domain.model.OrderStatus @OptIn(ExperimentalMaterial3Api::class) @Composable fun OrderResultBottomSheet( - order: List, + order: Order, onDismiss: () -> Unit, viewModel: OrderDetailViewModel = hiltViewModel() ) { @@ -57,8 +57,8 @@ fun OrderResultBottomSheet( var showCancelOrderDialog by remember { mutableStateOf(false) } val context = LocalContext.current - LaunchedEffect(order.firstOrNull()?.orderId) { - if (order.isNotEmpty()) viewModel.setOrderIdFromApi(order.first().orderId) + LaunchedEffect(order.orderId) { + viewModel.setOrderIdFromApi(order.orderId) } // 성공 시 Toast 표시 후 다이얼로그 닫기 @@ -70,14 +70,6 @@ fun OrderResultBottomSheet( } } - // 실패 시 Toast 표시 - LaunchedEffect(uiState.isProcessingError) { - uiState.isProcessingError?.let { error -> - Toast.makeText(context, error, Toast.LENGTH_LONG).show() - viewModel.onEvent(OrderDetailUiEvent.ClearError) - } - } - ModalBottomSheet( onDismissRequest = onDismiss, sheetState = sheetState @@ -105,12 +97,11 @@ fun OrderResultBottomSheet( .fillMaxWidth() .padding(16.dp) ) { - val orderStatus = order.firstOrNull()?.status + val orderStatus = order.status CommonButton( modifier = Modifier.weight(1f), variant = ButtonVariant.Error, - enabled = orderStatus != null && - !uiState.isProcessing && + enabled = !uiState.isProcessing && orderStatus == OrderStatus.PENDING, onClick = { showCancelOrderDialog = true } ) { diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt index d7ee115..c4f198a 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt @@ -1,7 +1,7 @@ package com.sampoom.android.feature.outbound.data.remote.api -import com.sampoom.android.core.network.ApiResponse -import com.sampoom.android.core.network.ApiSuccessResponse +import com.sampoom.android.core.model.ApiResponse +import com.sampoom.android.core.model.ApiSuccessResponse import com.sampoom.android.feature.outbound.data.remote.dto.AddOutboundRequestDto import com.sampoom.android.feature.outbound.data.remote.dto.OutboundDto import com.sampoom.android.feature.outbound.data.remote.dto.UpdateOutboundRequestDto diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt index 2ca541c..fb9658f 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt @@ -7,7 +7,6 @@ import com.sampoom.android.feature.outbound.data.remote.dto.UpdateOutboundReques import com.sampoom.android.feature.outbound.domain.model.OutboundList import com.sampoom.android.feature.outbound.domain.repository.OutboundRepository import jakarta.inject.Inject -import kotlin.coroutines.cancellation.CancellationException class OutboundRepositoryImpl @Inject constructor( private val api: OutboundApi @@ -17,8 +16,6 @@ class OutboundRepositoryImpl @Inject constructor( val dto = api.getOutboundList() val outboundItems = dto.data.map { it.toModel() } OutboundList(items = outboundItems) - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } @@ -26,8 +23,6 @@ class OutboundRepositoryImpl @Inject constructor( return runCatching { val dto = api.processOutbound() if (!dto.success) throw Exception(dto.message) - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } @@ -38,8 +33,6 @@ class OutboundRepositoryImpl @Inject constructor( return runCatching { val dto = api.addOutbound(AddOutboundRequestDto(partId, quantity)) if (!dto.success) throw Exception(dto.message) - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } @@ -47,8 +40,6 @@ class OutboundRepositoryImpl @Inject constructor( return runCatching { val dto = api.deleteOutbound(outboundId) if (!dto.success) throw Exception(dto.message) - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } @@ -56,8 +47,6 @@ class OutboundRepositoryImpl @Inject constructor( return runCatching { val dto = api.deleteAllOutbound() if (!dto.success) throw Exception(dto.message) - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } @@ -68,8 +57,6 @@ class OutboundRepositoryImpl @Inject constructor( return runCatching { val dto = api.updateOutbound(outboundId, UpdateOutboundRequestDto(quantity)) if (!dto.success) throw Exception(dto.message) - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt index 7888457..2d681ee 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt @@ -58,24 +58,23 @@ fun OutboundListScreen( viewModel: OutboundListViewModel = hiltViewModel() ) { val errorLabel = stringResource(R.string.common_error) + val successLabel = stringResource(R.string.outbound_toast_order_text) val uiState by viewModel.uiState.collectAsStateWithLifecycle() val pullRefreshState = rememberPullToRefreshState() var showEmptyOutboundDialog by remember { mutableStateOf(false) } var showConfirmDialog by remember { mutableStateOf(false) } - val context = LocalContext.current LaunchedEffect(Unit) { viewModel.clearSuccess() } LaunchedEffect(errorLabel) { - viewModel.bindLabel(errorLabel) + viewModel.bindLabel(errorLabel, successLabel) viewModel.onEvent(OutboundListUiEvent.LoadOutboundList) } LaunchedEffect(uiState.isOrderSuccess) { if (uiState.isOrderSuccess) { - Toast.makeText(context, context.getString(R.string.outbound_toast_order_text), Toast.LENGTH_SHORT).show() viewModel.clearSuccess() } } diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiEvent.kt index 48a2ca2..c1f2054 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiEvent.kt @@ -7,6 +7,4 @@ sealed interface OutboundListUiEvent { data class UpdateQuantity(val outboundId: Long, val quantity: Long) : OutboundListUiEvent data class DeleteOutbound(val outboundId: Long) : OutboundListUiEvent object DeleteAllOutbound : OutboundListUiEvent - object ClearUpdateError : OutboundListUiEvent - object ClearDeleteError : OutboundListUiEvent } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt index 65ba96d..3a49bc7 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt @@ -8,8 +8,6 @@ data class OutboundListUiState( val outboundError: String? = null, val selectedOutbound: Outbound? = null, val isUpdating: Boolean = false, - val updateError: String? = null, val isDeleting: Boolean = false, - val deleteError: String? = null, val isOrderSuccess: Boolean = false ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt index 90bae80..d6ac4ce 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt @@ -4,6 +4,7 @@ import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.core.util.GlobalMessageHandler import com.sampoom.android.feature.outbound.domain.usecase.DeleteAllOutboundUseCase import com.sampoom.android.feature.outbound.domain.usecase.DeleteOutboundUseCase import com.sampoom.android.feature.outbound.domain.usecase.GetOutboundUseCase @@ -19,6 +20,7 @@ import javax.inject.Inject @HiltViewModel class OutboundListViewModel @Inject constructor( + private val messageHandler: GlobalMessageHandler, private val getOutboundUseCase: GetOutboundUseCase, private val processOutboundUseCase: ProcessOutboundUseCase, private val updateOutboundQuantityUseCase: UpdateOutboundQuantityUseCase, @@ -34,9 +36,11 @@ class OutboundListViewModel @Inject constructor( val uiState: StateFlow = _uiState private var errorLabel: String = "" + private var successLabel: String = "" - fun bindLabel(error: String) { + fun bindLabel(error: String, success: String) { errorLabel = error + successLabel = success } init { @@ -51,8 +55,6 @@ class OutboundListViewModel @Inject constructor( is OutboundListUiEvent.UpdateQuantity -> updateQuantity(event.outboundId, event.quantity) is OutboundListUiEvent.DeleteOutbound -> deleteOutbound(event.outboundId) is OutboundListUiEvent.DeleteAllOutbound -> deleteAllOutbound() - is OutboundListUiEvent.ClearUpdateError -> _uiState.update { it.copy(updateError = null) } - is OutboundListUiEvent.ClearDeleteError -> _uiState.update { it.copy(deleteError = null) } } } @@ -72,10 +74,13 @@ class OutboundListViewModel @Inject constructor( } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { it.copy( outboundLoading = false, - outboundError = backendMessage ?: (throwable.message ?: errorLabel) + outboundError = error ) } } @@ -85,20 +90,22 @@ class OutboundListViewModel @Inject constructor( private fun processOutBound() { viewModelScope.launch { - _uiState.update { it.copy(outboundLoading = true, outboundError = null) } + _uiState.update { it.copy(outboundLoading = true) } processOutboundUseCase() .onSuccess { + messageHandler.showMessage(message = successLabel, isError = true) + _uiState.update { it.copy(outboundLoading = false, isOrderSuccess = true) } loadOutboundList() } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { - it.copy( - outboundLoading = false, - outboundError = backendMessage ?: (throwable.message ?: errorLabel) - ) + it.copy(outboundLoading = false) } } Log.d(TAG, "submit: ${_uiState.value}") @@ -107,7 +114,7 @@ class OutboundListViewModel @Inject constructor( private fun updateQuantity(outboundId: Long, newQuantity: Long) { viewModelScope.launch { - _uiState.update { it.copy(isUpdating = true, updateError = null) } + _uiState.update { it.copy(isUpdating = true) } updateOutboundQuantityUseCase(outboundId, newQuantity) .onSuccess { @@ -116,11 +123,11 @@ class OutboundListViewModel @Inject constructor( } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { - it.copy( - isUpdating = false, - updateError = backendMessage ?: (throwable.message ?: errorLabel) - ) + it.copy(isUpdating = false) } } Log.d(TAG, "submit: ${_uiState.value}") @@ -150,7 +157,7 @@ class OutboundListViewModel @Inject constructor( private fun deleteOutbound(outboundId: Long) { viewModelScope.launch { - _uiState.update { it.copy(isDeleting = true, deleteError = null) } + _uiState.update { it.copy(isDeleting = true) } deleteOutboundUseCase(outboundId) .onSuccess { @@ -159,11 +166,11 @@ class OutboundListViewModel @Inject constructor( } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { - it.copy( - isDeleting = false, - deleteError = backendMessage ?: (throwable.message ?: errorLabel) - ) + it.copy(isDeleting = false) } } Log.d(TAG, "submit: ${_uiState.value}") @@ -172,7 +179,7 @@ class OutboundListViewModel @Inject constructor( private fun deleteAllOutbound() { viewModelScope.launch { - _uiState.update { it.copy(isDeleting = true, deleteError = null) } + _uiState.update { it.copy(isDeleting = true) } deleteAllOutboundUseCase() .onSuccess { @@ -181,11 +188,11 @@ class OutboundListViewModel @Inject constructor( } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { - it.copy( - isDeleting = false, - deleteError = backendMessage ?: (throwable.message ?: errorLabel) - ) + it.copy(isDeleting = false) } } Log.d(TAG, "submit: ${_uiState.value}") diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt b/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt index 617f12a..ba8d611 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt @@ -1,6 +1,6 @@ package com.sampoom.android.feature.part.data.remote.api -import com.sampoom.android.core.network.ApiResponse +import com.sampoom.android.core.model.ApiResponse import com.sampoom.android.feature.part.data.remote.dto.CategoryDto import com.sampoom.android.feature.part.data.remote.dto.GroupDto import com.sampoom.android.feature.part.data.remote.dto.PartDto diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt index 254419e..51e0a18 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt @@ -13,7 +13,6 @@ import com.sampoom.android.feature.part.domain.model.SearchResult import com.sampoom.android.feature.part.domain.repository.PartRepository import kotlinx.coroutines.flow.Flow import javax.inject.Inject -import kotlin.coroutines.cancellation.CancellationException class PartRepositoryImpl @Inject constructor( private val api: PartApi, @@ -24,8 +23,6 @@ class PartRepositoryImpl @Inject constructor( val dto = api.getCategoryList() val categoryItems = dto.data.map { it.toModel() } CategoryList(items = categoryItems) - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } @@ -34,8 +31,6 @@ class PartRepositoryImpl @Inject constructor( val response = api.getGroupList(categoryId) val groupItems = response.data.map { it.toModel() } GroupList(items = groupItems) - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } @@ -44,8 +39,6 @@ class PartRepositoryImpl @Inject constructor( val response = api.getPartList(groupId) val partItems = response.data.map { it.toModel() } PartList(items = partItems) - }.onFailure { exception -> - if (exception is CancellationException) throw exception } } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt index d9a2701..6ee3f3f 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt @@ -1,6 +1,5 @@ package com.sampoom.android.feature.part.ui -import android.widget.Toast import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -26,7 +25,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.KeyboardType @@ -49,17 +47,18 @@ fun PartDetailBottomSheet( viewModel: PartDetailViewModel = hiltViewModel() ) { val errorLabel = stringResource(R.string.common_error) + val addOutboundLabel = stringResource(R.string.outbound_toast_success) + val addCartLabel = stringResource(R.string.cart_toast_success) val uiState by viewModel.uiState.collectAsStateWithLifecycle() var showOutboundDialog by remember { mutableStateOf(false) } var showCartDialog by remember { mutableStateOf(false) } - val context = LocalContext.current LaunchedEffect(Unit) { - viewModel.clearSuccess() + viewModel.clearStatus() } - LaunchedEffect(errorLabel) { - viewModel.bindLabel(errorLabel) + LaunchedEffect(errorLabel, addOutboundLabel, addCartLabel) { + viewModel.bindLabel(errorLabel, addOutboundLabel, addCartLabel) } LaunchedEffect(part.partId) { @@ -69,24 +68,23 @@ fun PartDetailBottomSheet( // 성공 시 Toast 표시 후 다이얼로그 닫기 LaunchedEffect(uiState.isOutboundSuccess) { if (uiState.isOutboundSuccess) { - Toast.makeText(context, context.getString(R.string.outbound_toast_success), Toast.LENGTH_SHORT).show() - viewModel.clearSuccess() + viewModel.clearStatus() + onDismiss() } } // 성공 시 Toast 표시 후 다이얼로그 닫기 LaunchedEffect(uiState.isCartSuccess) { if (uiState.isCartSuccess) { - Toast.makeText(context, context.getString(R.string.cart_toast_success), Toast.LENGTH_SHORT).show() - viewModel.clearSuccess() + viewModel.clearStatus() + onDismiss() } } - // 실패 시 Toast 표시 LaunchedEffect(uiState.updateError) { - uiState.updateError?.let { error -> - Toast.makeText(context, error, Toast.LENGTH_LONG).show() - viewModel.onEvent(PartDetailUiEvent.ClearError) + if (uiState.updateError != null) { + viewModel.clearStatus() + onDismiss() } } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt index b9ea49a..f72614b 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailUiEvent.kt @@ -9,6 +9,5 @@ sealed interface PartDetailUiEvent { data class SetQuantity(val quantity: Long) : PartDetailUiEvent data class AddToOutbound(val partId: Long, val quantity: Long) : PartDetailUiEvent data class AddToCart(val partId: Long, val quantity: Long) : PartDetailUiEvent - object ClearError : PartDetailUiEvent object Dismiss : PartDetailUiEvent } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt index d0c0c5c..4213ca5 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailViewModel.kt @@ -4,6 +4,7 @@ import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.core.util.GlobalMessageHandler import com.sampoom.android.feature.cart.domain.usecase.AddCartUseCase import com.sampoom.android.feature.outbound.domain.usecase.AddOutboundUseCase import dagger.hilt.android.lifecycle.HiltViewModel @@ -15,6 +16,7 @@ import javax.inject.Inject @HiltViewModel class PartDetailViewModel @Inject constructor( + private val messageHandler: GlobalMessageHandler, private val addOutboundUseCase: AddOutboundUseCase, private val addCartUseCase: AddCartUseCase ) : ViewModel() { @@ -27,9 +29,13 @@ class PartDetailViewModel @Inject constructor( val uiState: StateFlow = _uiState private var errorLabel: String = "" + private var addOutboundLabel: String = "" + private var addCartLabel: String = "" - fun bindLabel(error: String) { + fun bindLabel(error: String, outbound: String, cart: String) { errorLabel = error + addOutboundLabel = outbound + addCartLabel = cart } fun onEvent(event: PartDetailUiEvent) { @@ -40,7 +46,6 @@ class PartDetailViewModel @Inject constructor( part = event.part, quantity = 1, isUpdating = false, - updateError = null, isOutboundSuccess = false, isCartSuccess = false ) @@ -73,13 +78,11 @@ class PartDetailViewModel @Inject constructor( addToCart(part.partId, quantity) } } - is PartDetailUiEvent.ClearError -> _uiState.update { it.copy(updateError = null) } is PartDetailUiEvent.Dismiss -> { _uiState.update { it.copy( part = null, - quantity = 1, - updateError = null + quantity = 1 ) } } @@ -92,15 +95,16 @@ class PartDetailViewModel @Inject constructor( addOutboundUseCase(partId, quantity) .onSuccess { + messageHandler.showMessage(message= addOutboundLabel, isError = false) _uiState.update { it.copy(isUpdating = false, isOutboundSuccess = true) } } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { - it.copy( - isUpdating = false, - updateError = backendMessage ?: (throwable.message ?: errorLabel) - ) + it.copy(isUpdating = false, updateError = error) } } Log.d(TAG, "submit: ${_uiState.value}") @@ -113,22 +117,23 @@ class PartDetailViewModel @Inject constructor( addCartUseCase(partId, quantity) .onSuccess { + messageHandler.showMessage(message= addCartLabel, isError = false) _uiState.update { it.copy(isUpdating = false, isCartSuccess = true) } } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { - it.copy( - isUpdating = false, - updateError = backendMessage ?: (throwable.message ?: errorLabel) - ) + it.copy(isUpdating = false, updateError = error) } } Log.d(TAG, "submit: ${_uiState.value}") } } - fun clearSuccess() { - _uiState.update { it.copy(isOutboundSuccess = false, isCartSuccess = false) } + fun clearStatus() { + _uiState.update { it.copy(isOutboundSuccess = false, isCartSuccess = false, updateError = null) } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt index be98d9e..c2b3b2c 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt @@ -32,6 +32,7 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -51,6 +52,7 @@ import com.sampoom.android.core.ui.theme.disableColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.part.domain.model.Part +import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -59,6 +61,7 @@ fun PartListScreen( navController: NavHostController = rememberNavController(), viewModel: PartListViewModel = hiltViewModel() ) { + val coroutineScope = rememberCoroutineScope() val groupName by navController.previousBackStackEntry?.savedStateHandle?.getStateFlow( "groupName", null @@ -74,8 +77,17 @@ fun PartListScreen( val pullRefreshState = rememberPullToRefreshState() // ModalBottomSheet 상태 관리 - val sheetState = rememberModalBottomSheetState() - var showBottomSheet by remember { mutableStateOf(false) } + val sheetState = rememberModalBottomSheetState(true) + val selectedPart = uiState.selectedPart + + // selectedPart가 변경되면 시트 표시/숨김 + LaunchedEffect(selectedPart) { + if (selectedPart != null && !sheetState.isVisible) { + sheetState.show() + } else if (selectedPart == null && sheetState.isVisible) { + sheetState.hide() + } + } PullToRefreshBox( isRefreshing = false, @@ -160,7 +172,6 @@ fun PartListScreen( part = part, onClick = { viewModel.onEvent(PartListUiEvent.ShowBottomSheet(part)) - showBottomSheet = true } ) } @@ -170,20 +181,24 @@ fun PartListScreen( } } - if (showBottomSheet) { + if (selectedPart != null) { uiState.selectedPart?.let { selectedPart -> ModalBottomSheet( onDismissRequest = { - showBottomSheet = false - viewModel.onEvent(PartListUiEvent.DismissBottomSheet) + coroutineScope.launch { + sheetState.hide() + viewModel.onEvent(PartListUiEvent.DismissBottomSheet) + } }, sheetState = sheetState ) { PartDetailBottomSheet( part = selectedPart, onDismiss = { - showBottomSheet = false - viewModel.onEvent(PartListUiEvent.DismissBottomSheet) + coroutineScope.launch { + sheetState.hide() + viewModel.onEvent(PartListUiEvent.DismissBottomSheet) + } } ) } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt index bd8e9b8..811fc25 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.core.util.GlobalMessageHandler import com.sampoom.android.feature.part.domain.usecase.GetPartUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CancellationException @@ -16,6 +17,7 @@ import javax.inject.Inject @HiltViewModel class PartListViewModel @Inject constructor( + private val messageHandler: GlobalMessageHandler, private val getPartListUseCase: GetPartUseCase, savedStateHandle: SavedStateHandle ) : ViewModel() { @@ -67,10 +69,13 @@ class PartListViewModel @Inject constructor( } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { it.copy( partListLoading = false, - partListError = backendMessage ?: (throwable.message ?: errorLabel) + partListError = error ) } } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index b1eb17b..7c10cf2 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -97,7 +97,16 @@ fun PartScreen( // ModalBottomSheet 상태 관리 val sheetState = rememberModalBottomSheetState() - var showBottomSheet by remember { mutableStateOf(false) } + val selectedPart = searchUiState.selectedPart + + // selectedPart가 변경되면 시트 표시/숨김 + LaunchedEffect(selectedPart) { + if (selectedPart != null && !sheetState.isVisible) { + sheetState.show() + } else if (selectedPart == null && sheetState.isVisible) { + sheetState.hide() + } + } Box( modifier = Modifier @@ -232,7 +241,6 @@ fun PartScreen( searchResults = searchResultsPaged, onPartClick = { part -> searchViewModel.onEvent(PartListUiEvent.ShowBottomSheet(part)) - showBottomSheet = true } ) } @@ -410,20 +418,24 @@ fun PartScreen( } } - if (showBottomSheet) { + if (selectedPart != null) { searchUiState.selectedPart?.let { selectedPart -> ModalBottomSheet( onDismissRequest = { - showBottomSheet = false - searchViewModel.onEvent(PartListUiEvent.DismissBottomSheet) + coroutineScope.launch { + sheetState.hide() + searchViewModel.onEvent(PartListUiEvent.DismissBottomSheet) + } }, sheetState = sheetState ) { PartDetailBottomSheet( part = selectedPart, onDismiss = { - showBottomSheet = false - searchViewModel.onEvent(PartListUiEvent.DismissBottomSheet) + coroutineScope.launch { + sheetState.hide() + searchViewModel.onEvent(PartListUiEvent.DismissBottomSheet) + } } ) } @@ -549,6 +561,7 @@ fun SearchResultsList( CircularProgressIndicator() } } + is LoadState.Error -> { Box( modifier = Modifier @@ -562,6 +575,7 @@ fun SearchResultsList( ) } } + else -> {} } } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt index 5ecfc99..7ecbd5e 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.viewModelScope import androidx.paging.PagingData import androidx.paging.cachedIn import com.sampoom.android.core.network.serverMessageOrNull +import com.sampoom.android.core.util.GlobalMessageHandler import com.sampoom.android.feature.part.domain.model.Category import com.sampoom.android.feature.part.domain.model.SearchResult import com.sampoom.android.feature.part.domain.usecase.GetCategoryUseCase @@ -29,6 +30,7 @@ import javax.inject.Inject @HiltViewModel class PartViewModel @Inject constructor( + private val messageHandler: GlobalMessageHandler, private val getCategoryUseCase: GetCategoryUseCase, private val getGroupUseCase: GetGroupUseCase, private val searchPartsUseCase: SearchPartsUseCase @@ -99,10 +101,13 @@ class PartViewModel @Inject constructor( } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { it.copy( categoryLoading = false, - categoryError = backendMessage ?: (throwable.message ?: errorLabel) + categoryError = error ) } } @@ -136,11 +141,14 @@ class PartViewModel @Inject constructor( } .onFailure { throwable -> val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) if (_uiState.value.selectedCategory?.id != categoryId) return@launch + _uiState.update { it.copy( groupLoading = false, - groupError = backendMessage ?: (throwable.message ?: errorLabel) + groupError = error ) } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6e6dc2a..9bf214b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -74,7 +74,7 @@ 출고목록 - 출고목록 비우기 + 비우기 출고목록이 없습니다. 출고 목록에 추가하시겠습니까? 출고 목록에 추가되었습니다 @@ -85,7 +85,7 @@ 장바구니 - 장바구니 비우기 + 비우기 장바구니 목록이 없습니다. 장바구니 목록에 추가하시겠습니까? 장바구니 목록에 추가되었습니다 From 954ff06abc70146cd53a9975a45574d9588f3278 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Sun, 2 Nov 2025 23:16:37 +0900 Subject: [PATCH 73/88] =?UTF-8?q?[FIX]=20=ED=99=94=EB=A9=B4=20UI=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/cart/ui/CartListViewModel.kt | 1 + .../android/feature/order/ui/OrderListScreen.kt | 13 ++++++++++++- .../feature/order/ui/OrderResultBottomSheet.kt | 7 +++++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt index 090a5b1..4c3878b 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListViewModel.kt @@ -95,6 +95,7 @@ class CartListViewModel @Inject constructor( createOrderUseCase(cartList) .onSuccess { order -> _uiState.update { it.copy(isProcessing = false, processedOrder = order) } + deleteAllCart() loadCartList() } .onFailure { throwable -> diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt index b2739a7..8a2636c 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt @@ -12,7 +12,6 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.foundation.lazy.items import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme @@ -21,14 +20,21 @@ import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults.Indicator import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleEventObserver +import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.paging.LoadState import androidx.paging.compose.collectAsLazyPagingItems @@ -58,6 +64,10 @@ fun OrderListScreen( viewModel.bindLabel(errorLabel) } + LaunchedEffect(Unit) { + orderListPaged.refresh() + } + PullToRefreshBox( isRefreshing = false, onRefresh = { orderListPaged.refresh() }, @@ -116,6 +126,7 @@ fun OrderListScreen( else -> { LazyColumn( + state = listState, modifier = Modifier .fillMaxSize() .padding(horizontal = 16.dp), diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt index 6269c33..556ce60 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt @@ -59,8 +59,11 @@ fun OrderResultBottomSheet( LaunchedEffect(order.orderId) { viewModel.setOrderIdFromApi(order.orderId) + viewModel.onEvent(OrderDetailUiEvent.LoadOrder) } + val displayedOrder = uiState.orderDetail ?: order + // 성공 시 Toast 표시 후 다이얼로그 닫기 LaunchedEffect(uiState.isProcessingCancelSuccess) { if (uiState.isProcessingCancelSuccess) { @@ -85,7 +88,7 @@ fun OrderResultBottomSheet( // OrderDetailContent 재사용 OrderDetailContent( - order = order, + order = displayedOrder, modifier = Modifier.weight(1f) ) @@ -97,7 +100,7 @@ fun OrderResultBottomSheet( .fillMaxWidth() .padding(16.dp) ) { - val orderStatus = order.status + val orderStatus = displayedOrder.status CommonButton( modifier = Modifier.weight(1f), variant = ButtonVariant.Error, From 39a4aec12790b180bd10dadc5f260a95ac9baf67 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Sun, 2 Nov 2025 23:20:03 +0900 Subject: [PATCH 74/88] =?UTF-8?q?[REFAC]=20=EB=B6=88=ED=95=84=EC=9A=94=20i?= =?UTF-8?q?mport=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/dashboard/ui/DashboardViewModel.kt | 2 +- .../sampoom/android/feature/order/ui/OrderListScreen.kt | 7 ------- .../android/feature/order/ui/OrderResultBottomSheet.kt | 1 - 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt index 0504236..768d537 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt @@ -5,10 +5,10 @@ import androidx.lifecycle.viewModelScope import androidx.paging.PagingData import androidx.paging.cachedIn import com.sampoom.android.core.util.GlobalMessageHandler -import com.sampoom.android.feature.order.domain.usecase.GetOrderUseCase import com.sampoom.android.feature.auth.domain.model.User import com.sampoom.android.feature.auth.domain.usecase.GetStoredUserUseCase import com.sampoom.android.feature.order.domain.model.Order +import com.sampoom.android.feature.order.domain.usecase.GetOrderUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt index 8a2636c..58d2cc7 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt @@ -20,21 +20,14 @@ import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults.Indicator import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.LifecycleEventObserver -import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.paging.LoadState import androidx.paging.compose.collectAsLazyPagingItems diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt index 556ce60..0f3a050 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderResultBottomSheet.kt @@ -1,6 +1,5 @@ package com.sampoom.android.feature.order.ui -import android.R.attr.onClick import android.widget.Toast import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column From c8df3912c515518722648dbd1be03e965744a959 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Sun, 2 Nov 2025 23:46:51 +0900 Subject: [PATCH 75/88] =?UTF-8?q?[FIX]=20=EC=97=90=EB=9F=AC=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95=20=EB=B0=8F?= =?UTF-8?q?=20import=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/sampoom/android/MainActivity.kt | 1 - .../com/sampoom/android/core/network/ErrorHandling.kt | 1 - .../com/sampoom/android/core/util/GlobalMessageHandler.kt | 8 ++++---- .../com/sampoom/android/feature/auth/ui/LoginViewModel.kt | 4 ++-- .../feature/order/domain/usecase/GetOrderUseCase.kt | 1 - .../android/feature/order/ui/OrderDetailViewModel.kt | 4 ++-- .../android/feature/outbound/ui/OutboundListViewModel.kt | 2 +- 7 files changed, 9 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/MainActivity.kt b/app/src/main/java/com/sampoom/android/MainActivity.kt index 8350fe5..fd1d58f 100644 --- a/app/src/main/java/com/sampoom/android/MainActivity.kt +++ b/app/src/main/java/com/sampoom/android/MainActivity.kt @@ -3,7 +3,6 @@ package com.sampoom.android import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.lifecycle.viewmodel.compose.viewModel import com.sampoom.android.app.navigation.AppNavHost import com.sampoom.android.core.ui.theme.SampoomManagementTheme import dagger.hilt.android.AndroidEntryPoint diff --git a/app/src/main/java/com/sampoom/android/core/network/ErrorHandling.kt b/app/src/main/java/com/sampoom/android/core/network/ErrorHandling.kt index 2dd7892..516ea2f 100644 --- a/app/src/main/java/com/sampoom/android/core/network/ErrorHandling.kt +++ b/app/src/main/java/com/sampoom/android/core/network/ErrorHandling.kt @@ -5,7 +5,6 @@ import com.google.gson.Gson import com.google.gson.JsonSyntaxException import com.sampoom.android.core.model.ApiErrorResponse import retrofit2.HttpException -import kotlin.jvm.java fun Throwable.serverMessageOrNull(): String? { if (this is HttpException) { diff --git a/app/src/main/java/com/sampoom/android/core/util/GlobalMessageHandler.kt b/app/src/main/java/com/sampoom/android/core/util/GlobalMessageHandler.kt index c8caa05..4533272 100644 --- a/app/src/main/java/com/sampoom/android/core/util/GlobalMessageHandler.kt +++ b/app/src/main/java/com/sampoom/android/core/util/GlobalMessageHandler.kt @@ -3,19 +3,19 @@ package com.sampoom.android.core.util import com.sampoom.android.core.model.SnackBarMessage import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow import javax.inject.Inject import javax.inject.Singleton @Singleton class GlobalMessageHandler @Inject constructor() { private val _message = MutableStateFlow(null) - val message: SharedFlow = _message.asSharedFlow() + val message: StateFlow = _message.asStateFlow() suspend fun showMessage(message: String, isError: Boolean = false) { _message.value = SnackBarMessage(message, isError) - delay(100) + delay(3000) _message.value = null } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt index a5d59fd..9e06634 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/LoginViewModel.kt @@ -83,7 +83,7 @@ class LoginViewModel @Inject constructor( if (!_uiState.value.isValid) return@launch val s = _uiState.value - _uiState.update { it.copy(loading = true) } + _uiState.update { it.copy(loading = true, success = false) } singIn(s.email, s.password) .onSuccess { _uiState.update { @@ -96,7 +96,7 @@ class LoginViewModel @Inject constructor( messageHandler.showMessage(message = error, isError = true) _uiState.update { - it.copy(loading = false) + it.copy(loading = false, success = false) } } Log.d(TAG, "submit: ${_uiState.value}") diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderUseCase.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderUseCase.kt index 9b8afa2..6df4370 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/GetOrderUseCase.kt @@ -2,7 +2,6 @@ package com.sampoom.android.feature.order.domain.usecase import androidx.paging.PagingData import com.sampoom.android.feature.order.domain.model.Order -import com.sampoom.android.feature.order.domain.model.OrderList import com.sampoom.android.feature.order.domain.repository.OrderRepository import kotlinx.coroutines.flow.Flow import javax.inject.Inject diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt index 58eaf64..309c28a 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt @@ -106,7 +106,7 @@ class OrderDetailViewModel @Inject constructor( cancelOrderUseCase(orderId) .onSuccess { - messageHandler.showMessage(message = cancelLabel, isError = true) + messageHandler.showMessage(message = cancelLabel, isError = false) _uiState.update { it.copy( isProcessing = false, @@ -133,7 +133,7 @@ class OrderDetailViewModel @Inject constructor( receiveOrderUseCase(orderId) .onSuccess { - messageHandler.showMessage(message = receiveLabel, isError = true) + messageHandler.showMessage(message = receiveLabel, isError = false) _uiState.update { it.copy( isProcessing = false, diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt index d6ac4ce..6eb5820 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListViewModel.kt @@ -94,7 +94,7 @@ class OutboundListViewModel @Inject constructor( processOutboundUseCase() .onSuccess { - messageHandler.showMessage(message = successLabel, isError = true) + messageHandler.showMessage(message = successLabel, isError = false) _uiState.update { it.copy(outboundLoading = false, isOrderSuccess = true) } loadOutboundList() From bf59b4813b57cc81655f06a4e408699e56a94ce2 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Tue, 4 Nov 2025 11:58:22 +0900 Subject: [PATCH 76/88] =?UTF-8?q?[FIX]=20=EB=A1=9C=EA=B7=B8=EC=9D=B8,=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20/=20=EC=84=A4=EC=A0=95=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sampoom/android/MainActivityViewModel.kt | 20 +- .../android/app/navigation/AppNavHost.kt | 42 ++- .../core/preferences/AuthPreferences.kt | 21 +- .../android/core/ui/component/StatusChip.kt | 11 +- .../feature/auth/data/mapper/AuthMappers.kt | 16 +- .../feature/auth/data/remote/api/AuthApi.kt | 3 +- .../data/remote/dto/GetProfileResponseDto.kt | 7 +- .../auth/data/remote/dto/LoginRequestDto.kt | 1 + .../auth/data/remote/dto/LoginResponseDto.kt | 2 - .../data/repository/AuthRepositoryImpl.kt | 61 ++-- .../android/feature/auth/domain/model/User.kt | 6 +- .../auth/domain/repository/AuthRepository.kt | 2 +- .../feature/cart/data/remote/api/CartApi.kt | 26 +- .../data/repository/CartRepositoryImpl.kt | 19 +- .../feature/dashboard/ui/DashboardScreen.kt | 29 +- .../order/data/paging/OrderPagingSource.kt | 2 +- .../feature/order/data/remote/api/OrderApi.kt | 14 +- .../data/repository/OrderRepositoryImpl.kt | 14 +- .../feature/order/domain/model/OrderStatus.kt | 7 +- .../domain/repository/OrderRepository.kt | 2 +- .../domain/usecase/CompleteOrderUseCase.kt | 10 + .../feature/order/ui/OrderDetailScreen.kt | 2 +- .../feature/order/ui/OrderDetailViewModel.kt | 37 ++- .../outbound/data/remote/api/OutboundApi.kt | 30 +- .../data/repository/OutboundRepositoryImpl.kt | 27 +- .../part/data/paging/PartPagingSource.kt | 5 +- .../feature/part/data/remote/api/PartApi.kt | 11 +- .../data/repository/PartRepositoryImpl.kt | 5 +- .../android/feature/part/ui/PartListScreen.kt | 1 - .../feature/setting/ui/SettingScreen.kt | 266 ++++++++++++++++++ .../feature/setting/ui/SettingUiEvent.kt | 7 + .../feature/setting/ui/SettingUiState.kt | 17 ++ .../feature/setting/ui/SettingViewModel.kt | 89 ++++++ app/src/main/res/values/strings.xml | 13 +- 34 files changed, 689 insertions(+), 136 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CompleteOrderUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/setting/ui/SettingUiEvent.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/setting/ui/SettingUiState.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/setting/ui/SettingViewModel.kt diff --git a/app/src/main/java/com/sampoom/android/MainActivityViewModel.kt b/app/src/main/java/com/sampoom/android/MainActivityViewModel.kt index e32eb23..798b771 100644 --- a/app/src/main/java/com/sampoom/android/MainActivityViewModel.kt +++ b/app/src/main/java/com/sampoom/android/MainActivityViewModel.kt @@ -1,11 +1,27 @@ package com.sampoom.android import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import com.sampoom.android.core.util.GlobalMessageHandler +import com.sampoom.android.feature.auth.domain.model.User +import com.sampoom.android.feature.auth.domain.usecase.GetStoredUserUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class MainActivityViewModel @Inject constructor( - val messageHandler: GlobalMessageHandler -) : ViewModel() \ No newline at end of file + val messageHandler: GlobalMessageHandler, + private val getStoredUserUseCase: GetStoredUserUseCase +) : ViewModel() { + private val _user = MutableStateFlow(null) + val user: StateFlow = _user + + init { + viewModelScope.launch { + _user.value = getStoredUserUseCase() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 344559c..aa802ce 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -31,6 +31,7 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.core.view.WindowInsetsControllerCompat import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavHostController import androidx.navigation.NavType import androidx.navigation.compose.NavHost @@ -48,6 +49,7 @@ import com.sampoom.android.core.ui.theme.Main500 import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.backgroundColor import com.sampoom.android.core.ui.theme.textColor +import com.sampoom.android.feature.auth.domain.model.User import com.sampoom.android.feature.auth.ui.AuthViewModel import com.sampoom.android.feature.auth.ui.LoginScreen import com.sampoom.android.feature.auth.ui.SignUpScreen @@ -58,6 +60,7 @@ import com.sampoom.android.feature.order.ui.OrderListScreen import com.sampoom.android.feature.outbound.ui.OutboundListScreen import com.sampoom.android.feature.part.ui.PartListScreen import com.sampoom.android.feature.part.ui.PartScreen +import com.sampoom.android.feature.setting.ui.SettingScreen import kotlinx.coroutines.flow.filterNotNull // Auth Screen @@ -100,6 +103,7 @@ fun AppNavHost( val authViewModel: AuthViewModel = hiltViewModel() val isLoggedIn by authViewModel.isLoggedIn.collectAsState() val isLoading by authViewModel.isLoading.collectAsState() + val user by viewModel.user.collectAsStateWithLifecycle() val navBackStackEntry by navController.currentBackStackEntryAsState() val currentRoute = navBackStackEntry?.destination?.route @@ -177,16 +181,15 @@ fun AppNavHost( } ) } - composable(ROUTE_HOME) { MainScreen(navController, authViewModel) } + composable(ROUTE_HOME) { MainScreen(navController, user) } composable(ROUTE_PARTS) { PartScreen( onNavigateBack = { navController.navigateUp() }, onNavigatePartList = { group -> - // TODO: 실제 사용자의 agencyId 사용 navController.currentBackStackEntry?.savedStateHandle?.set("groupName", group.name) - navController.navigate(routePartList(1, group.id)) + navController.navigate(routePartList(user?.agencyId ?: 0, group.id)) } ) } @@ -217,6 +220,22 @@ fun AppNavHost( } ) } + composable( + ROUTE_SETTINGS + ) { + SettingScreen( + onNavigateBack = { + navController.navigateUp() + }, + onLogoutClick = { + authViewModel.signOut() + navController.navigate(ROUTE_LOGIN) { + popUpTo(navController.graph.startDestinationId) { inclusive = true } + launchSingleTop = true + } + } + ) + } } TopSnackBarHost(hostState = snackBarHostState, isError = currentMessage?.isError ?: false) } @@ -224,7 +243,7 @@ fun AppNavHost( @Composable fun MainScreen( parentNavController: NavHostController, - authViewModel: AuthViewModel + user: User? ) { val navController = rememberNavController() @@ -239,8 +258,11 @@ fun MainScreen( composable(ROUTE_DASHBOARD) { DashboardScreen( paddingValues = innerPadding, + onSettingClick = { + parentNavController.navigate(ROUTE_SETTINGS) + }, onNavigateOrderDetail = { order -> - parentNavController.navigate(routeOrderDetail(1, order.orderId)) + parentNavController.navigate(routeOrderDetail(user?.agencyId ?: 0, order.orderId)) }, onNavigationOrder = { navController.navigate(ROUTE_ORDERS) { @@ -248,13 +270,6 @@ fun MainScreen( launchSingleTop = true restoreState = true } - }, - onLogoutClick = { - authViewModel.signOut() - parentNavController.navigate(ROUTE_LOGIN) { - popUpTo(parentNavController.graph.startDestinationId) { inclusive = true } - launchSingleTop = true - } } ) } @@ -272,8 +287,7 @@ fun MainScreen( OrderListScreen( paddingValues = innerPadding, onNavigateOrderDetail = { order -> - // TODO: 실제 사용자의 agencyId 사용 - parentNavController.navigate(routeOrderDetail(1, order.orderId)) + parentNavController.navigate(routeOrderDetail(user?.agencyId ?: 0, order.orderId)) } ) } diff --git a/app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt b/app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt index 8f7fb59..f14fb1d 100644 --- a/app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt +++ b/app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt @@ -11,6 +11,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton import kotlinx.coroutines.flow.first +import java.time.LocalDateTime // Per official guidance, DataStore instance should be single and at top-level. private val Context.authDataStore by preferencesDataStore(name = "auth_prefs") @@ -28,10 +29,14 @@ class AuthPreferences @Inject constructor( val TOKEN_EXPIRES_AT: Preferences.Key = longPreferencesKey("token_expires_at") val USER_ID: Preferences.Key = stringPreferencesKey("user_id") val USER_NAME: Preferences.Key = stringPreferencesKey("user_name") + val USER_EMAIL: Preferences.Key = stringPreferencesKey("user_email") val USER_ROLE: Preferences.Key = stringPreferencesKey("user_role") val USER_POSITION: Preferences.Key = stringPreferencesKey("user_position") val USER_WORKSPACE: Preferences.Key = stringPreferencesKey("user_workspace") val USER_BRANCH: Preferences.Key = stringPreferencesKey("user_branch") + val USER_AGENCY_ID: Preferences.Key = stringPreferencesKey("user_agency_id") + val USER_STARTED_AT: Preferences.Key = stringPreferencesKey("user_started_at") + val USER_ENDED_AT: Preferences.Key = stringPreferencesKey("user_ended_at") } suspend fun saveUser(user: User) { @@ -42,10 +47,14 @@ class AuthPreferences @Inject constructor( prefs[Keys.TOKEN_EXPIRES_AT] = expiresAt prefs[Keys.USER_ID] = cryptoManager.encrypt(user.userId.toString()) prefs[Keys.USER_NAME] = cryptoManager.encrypt(user.userName) + prefs[Keys.USER_EMAIL] = cryptoManager.encrypt(user.email) prefs[Keys.USER_ROLE] = cryptoManager.encrypt(user.role) prefs[Keys.USER_POSITION] = cryptoManager.encrypt(user.position) prefs[Keys.USER_WORKSPACE] = cryptoManager.encrypt(user.workspace) prefs[Keys.USER_BRANCH] = cryptoManager.encrypt(user.branch) + prefs[Keys.USER_AGENCY_ID] = cryptoManager.encrypt(user.agencyId.toString()) + prefs[Keys.USER_STARTED_AT] = cryptoManager.encrypt(user.startedAt.toString()) + prefs[Keys.USER_ENDED_AT] = cryptoManager.encrypt(user.endedAt.toString()) } } @@ -62,6 +71,7 @@ class AuthPreferences @Inject constructor( val prefs = dataStore.data.first() val userId = prefs[Keys.USER_ID] val userName = prefs[Keys.USER_NAME] + val userEmail = prefs[Keys.USER_EMAIL] val userRole = prefs[Keys.USER_ROLE] val accessToken = prefs[Keys.ACCESS_TOKEN] val refreshToken = prefs[Keys.REFRESH_TOKEN] @@ -69,9 +79,12 @@ class AuthPreferences @Inject constructor( val userPosition = prefs[Keys.USER_POSITION] val userWorkspace = prefs[Keys.USER_WORKSPACE] val userBranch = prefs[Keys.USER_BRANCH] + val userAgencyId = prefs[Keys.USER_AGENCY_ID] + val userStartedAt = prefs[Keys.USER_STARTED_AT] + val userEndedAt = prefs[Keys.USER_ENDED_AT] - if (userId != null && userName != null && userRole != null && - accessToken != null && refreshToken != null && userPosition != null && userWorkspace != null && userBranch != null + if (userId != null && userName != null && userEmail != null && userRole != null && + accessToken != null && refreshToken != null && userPosition != null && userWorkspace != null && userBranch != null && userAgencyId != null && userStartedAt != null && userEndedAt != null ) { try { val remaining = expiresAt?.let { @@ -81,6 +94,7 @@ class AuthPreferences @Inject constructor( return User( cryptoManager.decrypt(userId).toLong(), cryptoManager.decrypt(userName), + cryptoManager.decrypt(userEmail), cryptoManager.decrypt(userRole), cryptoManager.decrypt(accessToken), cryptoManager.decrypt(refreshToken), @@ -88,6 +102,9 @@ class AuthPreferences @Inject constructor( cryptoManager.decrypt(userPosition), cryptoManager.decrypt(userWorkspace), cryptoManager.decrypt(userBranch), + cryptoManager.decrypt(userAgencyId).toLong(), + cryptoManager.decrypt(userStartedAt), + cryptoManager.decrypt(userEndedAt), ) } catch (e: Exception) { return null diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/StatusChip.kt b/app/src/main/java/com/sampoom/android/core/ui/component/StatusChip.kt index 47f0272..3d7341d 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/StatusChip.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/StatusChip.kt @@ -18,9 +18,14 @@ import com.sampoom.android.feature.order.domain.model.OrderStatus @Composable fun StatusChip(status: OrderStatus) { val (text, color) = when (status) { - OrderStatus.PENDING -> stringResource(R.string.order_status_pending) to WaitYellow - OrderStatus.COMPLETED -> stringResource(R.string.order_status_completed) to SuccessGreen - OrderStatus.CANCELED -> stringResource(R.string.order_status_canceled) to FailRed + OrderStatus.PENDING -> stringResource(R.string.order_status_pending) to WaitYellow // 대기중 + OrderStatus.CONFIRMED -> stringResource(R.string.order_status_confirmed) to WaitYellow // 주문 확인 + OrderStatus.SHIPPING -> stringResource(R.string.order_status_shipping) to WaitYellow // 배송 중 + OrderStatus.DELAYED -> stringResource(R.string.order_status_delayed) to WaitYellow // 배송 지연 + OrderStatus.PRODUCING -> stringResource(R.string.order_status_producing) to WaitYellow // 생산 중 + OrderStatus.ARRIVED -> stringResource(R.string.order_status_arrived) to WaitYellow // 배송 완료 + OrderStatus.COMPLETED -> stringResource(R.string.order_status_completed) to SuccessGreen // 입고 완료 + OrderStatus.CANCELED -> stringResource(R.string.order_status_canceled) to FailRed // 주문 취소 } Surface( diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt index 73d6d4c..557ffee 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt @@ -7,25 +7,33 @@ import com.sampoom.android.feature.auth.domain.model.User fun LoginResponseDto.toModel(): User = User( userId = userId, userName = "", - role = role, + email = "", + role = "", accessToken = accessToken, refreshToken = refreshToken, expiresIn = expiresIn, position = "", workspace = "", - branch = "" + branch = "", + agencyId = 0, + startedAt = null, + endedAt = null ) fun GetProfileResponseDto.toModel(): User = User( userId = userId, userName = userName, - role = "", + email = email, + role = role, accessToken = "", refreshToken = "", expiresIn = 0L, position = position, workspace = workspace, - branch = branch + branch = branch, + agencyId = organizationId, + startedAt = startedAt, + endedAt = endedAt ) fun User.mergeWith(profile: User): User = this.copy( diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt index 233274a..7f70e50 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt @@ -16,6 +16,7 @@ import retrofit2.http.GET import retrofit2.http.Headers import retrofit2.http.PATCH import retrofit2.http.POST +import retrofit2.http.Query interface AuthApi { @POST("auth/signup") @@ -33,7 +34,7 @@ interface AuthApi { suspend fun login(@Body body: LoginRequestDto): ApiResponse @GET("user/profile") - suspend fun getProfile(): ApiResponse + suspend fun getProfile(@Query("workspace") workspace: String): ApiResponse @PATCH("user/profile") suspend fun updateProfile(@Body body: UpdateProfileRequestDto): ApiResponse diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/GetProfileResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/GetProfileResponseDto.kt index ff0c29b..aa46f7d 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/GetProfileResponseDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/GetProfileResponseDto.kt @@ -3,7 +3,12 @@ package com.sampoom.android.feature.auth.data.remote.dto data class GetProfileResponseDto( val userId: Long, val userName: String, + val email: String, + val role: String, + val position: String, val workspace: String, val branch: String, - val position: String + val organizationId: Long, + val startedAt: String, + val endedAt: String? ) diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginRequestDto.kt index 136b9ac..b52f270 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginRequestDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginRequestDto.kt @@ -1,6 +1,7 @@ package com.sampoom.android.feature.auth.data.remote.dto data class LoginRequestDto( + val workspace: String, val email: String, val password: String ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginResponseDto.kt index 8743a70..67a83d1 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginResponseDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/LoginResponseDto.kt @@ -2,8 +2,6 @@ package com.sampoom.android.feature.auth.data.remote.dto data class LoginResponseDto( val userId: Long, - val userName: String?, - val role: String, val accessToken: String, val refreshToken: String, val expiresIn: Long diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt index 747122d..d630d3f 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt @@ -10,6 +10,7 @@ import com.sampoom.android.feature.auth.data.remote.dto.SignUpRequestDto import com.sampoom.android.feature.auth.domain.model.User import com.sampoom.android.feature.auth.domain.repository.AuthRepository import javax.inject.Inject +import kotlin.math.log class AuthRepositoryImpl @Inject constructor( private val api: AuthApi, @@ -24,14 +25,16 @@ class AuthRepositoryImpl @Inject constructor( position: String ): Result { return runCatching { - val signUpRes = api.signUp(SignUpRequestDto( - email = email, - password = password, - workspace = workspace, - branch = branch, - userName = userName, - position = position - )) + val signUpRes = api.signUp( + SignUpRequestDto( + email = email, + password = password, + workspace = workspace, + branch = branch, + userName = userName, + position = position + ) + ) if (!signUpRes.success) throw Exception(signUpRes.message) signIn(email, password).getOrThrow() } @@ -42,34 +45,60 @@ class AuthRepositoryImpl @Inject constructor( password: String ): Result { return runCatching { - val loginDto = api.login(LoginRequestDto(email, password)) + val loginDto = api.login( + LoginRequestDto( + workspace = "AGENCY", + email = email, + password = password + ) + ) if (!loginDto.success) throw Exception(loginDto.message) val loginUser = loginDto.data.toModel() preferences.saveUser(loginUser) - val profileDto = getProfile() + val profileDto = getProfile("AGENCY") val profileUser = profileDto.getOrThrow() - val user = loginUser.mergeWith(profileUser) + val user = User( + userId = loginUser.userId, + userName = profileUser.userName, + email = profileUser.email, + role = profileUser.role, + accessToken = loginUser.accessToken, + refreshToken = loginUser.refreshToken, + expiresIn = loginUser.expiresIn, + position = profileUser.position, + workspace = profileUser.workspace, + branch = profileUser.branch, + agencyId = profileUser.agencyId, + startedAt = profileUser.startedAt, + endedAt = profileUser.endedAt + ) preferences.saveUser(user) user } } - override suspend fun signOut() : Result { + override suspend fun signOut(): Result { return runCatching { val dto = api.logout() if (!dto.success) throw Exception(dto.message) + }.onSuccess { + preferences.clear() + }.onFailure { + preferences.clear() } } override suspend fun refreshToken(): Result { return runCatching { - val refreshToken = preferences.getRefreshToken() ?: throw Exception("No refresh token available") + val refreshToken = + preferences.getRefreshToken() ?: throw Exception("No refresh token available") val response = api.refresh(RefreshRequestDto(refreshToken)) - val existingUser = preferences.getStoredUser() ?: throw Exception("No user information available") + val existingUser = + preferences.getStoredUser() ?: throw Exception("No user information available") val updatedUser = existingUser.copy( accessToken = response.data.accessToken, @@ -89,9 +118,9 @@ class AuthRepositoryImpl @Inject constructor( override suspend fun isSignedIn(): Boolean = preferences.hasToken() - override suspend fun getProfile(): Result { + override suspend fun getProfile(workspace: String): Result { return runCatching { - val dto = api.getProfile() + val dto = api.getProfile(workspace) if (!dto.success) throw Exception(dto.message) dto.data.toModel() } diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt index 266d05b..d4a4fb5 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt @@ -3,11 +3,15 @@ package com.sampoom.android.feature.auth.domain.model data class User( val userId: Long, val userName: String, + val email: String, val role: String, val accessToken: String, val refreshToken: String, val expiresIn: Long, val position: String, val workspace: String, - val branch: String + val branch: String, + val agencyId: Long, + val startedAt: String?, + val endedAt: String? ) diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt index a54529d..866028a 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt @@ -17,5 +17,5 @@ interface AuthRepository { suspend fun refreshToken(): Result suspend fun clearTokens(): Result suspend fun isSignedIn(): Boolean - suspend fun getProfile(): Result + suspend fun getProfile(workspace: String): Result } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt index 4e798e9..92dc7eb 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/api/CartApi.kt @@ -12,28 +12,34 @@ import retrofit2.http.POST import retrofit2.http.PUT import retrofit2.http.Path -// TODO: AgencyId 동적 주입 interface CartApi { // 장바구니 목록 조회 - @GET("agency/1/cart") - suspend fun getCartList(): ApiResponse> + @GET("agency/{agencyId}/cart") + suspend fun getCartList(@Path("agencyId") agencyId: Long): ApiResponse> // 장바구니에 부품 추가 - @POST("agency/1/cart") - suspend fun addCart(@Body body: AddCartRequestDto): ApiSuccessResponse + @POST("agency/{agencyId}/cart") + suspend fun addCart( + @Path("agencyId") agencyId: Long, + @Body body: AddCartRequestDto + ): ApiSuccessResponse // 장바구니 항목 삭제 - @DELETE("agency/1/cart/{cartItemId}") - suspend fun deleteCart(@Path("cartItemId") cartItemId: Long): ApiSuccessResponse + @DELETE("agency/{agencyId}/cart/{cartItemId}") + suspend fun deleteCart( + @Path("agencyId") agencyId: Long, + @Path("cartItemId") cartItemId: Long + ): ApiSuccessResponse // 장바구니 수량 변경 - @PUT("agency/1/cart/{cartItemId}") + @PUT("agency/{agencyId}/cart/{cartItemId}") suspend fun updateCart( + @Path("agencyId") agencyId: Long, @Path("cartItemId") cartItemId: Long, @Body body: UpdateCartRequestDto ): ApiSuccessResponse // 장바구니 전체 비우기 - @DELETE("agency/1/cart/clear") - suspend fun deleteAllCart(): ApiSuccessResponse + @DELETE("agency/{agencyId}/cart/clear") + suspend fun deleteAllCart(@Path("agencyId") agencyId: Long): ApiSuccessResponse } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt index 87cf54c..a8554d4 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/repository/CartRepositoryImpl.kt @@ -1,5 +1,6 @@ package com.sampoom.android.feature.cart.data.repository +import com.sampoom.android.core.preferences.AuthPreferences import com.sampoom.android.feature.cart.data.mapper.toModel import com.sampoom.android.feature.cart.data.remote.api.CartApi import com.sampoom.android.feature.cart.data.remote.dto.AddCartRequestDto @@ -9,11 +10,13 @@ import com.sampoom.android.feature.cart.domain.repository.CartRepository import javax.inject.Inject class CartRepositoryImpl @Inject constructor( - private val api: CartApi + private val api: CartApi, + private val authPreferences: AuthPreferences ) : CartRepository { override suspend fun getCartList(): Result { return runCatching { - val dto = api.getCartList() + val agencyId = authPreferences.getStoredUser()?.agencyId ?: throw Exception() + val dto = api.getCartList(agencyId) val cartItems = dto.data.map { it.toModel() } CartList(items = cartItems) } @@ -24,21 +27,24 @@ class CartRepositoryImpl @Inject constructor( quantity: Long ): Result { return runCatching { - val dto = api.addCart(AddCartRequestDto(partId, quantity)) + val agencyId = authPreferences.getStoredUser()?.agencyId ?: throw Exception() + val dto = api.addCart(agencyId = agencyId, body = AddCartRequestDto(partId, quantity)) if (!dto.success) throw Exception(dto.message) } } override suspend fun deleteCart(cartItemId: Long): Result { return runCatching { - val dto = api.deleteCart(cartItemId) + val agencyId = authPreferences.getStoredUser()?.agencyId ?: throw Exception() + val dto = api.deleteCart(agencyId = agencyId, cartItemId = cartItemId) if (!dto.success) throw Exception(dto.message) } } override suspend fun deleteAllCart(): Result { return runCatching { - val dto = api.deleteAllCart() + val agencyId = authPreferences.getStoredUser()?.agencyId ?: throw Exception() + val dto = api.deleteAllCart(agencyId) if (!dto.success) throw Exception(dto.message) } } @@ -48,7 +54,8 @@ class CartRepositoryImpl @Inject constructor( quantity: Long ): Result { return runCatching { - val dto = api.updateCart(cartItemId, UpdateCartRequestDto(quantity)) + val agencyId = authPreferences.getStoredUser()?.agencyId ?: throw Exception() + val dto = api.updateCart(agencyId = agencyId, cartItemId = cartItemId, body = UpdateCartRequestDto(quantity)) if (!dto.success) throw Exception(dto.message) } } diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt index 208de19..a67b26a 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt @@ -17,7 +17,6 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CornerSize import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Button import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.CircularProgressIndicator @@ -45,6 +44,7 @@ import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.paging.LoadState +import androidx.paging.compose.LazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems import com.sampoom.android.R import com.sampoom.android.core.ui.component.EmptyContent @@ -60,15 +60,16 @@ import com.sampoom.android.feature.order.domain.model.Order @Composable fun DashboardScreen( paddingValues: PaddingValues, + onSettingClick: () -> Unit, onNavigateOrderDetail: (Order) -> Unit, onNavigationOrder: () -> Unit, - onLogoutClick: () -> Unit, viewModel: DashboardViewModel = hiltViewModel() ) { val errorLabel = stringResource(R.string.common_error) val uiState by viewModel.uiState.collectAsStateWithLifecycle() val user by viewModel.user.collectAsStateWithLifecycle() val pullRefreshState = rememberPullToRefreshState() + val orderListPaged = viewModel.orderListPaged.collectAsLazyPagingItems() val isManager = user?.role == "ADMIN" LaunchedEffect(errorLabel) { @@ -77,7 +78,10 @@ fun DashboardScreen( PullToRefreshBox( isRefreshing = false, - onRefresh = { viewModel.onEvent(DashboardUiEvent.LoadDashboard) }, + onRefresh = { + viewModel.onEvent(DashboardUiEvent.LoadDashboard) + orderListPaged.refresh() + }, state = pullRefreshState, modifier = Modifier.fillMaxSize(), indicator = { @@ -123,7 +127,7 @@ fun DashboardScreen( } IconButton( - onClick = { } + onClick = { onSettingClick() } ) { Icon( painter = painterResource(R.drawable.settings), @@ -139,12 +143,6 @@ fun DashboardScreen( .padding(horizontal = 16.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { - item { - Button(onClick = { onLogoutClick() }) { - Text("로그아웃") - } - } - item { TitleSection(user) } item { ButtonSection(isManager) } @@ -152,7 +150,7 @@ fun DashboardScreen( item { OrderListSection( viewModel = viewModel, - uiState = uiState, + orderListPaged = orderListPaged, onNavigateOrderDetail = { order -> onNavigateOrderDetail(order) }, @@ -179,7 +177,7 @@ fun TitleSection( verticalArrangement = Arrangement.spacedBy(16.dp) ) { Text( - text = user?.branch ?: "", // TODO: Agency Id 받아오기 + text = user?.branch ?: "", style = MaterialTheme.typography.headlineMedium, fontWeight = FontWeight.Bold, color = textColor() @@ -190,7 +188,7 @@ fun TitleSection( pushStringAnnotation(tag = "NAME", annotation = "name") withStyle(style = SpanStyle(color = Main500)) { - append(user?.userName ?: "") // TODO : 이름 받아오기 + append(user?.userName ?: "") } append(stringResource(R.string.dashboard_title_hello_sir)) pop() @@ -338,11 +336,10 @@ fun ButtonCard( @Composable fun OrderListSection( viewModel: DashboardViewModel, - uiState: DashboardUiState, + orderListPaged: LazyPagingItems, onNavigateOrderDetail: (Order) -> Unit, onNavigationOrder: () -> Unit ) { - val orderListPaged = viewModel.orderListPaged.collectAsLazyPagingItems() Column( modifier = Modifier.fillMaxWidth() @@ -390,7 +387,7 @@ fun OrderListSection( contentAlignment = Alignment.Center ) { ErrorContent( - onRetry = { viewModel.onEvent(DashboardUiEvent.RetryDashboard) }, + onRetry = { orderListPaged.refresh() }, modifier = Modifier.height(200.dp) ) } diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/paging/OrderPagingSource.kt b/app/src/main/java/com/sampoom/android/feature/order/data/paging/OrderPagingSource.kt index d631e83..e7e52fe 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/paging/OrderPagingSource.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/paging/OrderPagingSource.kt @@ -28,7 +28,7 @@ class OrderPagingSource @AssistedInject constructor( override suspend fun load(params: LoadParams): LoadResult { return try { - val agencyName = authPreferences.getStoredUser()?.branch ?: "" + val agencyName = authPreferences.getStoredUser()?.branch ?: throw Exception() val page = params.key ?: 0 val pageSize = params.loadSize val response = api.getOrderList(agencyName, page, pageSize) diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt b/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt index 11496b1..7b77436 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt @@ -12,7 +12,6 @@ import retrofit2.http.POST import retrofit2.http.Path import retrofit2.http.Query -// TODO: AgencyId 동적 주입 interface OrderApi { // 주문 목록 조회 @GET("order/requested") @@ -26,9 +25,16 @@ interface OrderApi { @POST("order/") suspend fun createOrder(@Body orderRequestDto: OrderRequestDto): ApiResponse - // 주문 입고 처리 - @PATCH("agency/1/orders/{orderId}/receive") - suspend fun receiveOrder(@Path("orderId") orderId: Long): ApiSuccessResponse + // 주문 완료 처리 + @PATCH("order/complete/{orderId}") + suspend fun completeOrder(@Path("orderId") orderId: Long): ApiSuccessResponse + + // 주문 입고 처리 (대리점) + @PATCH("agency/{agencyId}/orders/{orderId}/receive") + suspend fun receiveOrder( + @Path("agencyId") agencyId: Long, + @Path("orderId") orderId: Long + ): ApiSuccessResponse // 주문 상세 조회 @GET("order/{orderId}") diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt index 9f07890..4d10f48 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt @@ -19,7 +19,7 @@ import javax.inject.Inject class OrderRepositoryImpl @Inject constructor( private val api: OrderApi, - private val preferences: AuthPreferences, + private val authPreferences: AuthPreferences, private val pagingSourceFactory: OrderPagingSource.Factory ) : OrderRepository { override fun getOrderList(): Flow> { @@ -31,7 +31,7 @@ class OrderRepositoryImpl @Inject constructor( override suspend fun createOrder(cartList: CartList): Result { return runCatching { - val agencyName = preferences.getStoredUser()?.branch ?: throw Exception() + val agencyName = authPreferences.getStoredUser()?.branch ?: throw Exception() val items = cartList.items.map { cart -> OrderCategoryDto( categoryId = cart.categoryId, @@ -64,9 +64,17 @@ class OrderRepositoryImpl @Inject constructor( } } + override suspend fun completeOrder(orderId: Long): Result { + return runCatching { + val dto = api.completeOrder(orderId) + if (!dto.success) throw Exception(dto.message) + } + } + override suspend fun receiveOrder(orderId: Long): Result { return runCatching { - val dto = api.receiveOrder(orderId) + val agencyId = authPreferences.getStoredUser()?.agencyId ?: throw Exception() + val dto = api.receiveOrder(agencyId = agencyId, orderId = orderId) if (!dto.success) throw Exception(dto.message) } } diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/model/OrderStatus.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/model/OrderStatus.kt index 211339b..2eb62ea 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/model/OrderStatus.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/model/OrderStatus.kt @@ -3,11 +3,16 @@ package com.sampoom.android.feature.order.domain.model import java.util.Locale enum class OrderStatus { - PENDING, COMPLETED, CANCELED; + PENDING, CONFIRMED, SHIPPING, DELAYED, PRODUCING, ARRIVED, COMPLETED, CANCELED; companion object { fun from(raw: String?): OrderStatus = when (raw?.uppercase(Locale.ROOT)) { "PENDING" -> PENDING + "CONFIRMED" -> CONFIRMED + "SHIPPING" -> SHIPPING + "DELAYED" -> DELAYED + "PRODUCING" -> PRODUCING + "ARRIVED" -> ARRIVED "COMPLETED" -> COMPLETED "CANCELED" -> CANCELED else -> PENDING diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt index edf9adf..f103d37 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt @@ -3,13 +3,13 @@ package com.sampoom.android.feature.order.domain.repository import androidx.paging.PagingData import com.sampoom.android.feature.cart.domain.model.CartList import com.sampoom.android.feature.order.domain.model.Order -import com.sampoom.android.feature.order.domain.model.OrderList import kotlinx.coroutines.flow.Flow interface OrderRepository { // suspend fun getOrderList(): Result fun getOrderList(): Flow> suspend fun createOrder(cartList: CartList): Result + suspend fun completeOrder(orderId: Long): Result suspend fun receiveOrder(orderId: Long): Result suspend fun getOrderDetail(orderId: Long): Result suspend fun cancelOrder(orderId: Long): Result diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CompleteOrderUseCase.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CompleteOrderUseCase.kt new file mode 100644 index 0000000..d433c14 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/CompleteOrderUseCase.kt @@ -0,0 +1,10 @@ +package com.sampoom.android.feature.order.domain.usecase + +import com.sampoom.android.feature.order.domain.repository.OrderRepository +import javax.inject.Inject + +class CompleteOrderUseCase @Inject constructor( + private val repository: OrderRepository +) { + suspend operator fun invoke(orderId: Long): Result = repository.completeOrder(orderId) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt index e5aba2d..8c64f2d 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt @@ -127,7 +127,7 @@ fun OrderDetailScreen( modifier = Modifier.weight(1f), enabled = orderStatus != null && !uiState.isProcessing && - orderStatus == OrderStatus.PENDING, + orderStatus == OrderStatus.ARRIVED, onClick = { showReceiveOrderDialog = true } ) { Text(stringResource(R.string.order_detail_order_receive)) diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt index 309c28a..d7122ea 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.viewModelScope import com.sampoom.android.core.network.serverMessageOrNull import com.sampoom.android.core.util.GlobalMessageHandler import com.sampoom.android.feature.order.domain.usecase.CancelOrderUseCase +import com.sampoom.android.feature.order.domain.usecase.CompleteOrderUseCase import com.sampoom.android.feature.order.domain.usecase.GetOrderDetailUseCase import com.sampoom.android.feature.order.domain.usecase.ReceiveOrderUseCase import dagger.hilt.android.lifecycle.HiltViewModel @@ -21,6 +22,7 @@ class OrderDetailViewModel @Inject constructor( private val messageHandler: GlobalMessageHandler, private val getOrderDetailUseCase: GetOrderDetailUseCase, private val cancelOrderUseCase: CancelOrderUseCase, + private val completeOrderUseCase: CompleteOrderUseCase, private val receiveOrderUseCase: ReceiveOrderUseCase, savedStateHandle: SavedStateHandle ) : ViewModel() { @@ -130,26 +132,23 @@ class OrderDetailViewModel @Inject constructor( private fun receiveOrder(orderId: Long) { viewModelScope.launch { _uiState.update { it.copy(isProcessing = true) } - - receiveOrderUseCase(orderId) - .onSuccess { - messageHandler.showMessage(message = receiveLabel, isError = false) - _uiState.update { - it.copy( - isProcessing = false, - isProcessingReceiveSuccess = true - ) - } - } - .onFailure { throwable -> - val backendMessage = throwable.serverMessageOrNull() - val error = backendMessage ?: (throwable.message ?: errorLabel) - messageHandler.showMessage(message = error, isError = true) - - _uiState.update { - it.copy(isProcessing = false) - } + try { + receiveOrderUseCase(orderId).getOrThrow() // 1단계 + completeOrderUseCase(orderId).getOrThrow() // 2단계 + + messageHandler.showMessage(message = receiveLabel, isError = false) + _uiState.update { + it.copy( + isProcessing = false, + isProcessingReceiveSuccess = true + ) } + } catch (t: Throwable) { + val backendMessage = t.serverMessageOrNull() + val error = backendMessage ?: (t.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { it.copy(isProcessing = false) } + } Log.d(TAG, "submit: ${_uiState.value}") } } diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt index c4f198a..b4209ec 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/api/OutboundApi.kt @@ -12,32 +12,38 @@ import retrofit2.http.PATCH import retrofit2.http.POST import retrofit2.http.Path -// TODO: AgencyId 동적 주입 interface OutboundApi { // 출고 목록 조회 - @GET("agency/1/outbound") - suspend fun getOutboundList(): ApiResponse> + @GET("agency/{agencyId}/outbound") + suspend fun getOutboundList(@Path("agencyId") agencyId: Long): ApiResponse> // 출고 목록에 부품 추가 - @POST("agency/1/outbound") - suspend fun addOutbound(@Body body: AddOutboundRequestDto): ApiSuccessResponse + @POST("agency/{agencyId}/outbound") + suspend fun addOutbound( + @Path("agencyId") agencyId: Long, + @Body body: AddOutboundRequestDto + ): ApiSuccessResponse // 출고 처리 - @POST("agency/1/outbound/process") - suspend fun processOutbound(): ApiSuccessResponse + @POST("agency/{agencyId}/outbound/process") + suspend fun processOutbound(@Path("agencyId") agencyId: Long): ApiSuccessResponse // 출고 항목 삭제 - @DELETE("agency/1/outbound/{outboundId}") - suspend fun deleteOutbound(@Path("outboundId") outboundId: Long): ApiSuccessResponse + @DELETE("agency/{agencyId}/outbound/{outboundId}") + suspend fun deleteOutbound( + @Path("agencyId") agencyId: Long, + @Path("outboundId") outboundId: Long + ): ApiSuccessResponse // 출고 수량 변경 - @PATCH("agency/1/outbound/{outboundId}") + @PATCH("agency/{agencyId}/outbound/{outboundId}") suspend fun updateOutbound( + @Path("agencyId") agencyId: Long, @Path("outboundId") outboundId: Long, @Body body: UpdateOutboundRequestDto ): ApiSuccessResponse // 출고 목록 전체 비우기 - @DELETE("agency/1/outbound/clear") - suspend fun deleteAllOutbound(): ApiSuccessResponse + @DELETE("agency/{agencyId}/outbound/clear") + suspend fun deleteAllOutbound(@Path("agencyId") agencyId: Long): ApiSuccessResponse } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt index fb9658f..bb3fe7b 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/repository/OutboundRepositoryImpl.kt @@ -1,5 +1,6 @@ package com.sampoom.android.feature.outbound.data.repository +import com.sampoom.android.core.preferences.AuthPreferences import com.sampoom.android.feature.outbound.data.mapper.toModel import com.sampoom.android.feature.outbound.data.remote.api.OutboundApi import com.sampoom.android.feature.outbound.data.remote.dto.AddOutboundRequestDto @@ -9,11 +10,13 @@ import com.sampoom.android.feature.outbound.domain.repository.OutboundRepository import jakarta.inject.Inject class OutboundRepositoryImpl @Inject constructor( - private val api: OutboundApi + private val api: OutboundApi, + private val authPreferences: AuthPreferences ) : OutboundRepository { override suspend fun getOutboundList(): Result { return runCatching { - val dto = api.getOutboundList() + val agencyId = authPreferences.getStoredUser()?.agencyId ?: throw Exception() + val dto = api.getOutboundList(agencyId) val outboundItems = dto.data.map { it.toModel() } OutboundList(items = outboundItems) } @@ -21,7 +24,8 @@ class OutboundRepositoryImpl @Inject constructor( override suspend fun processOutbound(): Result { return runCatching { - val dto = api.processOutbound() + val agencyId = authPreferences.getStoredUser()?.agencyId ?: throw Exception() + val dto = api.processOutbound(agencyId) if (!dto.success) throw Exception(dto.message) } } @@ -31,21 +35,25 @@ class OutboundRepositoryImpl @Inject constructor( quantity: Long ): Result { return runCatching { - val dto = api.addOutbound(AddOutboundRequestDto(partId, quantity)) + val agencyId = authPreferences.getStoredUser()?.agencyId ?: throw Exception() + val dto = + api.addOutbound(agencyId = agencyId, body = AddOutboundRequestDto(partId, quantity)) if (!dto.success) throw Exception(dto.message) } } override suspend fun deleteOutbound(outboundId: Long): Result { return runCatching { - val dto = api.deleteOutbound(outboundId) + val agencyId = authPreferences.getStoredUser()?.agencyId ?: throw Exception() + val dto = api.deleteOutbound(agencyId = agencyId, outboundId = outboundId) if (!dto.success) throw Exception(dto.message) } } override suspend fun deleteAllOutbound(): Result { return runCatching { - val dto = api.deleteAllOutbound() + val agencyId = authPreferences.getStoredUser()?.agencyId ?: throw Exception() + val dto = api.deleteAllOutbound(agencyId) if (!dto.success) throw Exception(dto.message) } } @@ -55,7 +63,12 @@ class OutboundRepositoryImpl @Inject constructor( quantity: Long ): Result { return runCatching { - val dto = api.updateOutbound(outboundId, UpdateOutboundRequestDto(quantity)) + val agencyId = authPreferences.getStoredUser()?.agencyId ?: throw Exception() + val dto = api.updateOutbound( + agencyId = agencyId, + outboundId = outboundId, + body = UpdateOutboundRequestDto(quantity) + ) if (!dto.success) throw Exception(dto.message) } } diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/paging/PartPagingSource.kt b/app/src/main/java/com/sampoom/android/feature/part/data/paging/PartPagingSource.kt index 1509218..3d1c448 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/paging/PartPagingSource.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/paging/PartPagingSource.kt @@ -2,6 +2,7 @@ package com.sampoom.android.feature.part.data.paging import androidx.paging.PagingSource import androidx.paging.PagingState +import com.sampoom.android.core.preferences.AuthPreferences import com.sampoom.android.feature.part.data.mapper.toModel import com.sampoom.android.feature.part.data.remote.api.PartApi import com.sampoom.android.feature.part.domain.model.SearchResult @@ -11,6 +12,7 @@ import dagger.assisted.AssistedInject class PartPagingSource @AssistedInject constructor( private val api: PartApi, + private val authPreferences: AuthPreferences, @Assisted private val keyword: String ) : PagingSource() { @@ -29,7 +31,8 @@ class PartPagingSource @AssistedInject constructor( override suspend fun load(params: LoadParams): LoadResult { return try { val page = params.key ?: 0 - val response = api.searchParts(keyword, page, 20) + val agencyId = authPreferences.getStoredUser()?.agencyId ?: throw Exception() + val response = api.searchParts(agencyId, keyword, page, 20) val flatParts = response.data.toModel() diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt b/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt index ba8d611..ac7c808 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/remote/api/PartApi.kt @@ -9,7 +9,6 @@ import retrofit2.http.GET import retrofit2.http.Path import retrofit2.http.Query -// TODO: AgencyId 동적 주입 interface PartApi { @GET("agency/category") suspend fun getCategoryList(): ApiResponse> @@ -17,11 +16,15 @@ interface PartApi { @GET("agency/category/{categoryId}") suspend fun getGroupList(@Path("categoryId") categoryId: Long): ApiResponse> - @GET("agency/1/group/{groupId}") - suspend fun getPartList(@Path("groupId") groupId: Long): ApiResponse> + @GET("agency/{agencyId}/group/{groupId}") + suspend fun getPartList( + @Path("agencyId") agencyId: Long, + @Path("groupId") groupId: Long + ): ApiResponse> - @GET("agency/1/search") + @GET("agency/{agencyId}/search") suspend fun searchParts( + @Path("agencyId") agencyId: Long, @Query("keyword") keyword: String, @Query("page") page: Int = 0, @Query("size") size: Int = 20 diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt index 51e0a18..c9b45e1 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/repository/PartRepositoryImpl.kt @@ -3,6 +3,7 @@ package com.sampoom.android.feature.part.data.repository import androidx.paging.Pager import androidx.paging.PagingConfig import androidx.paging.PagingData +import com.sampoom.android.core.preferences.AuthPreferences import com.sampoom.android.feature.part.data.mapper.toModel import com.sampoom.android.feature.part.data.paging.PartPagingSource import com.sampoom.android.feature.part.data.remote.api.PartApi @@ -16,6 +17,7 @@ import javax.inject.Inject class PartRepositoryImpl @Inject constructor( private val api: PartApi, + private val authPreferences: AuthPreferences, private val pagingSourceFactory: PartPagingSource.Factory ) : PartRepository { override suspend fun getCategoryList(): Result { @@ -36,7 +38,8 @@ class PartRepositoryImpl @Inject constructor( override suspend fun getPartList(groupId: Long): Result { return runCatching { - val response = api.getPartList(groupId) + val agencyId = authPreferences.getStoredUser()?.agencyId ?: throw Exception() + val response = api.getPartList(agencyId = agencyId, groupId = groupId) val partItems = response.data.map { it.toModel() } PartList(items = partItems) } diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt index c2b3b2c..2d16093 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt @@ -33,7 +33,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource diff --git a/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt new file mode 100644 index 0000000..001cb02 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt @@ -0,0 +1,266 @@ +package com.sampoom.android.feature.setting.ui + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.pulltorefresh.PullToRefreshBox +import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults.Indicator +import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.sampoom.android.R +import com.sampoom.android.core.ui.theme.backgroundCardColor +import com.sampoom.android.core.ui.theme.disableColor +import com.sampoom.android.core.ui.theme.textColor +import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.core.util.formatDate +import com.sampoom.android.feature.auth.domain.model.User + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SettingScreen( + viewModel: SettingViewModel = hiltViewModel(), + onNavigateBack: () -> Unit = {}, + onLogoutClick: () -> Unit = {} +) { + val errorLabel = stringResource(R.string.common_error) + val nameLabel = stringResource(R.string.signup_title_name) + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + val user by viewModel.user.collectAsStateWithLifecycle() + val pullRefreshState = rememberPullToRefreshState() + var showLogoutDialog by remember { mutableStateOf(false) } + + LaunchedEffect(errorLabel, nameLabel) { + viewModel.bindLabel(errorLabel, nameLabel) + } + + LaunchedEffect(uiState.profileChangeSuccess) { + if (uiState.profileChangeSuccess) { + viewModel.clearSuccess() + viewModel.onEvent(SettingUiEvent.LoadProfile) + } + } + + LaunchedEffect(uiState.logoutSuccess) { + if (uiState.logoutSuccess) { + viewModel.clearSuccess() + onLogoutClick() + } + } + + PullToRefreshBox( + isRefreshing = false, + onRefresh = { viewModel.onEvent(SettingUiEvent.LoadProfile) }, + state = pullRefreshState, + modifier = Modifier.fillMaxSize(), + indicator = { + Indicator( + modifier = Modifier.align(Alignment.TopCenter), + isRefreshing = uiState.loading, + containerColor = MaterialTheme.colorScheme.primaryContainer, + color = MaterialTheme.colorScheme.onPrimaryContainer, + state = pullRefreshState + ) + } + ) { + Scaffold( + topBar = { + TopAppBar( + title = { Text(stringResource(R.string.setting_title)) }, + navigationIcon = { + IconButton(onClick = onNavigateBack) { + Icon( + painter = painterResource(R.drawable.ic_arrow_back), + contentDescription = stringResource(R.string.nav_back) + ) + } + } + ) + } + ) { innerPadding -> + LazyColumn( + Modifier + .fillMaxSize() + .padding(innerPadding) + .padding(horizontal = 16.dp) + ) { + item { + UserSection( + user = user, + modifier = Modifier + ) + } + item { + SettingSection( + onEditProfileClick = { }, + onLogoutClick = { showLogoutDialog = true } + ) + } + } + } + } + + if (showLogoutDialog) { + AlertDialog( + onDismissRequest = { showLogoutDialog = false }, + text = { Text(stringResource(R.string.setting_dialog_logout)) }, + confirmButton = { + TextButton( + onClick = { + showLogoutDialog = false + onLogoutClick() + } + ) { + Text(stringResource(R.string.common_confirm)) + } + }, + dismissButton = { + TextButton( + onClick = { showLogoutDialog = false } + ) { + Text(stringResource(R.string.common_cancel)) + } + } + ) + } +} + +@Composable +fun UserSection( + user: User?, + modifier: Modifier = Modifier +) { + Row( + modifier = modifier + .fillMaxWidth() + .padding(vertical = 16.dp) + ) { + Column( + modifier = Modifier.weight(1f), + horizontalAlignment = Alignment.Start + ) { + Text( + text = user?.userName.toString(), + style = MaterialTheme.typography.headlineLarge, + color = textColor() + ) + Text( + text = user?.position.toString(), + style = MaterialTheme.typography.bodyMedium, + color = textSecondaryColor() + ) + } + Column( + modifier = Modifier.weight(1f), + horizontalAlignment = Alignment.End + ) { + Text( + text = user?.email.toString(), + style = MaterialTheme.typography.bodyMedium, + color = textSecondaryColor() + ) + if (!user?.startedAt.isNullOrEmpty()) { + Text( + text = formatDate(user.startedAt), + style = MaterialTheme.typography.bodyMedium, + color = textSecondaryColor() + ) + } + if (!user?.endedAt.isNullOrEmpty()) { + Text( + text = formatDate(user.endedAt), + style = MaterialTheme.typography.bodyMedium, + color = textSecondaryColor() + ) + } + } + } +} + +@Composable +private fun SettingSection( + onEditProfileClick: () -> Unit, + onLogoutClick: () -> Unit +) { + Card( + onClick = { onEditProfileClick() }, + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors(containerColor = backgroundCardColor()), + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = stringResource(R.string.setting_edit_profile), + style = MaterialTheme.typography.titleMedium, + color = textColor() + ) + + Icon( + painterResource(R.drawable.chevron_right), + contentDescription = stringResource(R.string.common_detail), + tint = disableColor() + ) + } + } + + Spacer(Modifier.height(8.dp)) + + Card( + onClick = { onLogoutClick() }, + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors(containerColor = backgroundCardColor()), + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = stringResource(R.string.setting_logout), + style = MaterialTheme.typography.titleMedium, + color = textColor() + ) + + Icon( + painterResource(R.drawable.chevron_right), + contentDescription = stringResource(R.string.common_detail), + tint = disableColor() + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingUiEvent.kt new file mode 100644 index 0000000..4845ecd --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingUiEvent.kt @@ -0,0 +1,7 @@ +package com.sampoom.android.feature.setting.ui + +sealed interface SettingUiEvent { + object LoadProfile : SettingUiEvent + data class NameChanged(val userName: String) : SettingUiEvent + object EditProfile : SettingUiEvent +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingUiState.kt b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingUiState.kt new file mode 100644 index 0000000..caad258 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingUiState.kt @@ -0,0 +1,17 @@ +package com.sampoom.android.feature.setting.ui + +import com.sampoom.android.feature.auth.domain.model.User + +data class SettingUiState( + val profile: User? = null, + val userName: String = "", + val userNameError: String? = null, + + val loading: Boolean = false, + val error: Boolean = false, + val profileChangeSuccess: Boolean = false, + val logoutSuccess: Boolean = false +) { + val isValid: Boolean + get() = userName.isNotBlank() && userNameError == null +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingViewModel.kt b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingViewModel.kt new file mode 100644 index 0000000..2cab7bc --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingViewModel.kt @@ -0,0 +1,89 @@ +package com.sampoom.android.feature.setting.ui + +import android.app.Application +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.sampoom.android.core.util.GlobalMessageHandler +import com.sampoom.android.feature.auth.domain.AuthValidator +import com.sampoom.android.feature.auth.domain.ValidationResult +import com.sampoom.android.feature.auth.domain.model.User +import com.sampoom.android.feature.auth.domain.usecase.GetStoredUserUseCase +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class SettingViewModel @Inject constructor( + private val messageHandler: GlobalMessageHandler, + private val application: Application, + private val getStoredUserUseCase: GetStoredUserUseCase +) : ViewModel() { + + private companion object { + private const val TAG = "SettingViewModel" + } + + private val _uiState = MutableStateFlow(SettingUiState()) + val uiState: StateFlow = _uiState + + private val _user = MutableStateFlow(null) + val user: StateFlow = _user + + private var nameLabel: String = "" + private var errorLabel: String = "" + + fun bindLabel(name: String, error: String) { + nameLabel = name + errorLabel = error + } + + init { + viewModelScope.launch { + _user.value = getStoredUserUseCase() + } + } + + fun onEvent(event: SettingUiEvent) { + when (event) { + is SettingUiEvent.LoadProfile -> {} + is SettingUiEvent.NameChanged -> { + _uiState.value = _uiState.value.copy(userName = event.userName) + validateName() + } + is SettingUiEvent.EditProfile -> editProfile() + } + } + + private fun validateName() { + val result = AuthValidator.validateNotEmpty(_uiState.value.userName, nameLabel) + _uiState.value = _uiState.value.copy( + userNameError = result.toErrorMessage() + ) + } + + private fun ValidationResult.toErrorMessage(): String? { + return when (this) { + is ValidationResult.Error -> application.getString(messageResId) + is ValidationResult.ErrorWithArgs -> application.getString(messageResId, args) + ValidationResult.Success -> null + } + } + + private fun editProfile() = viewModelScope.launch { + validateName() + + if (!_uiState.value.isValid) return@launch + + val s = _uiState.value + _uiState.update { it.copy(loading = true) } + + // TODO : Edit Profile 연동 + } + + fun clearSuccess() { + _uiState.update { it.copy(profileChangeSuccess = false, logoutSuccess = false) } + } +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9bf214b..1bf8cf7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -111,10 +111,21 @@ 입고 처리되었습니다 - 승인대기 + 대기중 + 주문확인 + 배송중 + 배송지연 + 생산중 + 배송완료 입고완료 주문취소 + + 설정 + 프로필 수정 + 로그아웃 + 로그아웃 하시겠습니까? + 오류가 발생했습니다 다시 시도 From 25afeeafbaacb43f4291a17a0e6da44afcf37fd8 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Tue, 4 Nov 2025 14:42:00 +0900 Subject: [PATCH 77/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/sampoom/android/app/navigation/AppNavHost.kt | 9 ++++++--- .../sampoom/android/feature/setting/ui/SettingScreen.kt | 8 ++++---- app/src/main/res/values/strings.xml | 3 +++ 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index aa802ce..00e8cc3 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -189,7 +189,8 @@ fun AppNavHost( }, onNavigatePartList = { group -> navController.currentBackStackEntry?.savedStateHandle?.set("groupName", group.name) - navController.navigate(routePartList(user?.agencyId ?: 0, group.id)) + val agencyId = user?.agencyId + if (agencyId != null) navController.navigate(routePartList(agencyId, group.id)) } ) } @@ -262,7 +263,8 @@ fun MainScreen( parentNavController.navigate(ROUTE_SETTINGS) }, onNavigateOrderDetail = { order -> - parentNavController.navigate(routeOrderDetail(user?.agencyId ?: 0, order.orderId)) + val agencyId = user?.agencyId + if (agencyId != null) parentNavController.navigate(routeOrderDetail(agencyId, order.orderId)) }, onNavigationOrder = { navController.navigate(ROUTE_ORDERS) { @@ -287,7 +289,8 @@ fun MainScreen( OrderListScreen( paddingValues = innerPadding, onNavigateOrderDetail = { order -> - parentNavController.navigate(routeOrderDetail(user?.agencyId ?: 0, order.orderId)) + val agencyId = user?.agencyId + if (agencyId != null) parentNavController.navigate(routeOrderDetail(agencyId, order.orderId)) } ) } diff --git a/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt index 001cb02..2e4377e 100644 --- a/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt @@ -187,16 +187,16 @@ fun UserSection( style = MaterialTheme.typography.bodyMedium, color = textSecondaryColor() ) - if (!user?.startedAt.isNullOrEmpty()) { + user?.startedAt?.takeIf { it.isNotBlank() }?.let { startedAt -> Text( - text = formatDate(user.startedAt), + text = formatDate(startedAt), style = MaterialTheme.typography.bodyMedium, color = textSecondaryColor() ) } - if (!user?.endedAt.isNullOrEmpty()) { + user?.endedAt?.takeIf { it.isNotBlank() }?.let { endedAt -> Text( - text = formatDate(user.endedAt), + text = formatDate(endedAt), style = MaterialTheme.typography.bodyMedium, color = textSecondaryColor() ) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1bf8cf7..2ff1e1b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -137,6 +137,9 @@ EA - + + 지점명을 찾을 수 없습니다. + 이메일을 입력해주세요 올바른 이메일 형식이 아닙니다 From e9e4d950d96f3d0421fba803e9ed099f21cc8410 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Tue, 4 Nov 2025 14:42:23 +0900 Subject: [PATCH 78/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/values/strings.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2ff1e1b..1bf8cf7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -137,9 +137,6 @@ EA - - - 지점명을 찾을 수 없습니다. - 이메일을 입력해주세요 올바른 이메일 형식이 아닙니다 From b0d7ec24671742c46c38f1ff9c40c6f97c96ee14 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Tue, 4 Nov 2025 16:04:44 +0900 Subject: [PATCH 79/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sampoom/android/feature/setting/ui/SettingScreen.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt index 2e4377e..5a6090e 100644 --- a/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt @@ -136,7 +136,6 @@ fun SettingScreen( TextButton( onClick = { showLogoutDialog = false - onLogoutClick() } ) { Text(stringResource(R.string.common_confirm)) From 542f921fed984ec3a22a97c4149c2086f629bc7d Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Tue, 4 Nov 2025 16:18:04 +0900 Subject: [PATCH 80/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/sampoom/android/feature/setting/ui/SettingScreen.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt index 5a6090e..324a561 100644 --- a/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt @@ -167,12 +167,12 @@ fun UserSection( horizontalAlignment = Alignment.Start ) { Text( - text = user?.userName.toString(), + text = user?.userName ?: "", style = MaterialTheme.typography.headlineLarge, color = textColor() ) Text( - text = user?.position.toString(), + text = user?.position ?: "", style = MaterialTheme.typography.bodyMedium, color = textSecondaryColor() ) @@ -182,7 +182,7 @@ fun UserSection( horizontalAlignment = Alignment.End ) { Text( - text = user?.email.toString(), + text = user?.email ?: "", style = MaterialTheme.typography.bodyMedium, color = textSecondaryColor() ) From c9b980bd401d1b0178d916f1f07017a4bea945ef Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Tue, 4 Nov 2025 16:58:52 +0900 Subject: [PATCH 81/88] =?UTF-8?q?[FIX]=20Role=20Enum=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/core/preferences/AuthPreferences.kt | 7 +++++-- .../feature/auth/data/mapper/AuthMappers.kt | 13 ++++++++++--- .../auth/data/repository/AuthRepositoryImpl.kt | 2 -- .../android/feature/auth/domain/model/User.kt | 15 ++++++++++++++- .../feature/dashboard/ui/DashboardScreen.kt | 16 +++++++++++++++- 5 files changed, 44 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt b/app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt index f14fb1d..c7ef2f3 100644 --- a/app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt +++ b/app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt @@ -7,6 +7,7 @@ import androidx.datastore.preferences.core.longPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore import com.sampoom.android.feature.auth.domain.model.User +import com.sampoom.android.feature.auth.domain.model.UserRole import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton @@ -48,7 +49,7 @@ class AuthPreferences @Inject constructor( prefs[Keys.USER_ID] = cryptoManager.encrypt(user.userId.toString()) prefs[Keys.USER_NAME] = cryptoManager.encrypt(user.userName) prefs[Keys.USER_EMAIL] = cryptoManager.encrypt(user.email) - prefs[Keys.USER_ROLE] = cryptoManager.encrypt(user.role) + prefs[Keys.USER_ROLE] = cryptoManager.encrypt(user.role.name) prefs[Keys.USER_POSITION] = cryptoManager.encrypt(user.position) prefs[Keys.USER_WORKSPACE] = cryptoManager.encrypt(user.workspace) prefs[Keys.USER_BRANCH] = cryptoManager.encrypt(user.branch) @@ -95,7 +96,9 @@ class AuthPreferences @Inject constructor( cryptoManager.decrypt(userId).toLong(), cryptoManager.decrypt(userName), cryptoManager.decrypt(userEmail), - cryptoManager.decrypt(userRole), + cryptoManager.decrypt(userRole).let { decrypted -> + try { UserRole.valueOf(decrypted.uppercase()) } catch (_: Exception) { UserRole.STAFF } + }, cryptoManager.decrypt(accessToken), cryptoManager.decrypt(refreshToken), remaining, diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt index 557ffee..f6aa68a 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt @@ -3,12 +3,13 @@ package com.sampoom.android.feature.auth.data.mapper import com.sampoom.android.feature.auth.data.remote.dto.GetProfileResponseDto import com.sampoom.android.feature.auth.data.remote.dto.LoginResponseDto import com.sampoom.android.feature.auth.domain.model.User +import com.sampoom.android.feature.auth.domain.model.UserRole fun LoginResponseDto.toModel(): User = User( userId = userId, userName = "", email = "", - role = "", + role = UserRole.STAFF, accessToken = accessToken, refreshToken = refreshToken, expiresIn = expiresIn, @@ -24,7 +25,7 @@ fun GetProfileResponseDto.toModel(): User = User( userId = userId, userName = userName, email = email, - role = role, + role = role.toUserRole(), accessToken = "", refreshToken = "", expiresIn = 0L, @@ -41,4 +42,10 @@ fun User.mergeWith(profile: User): User = this.copy( position = profile.position, workspace = profile.workspace, branch = profile.branch -) \ No newline at end of file +) + +private fun String.toUserRole(): UserRole = try { + UserRole.valueOf(this.uppercase()) +} catch (_: Exception) { + UserRole.STAFF +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt index d630d3f..a1e49b2 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt @@ -1,7 +1,6 @@ package com.sampoom.android.feature.auth.data.repository import com.sampoom.android.core.preferences.AuthPreferences -import com.sampoom.android.feature.auth.data.mapper.mergeWith import com.sampoom.android.feature.auth.data.mapper.toModel import com.sampoom.android.feature.auth.data.remote.api.AuthApi import com.sampoom.android.feature.auth.data.remote.dto.LoginRequestDto @@ -10,7 +9,6 @@ import com.sampoom.android.feature.auth.data.remote.dto.SignUpRequestDto import com.sampoom.android.feature.auth.domain.model.User import com.sampoom.android.feature.auth.domain.repository.AuthRepository import javax.inject.Inject -import kotlin.math.log class AuthRepositoryImpl @Inject constructor( private val api: AuthApi, diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt index d4a4fb5..4259b60 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt @@ -1,10 +1,23 @@ package com.sampoom.android.feature.auth.domain.model +enum class UserRole { + STAFF, // 사원 + SENIOR_STAFF, // 주임 + ASSISTANT_MANAGER, // 대리 + MANAGER, // 과장 + DEPUTY_GENERAL_MANAGER, // 차장 + GENERAL_MANAGER, // 부장 + DIRECTOR, // 이사 + VICE_PRESIDENT, // 부사장 + PRESIDENT, // 사장 + CHAIRMAN // 회장 +} + data class User( val userId: Long, val userName: String, val email: String, - val role: String, + val role: UserRole, val accessToken: String, val refreshToken: String, val expiresIn: Long, diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt index a67b26a..a76be26 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt @@ -55,6 +55,7 @@ import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.auth.domain.model.User +import com.sampoom.android.feature.auth.domain.model.UserRole import com.sampoom.android.feature.order.domain.model.Order @Composable @@ -70,7 +71,20 @@ fun DashboardScreen( val user by viewModel.user.collectAsStateWithLifecycle() val pullRefreshState = rememberPullToRefreshState() val orderListPaged = viewModel.orderListPaged.collectAsLazyPagingItems() - val isManager = user?.role == "ADMIN" + val isManager = when (user?.role) { + UserRole.STAFF, + UserRole.SENIOR_STAFF, + UserRole.ASSISTANT_MANAGER, + UserRole.MANAGER, + UserRole.DEPUTY_GENERAL_MANAGER, + UserRole.GENERAL_MANAGER, + UserRole.DIRECTOR, + UserRole.VICE_PRESIDENT, + UserRole.PRESIDENT, + UserRole.CHAIRMAN -> true + + else -> false + } LaunchedEffect(errorLabel) { viewModel.bindLabel(errorLabel) From 5151246af2ccdc0631cfd5874e6515a3819edc4e Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Thu, 6 Nov 2025 00:26:47 +0900 Subject: [PATCH 82/88] =?UTF-8?q?[REFAC]=20=EC=A7=81=EA=B8=89=20Enum=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sampoom/android/MainActivity.kt | 18 +++++ .../android/app/navigation/AppNavHost.kt | 24 +++---- .../android/core/model/UserPosition.kt | 14 ++++ .../core/preferences/AuthPreferences.kt | 15 ++--- .../core/ui/component/CommonTextField.kt | 8 ++- .../sampoom/android/core/util/DelayNetwork.kt | 23 +++++++ .../android/core/util/PositionToKorean.kt | 17 +++++ .../feature/auth/data/mapper/AuthMappers.kt | 16 ++--- .../data/repository/AuthRepositoryImpl.kt | 7 +- .../android/feature/auth/domain/model/User.kt | 17 +---- .../android/feature/auth/ui/SignUpScreen.kt | 67 ++++++++++++++++--- .../android/feature/auth/ui/SignUpUiEvent.kt | 4 +- .../android/feature/auth/ui/SignUpUiState.kt | 6 +- .../feature/auth/ui/SignUpViewModel.kt | 12 +++- .../feature/dashboard/ui/DashboardScreen.kt | 24 +++---- .../feature/setting/ui/SettingScreen.kt | 16 +++-- app/src/main/res/values/strings.xml | 1 + 17 files changed, 209 insertions(+), 80 deletions(-) create mode 100644 app/src/main/java/com/sampoom/android/core/model/UserPosition.kt create mode 100644 app/src/main/java/com/sampoom/android/core/util/DelayNetwork.kt create mode 100644 app/src/main/java/com/sampoom/android/core/util/PositionToKorean.kt diff --git a/app/src/main/java/com/sampoom/android/MainActivity.kt b/app/src/main/java/com/sampoom/android/MainActivity.kt index fd1d58f..0112e92 100644 --- a/app/src/main/java/com/sampoom/android/MainActivity.kt +++ b/app/src/main/java/com/sampoom/android/MainActivity.kt @@ -1,8 +1,13 @@ package com.sampoom.android +import android.os.Build import android.os.Bundle import androidx.activity.ComponentActivity +import androidx.activity.SystemBarStyle import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb import com.sampoom.android.app.navigation.AppNavHost import com.sampoom.android.core.ui.theme.SampoomManagementTheme import dagger.hilt.android.AndroidEntryPoint @@ -11,6 +16,19 @@ import dagger.hilt.android.AndroidEntryPoint class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + enableEdgeToEdge( + statusBarStyle = SystemBarStyle.auto( + lightScrim = Color.Transparent.toArgb(), + darkScrim = Color.Transparent.toArgb() + ), + navigationBarStyle = SystemBarStyle.auto( + lightScrim = Color.Transparent.toArgb(), + darkScrim = Color.Transparent.toArgb() + ) + ) + if (Build.VERSION.SDK_INT >= 29) { + window.isNavigationBarContrastEnforced = false + } setContent { SampoomManagementTheme { AppNavHost() diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index 00e8cc3..dc3675c 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -128,18 +128,18 @@ fun AppNavHost( } } - LaunchedEffect(currentRoute, homeNavColor, lightIcons) { - val window = activity?.window ?: return@LaunchedEffect - if (currentRoute == ROUTE_HOME) { - window.navigationBarColor = homeNavColor.toArgb() - WindowInsetsControllerCompat(window, window.decorView) - .isAppearanceLightNavigationBars = lightIcons - } else { - window.navigationBarColor = elseNavColor.toArgb() - WindowInsetsControllerCompat(window, window.decorView) - .isAppearanceLightNavigationBars = lightIcons - } - } +// LaunchedEffect(currentRoute, homeNavColor, lightIcons) { +// val window = activity?.window ?: return@LaunchedEffect +// if (currentRoute == ROUTE_HOME) { +// window.navigationBarColor = homeNavColor.toArgb() +// WindowInsetsControllerCompat(window, window.decorView) +// .isAppearanceLightNavigationBars = lightIcons +// } else { +// window.navigationBarColor = elseNavColor.toArgb() +// WindowInsetsControllerCompat(window, window.decorView) +// .isAppearanceLightNavigationBars = lightIcons +// } +// } if (isLoading) { Box( diff --git a/app/src/main/java/com/sampoom/android/core/model/UserPosition.kt b/app/src/main/java/com/sampoom/android/core/model/UserPosition.kt new file mode 100644 index 0000000..82e6f14 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/model/UserPosition.kt @@ -0,0 +1,14 @@ +package com.sampoom.android.core.model + +enum class UserPosition { + STAFF, // 사원 + SENIOR_STAFF, // 주임 + ASSISTANT_MANAGER, // 대리 + MANAGER, // 과장 + DEPUTY_GENERAL_MANAGER, // 차장 + GENERAL_MANAGER, // 부장 + DIRECTOR, // 이사 + VICE_PRESIDENT, // 부사장 + PRESIDENT, // 사장 + CHAIRMAN // 회장 +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt b/app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt index c7ef2f3..5b3faeb 100644 --- a/app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt +++ b/app/src/main/java/com/sampoom/android/core/preferences/AuthPreferences.kt @@ -6,13 +6,12 @@ import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.longPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore +import com.sampoom.android.core.model.UserPosition import com.sampoom.android.feature.auth.domain.model.User -import com.sampoom.android.feature.auth.domain.model.UserRole import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton import kotlinx.coroutines.flow.first -import java.time.LocalDateTime // Per official guidance, DataStore instance should be single and at top-level. private val Context.authDataStore by preferencesDataStore(name = "auth_prefs") @@ -49,8 +48,8 @@ class AuthPreferences @Inject constructor( prefs[Keys.USER_ID] = cryptoManager.encrypt(user.userId.toString()) prefs[Keys.USER_NAME] = cryptoManager.encrypt(user.userName) prefs[Keys.USER_EMAIL] = cryptoManager.encrypt(user.email) - prefs[Keys.USER_ROLE] = cryptoManager.encrypt(user.role.name) - prefs[Keys.USER_POSITION] = cryptoManager.encrypt(user.position) + prefs[Keys.USER_ROLE] = cryptoManager.encrypt(user.role) + prefs[Keys.USER_POSITION] = cryptoManager.encrypt(user.position.name) prefs[Keys.USER_WORKSPACE] = cryptoManager.encrypt(user.workspace) prefs[Keys.USER_BRANCH] = cryptoManager.encrypt(user.branch) prefs[Keys.USER_AGENCY_ID] = cryptoManager.encrypt(user.agencyId.toString()) @@ -96,13 +95,13 @@ class AuthPreferences @Inject constructor( cryptoManager.decrypt(userId).toLong(), cryptoManager.decrypt(userName), cryptoManager.decrypt(userEmail), - cryptoManager.decrypt(userRole).let { decrypted -> - try { UserRole.valueOf(decrypted.uppercase()) } catch (_: Exception) { UserRole.STAFF } - }, + cryptoManager.decrypt(userRole), cryptoManager.decrypt(accessToken), cryptoManager.decrypt(refreshToken), remaining, - cryptoManager.decrypt(userPosition), + cryptoManager.decrypt(userPosition).let { decrypted -> + try { UserPosition.valueOf(decrypted.uppercase()) } catch (_: Exception) { UserPosition.STAFF } + }, cryptoManager.decrypt(userWorkspace), cryptoManager.decrypt(userBranch), cryptoManager.decrypt(userAgencyId).toLong(), diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt b/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt index 0b4867c..1e3f525 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt @@ -38,7 +38,10 @@ fun CommonTextField( isError: Boolean = false, errorMessage: String? = null, imeAction: ImeAction = ImeAction.Next, - keyboardActions: KeyboardActions = KeyboardActions() + keyboardActions: KeyboardActions = KeyboardActions(), + readOnly: Boolean = false, + singleLine: Boolean = true, + trailingIcon: @Composable (() -> Unit)? = null ) { var passwordVisible by remember { mutableStateOf(false) } @@ -84,7 +87,8 @@ fun CommonTextField( modifier = modifier .fillMaxWidth() .padding(vertical = 4.dp), - singleLine = true, + readOnly = readOnly, + singleLine = singleLine, enabled = enabled, isError = isError, trailingIcon = trailingIconView, diff --git a/app/src/main/java/com/sampoom/android/core/util/DelayNetwork.kt b/app/src/main/java/com/sampoom/android/core/util/DelayNetwork.kt new file mode 100644 index 0000000..6f78de2 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/util/DelayNetwork.kt @@ -0,0 +1,23 @@ +package com.sampoom.android.core.util + +import kotlinx.coroutines.delay + +suspend fun retry( + times: Int = 5, + initialDelay: Long = 300, + maxDelay: Long = 1500, + factor: Double = 1.8, + block: suspend () -> T +): T { + var currentDelay = initialDelay + repeat(times - 1) { + try { + return block() + } catch (t: Throwable) { + // 서버 반영 지연에서만 재시도하고, 다른 오류는 그대로 throw 하려면 필터링 가능 + } + delay(currentDelay) + currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay) + } + return block() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/util/PositionToKorean.kt b/app/src/main/java/com/sampoom/android/core/util/PositionToKorean.kt new file mode 100644 index 0000000..75f00dc --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/util/PositionToKorean.kt @@ -0,0 +1,17 @@ +package com.sampoom.android.core.util + +import com.sampoom.android.core.model.UserPosition + +fun positionToKorean(position: UserPosition?): String = when (position) { + UserPosition.STAFF -> "사원" + UserPosition.SENIOR_STAFF -> "주임" + UserPosition.ASSISTANT_MANAGER -> "대리" + UserPosition.MANAGER -> "과장" + UserPosition.DEPUTY_GENERAL_MANAGER -> "차장" + UserPosition.GENERAL_MANAGER -> "부장" + UserPosition.DIRECTOR -> "이사" + UserPosition.VICE_PRESIDENT -> "부사장" + UserPosition.PRESIDENT -> "사장" + UserPosition.CHAIRMAN -> "회장" + else -> "-" +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt index f6aa68a..6a54986 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt @@ -1,19 +1,19 @@ package com.sampoom.android.feature.auth.data.mapper +import com.sampoom.android.core.model.UserPosition import com.sampoom.android.feature.auth.data.remote.dto.GetProfileResponseDto import com.sampoom.android.feature.auth.data.remote.dto.LoginResponseDto import com.sampoom.android.feature.auth.domain.model.User -import com.sampoom.android.feature.auth.domain.model.UserRole fun LoginResponseDto.toModel(): User = User( userId = userId, userName = "", email = "", - role = UserRole.STAFF, + role = "", accessToken = accessToken, refreshToken = refreshToken, expiresIn = expiresIn, - position = "", + position = UserPosition.STAFF, workspace = "", branch = "", agencyId = 0, @@ -25,11 +25,11 @@ fun GetProfileResponseDto.toModel(): User = User( userId = userId, userName = userName, email = email, - role = role.toUserRole(), + role = role, accessToken = "", refreshToken = "", expiresIn = 0L, - position = position, + position = position.toUserRole(), workspace = workspace, branch = branch, agencyId = organizationId, @@ -44,8 +44,8 @@ fun User.mergeWith(profile: User): User = this.copy( branch = profile.branch ) -private fun String.toUserRole(): UserRole = try { - UserRole.valueOf(this.uppercase()) +private fun String.toUserRole(): UserPosition = try { + UserPosition.valueOf(this.uppercase()) } catch (_: Exception) { - UserRole.STAFF + UserPosition.STAFF } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt index a1e49b2..5273dce 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt @@ -1,6 +1,7 @@ package com.sampoom.android.feature.auth.data.repository import com.sampoom.android.core.preferences.AuthPreferences +import com.sampoom.android.core.util.retry import com.sampoom.android.feature.auth.data.mapper.toModel import com.sampoom.android.feature.auth.data.remote.api.AuthApi import com.sampoom.android.feature.auth.data.remote.dto.LoginRequestDto @@ -14,6 +15,7 @@ class AuthRepositoryImpl @Inject constructor( private val api: AuthApi, private val preferences: AuthPreferences ) : AuthRepository { + override suspend fun signUp( email: String, password: String, @@ -55,8 +57,9 @@ class AuthRepositoryImpl @Inject constructor( preferences.saveUser(loginUser) - val profileDto = getProfile("AGENCY") - val profileUser = profileDto.getOrThrow() + val profileUser = retry(times = 5, initialDelay = 300) { + getProfile("AGENCY").getOrThrow() + } val user = User( userId = loginUser.userId, diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt index 4259b60..984500a 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/model/User.kt @@ -1,27 +1,16 @@ package com.sampoom.android.feature.auth.domain.model -enum class UserRole { - STAFF, // 사원 - SENIOR_STAFF, // 주임 - ASSISTANT_MANAGER, // 대리 - MANAGER, // 과장 - DEPUTY_GENERAL_MANAGER, // 차장 - GENERAL_MANAGER, // 부장 - DIRECTOR, // 이사 - VICE_PRESIDENT, // 부사장 - PRESIDENT, // 사장 - CHAIRMAN // 회장 -} +import com.sampoom.android.core.model.UserPosition data class User( val userId: Long, val userName: String, val email: String, - val role: UserRole, + val role: String, val accessToken: String, val refreshToken: String, val expiresIn: Long, - val position: String, + val position: UserPosition, val workspace: String, val branch: String, val agencyId: Long, diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt index 8123ed3..3515f95 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt @@ -15,7 +15,11 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExposedDropdownMenuAnchorType +import androidx.compose.material3.ExposedDropdownMenuBox +import androidx.compose.material3.ExposedDropdownMenuDefaults import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.Scaffold @@ -26,7 +30,9 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester @@ -39,8 +45,10 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import com.sampoom.android.R +import com.sampoom.android.core.model.UserPosition import com.sampoom.android.core.ui.component.CommonButton import com.sampoom.android.core.ui.component.CommonTextField +import com.sampoom.android.core.util.positionToKorean @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -72,6 +80,9 @@ fun SignUpScreen( if (state.success) onSuccess() } + val positionItems = remember { UserPosition.entries } + var positionMenuExpanded by remember { mutableStateOf(false) } + Scaffold( topBar = { TopAppBar( @@ -148,16 +159,52 @@ fun SignUpScreen( text = stringResource(R.string.signup_title_position), fontSize = labelTextSize ) - CommonTextField( - modifier = Modifier.fillMaxWidth().focusRequester(positionFocus), - value = state.position, - onValueChange = { viewModel.onEvent(SignUpUiEvent.PositionChanged(it)) }, - placeholder = stringResource(R.string.signup_placeholder_position), - isError = state.positionError != null, - errorMessage = state.positionError, - imeAction = ImeAction.Next, - keyboardActions = KeyboardActions(onNext = { emailFocus.requestFocus() }) - ) +// CommonTextField( +// modifier = Modifier.fillMaxWidth().focusRequester(positionFocus), +// value = state.position, +// onValueChange = { viewModel.onEvent(SignUpUiEvent.PositionChanged(it)) }, +// placeholder = stringResource(R.string.signup_placeholder_position), +// isError = state.positionError != null, +// errorMessage = state.positionError, +// imeAction = ImeAction.Next, +// keyboardActions = KeyboardActions(onNext = { emailFocus.requestFocus() }) +// ) + ExposedDropdownMenuBox( + expanded = positionMenuExpanded, + onExpandedChange = { positionMenuExpanded = it } + ) { + CommonTextField( + modifier = Modifier + .menuAnchor( + type = ExposedDropdownMenuAnchorType.PrimaryNotEditable, + enabled = true + ) + .fillMaxWidth(), + readOnly = true, + value = state.position?.let { positionToKorean(it) } ?: "", + onValueChange = {}, + placeholder = stringResource(R.string.signup_placeholder_position), + isError = state.positionError != null, + errorMessage = state.positionError, + trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = positionMenuExpanded) }, + singleLine = true + ) + ExposedDropdownMenu( + expanded = positionMenuExpanded, + onDismissRequest = { positionMenuExpanded = false } + ) { + positionItems.forEach { role -> + DropdownMenuItem( + text = { Text(positionToKorean(role)) }, + onClick = { + viewModel.onEvent(SignUpUiEvent.PositionChanged(role)) + positionMenuExpanded = false + emailFocus.requestFocus() + } + ) + } + } + } Spacer(Modifier.height(8.dp)) Text( text = stringResource(R.string.signup_title_email), diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt index eb8e77b..dda938b 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt @@ -1,9 +1,11 @@ package com.sampoom.android.feature.auth.ui +import com.sampoom.android.core.model.UserPosition + sealed interface SignUpUiEvent { data class NameChanged(val name: String) : SignUpUiEvent data class BranchChanged(val branch: String) : SignUpUiEvent - data class PositionChanged(val position: String) : SignUpUiEvent + data class PositionChanged(val position: UserPosition) : SignUpUiEvent data class EmailChanged(val email: String) : SignUpUiEvent data class PasswordChanged(val password: String) : SignUpUiEvent data class PasswordCheckChanged(val passwordCheck: String) : SignUpUiEvent diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt index d274bf1..f8c7383 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt @@ -1,10 +1,12 @@ package com.sampoom.android.feature.auth.ui +import com.sampoom.android.core.model.UserPosition + data class SignUpUiState( val name: String = "", val workspace: String = "AGENCY", val branch: String = "", - val position: String = "", + val position: UserPosition? = null, val email: String = "", val password: String = "", val passwordCheck: String = "", @@ -23,7 +25,7 @@ data class SignUpUiState( val isValid: Boolean get() = name.isNotBlank() && branch.isNotBlank() && - position.isNotBlank() && + position != null && email.isNotBlank() && password.isNotBlank() && passwordCheck.isNotBlank() && diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt index 68a3fdb..50d5633 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt @@ -4,9 +4,13 @@ import android.app.Application import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.sampoom.android.R import com.sampoom.android.core.network.serverMessageOrNull import com.sampoom.android.core.util.GlobalMessageHandler import com.sampoom.android.feature.auth.domain.AuthValidator +import com.sampoom.android.feature.auth.domain.AuthValidator.validateEmail +import com.sampoom.android.feature.auth.domain.AuthValidator.validatePassword +import com.sampoom.android.feature.auth.domain.AuthValidator.validatePasswordCheck import com.sampoom.android.feature.auth.domain.ValidationResult import com.sampoom.android.feature.auth.domain.usecase.SignUpUseCase import dagger.hilt.android.lifecycle.HiltViewModel @@ -90,7 +94,11 @@ class SignUpViewModel @Inject constructor( } private fun validatePosition() { - val result = AuthValidator.validateNotEmpty(_state.value.position, positionLabel) + val result = if (_state.value.position == null) { + ValidationResult.Error(messageResId = R.string.common_required_field) + } else { + ValidationResult.Success + } _state.value = _state.value.copy( positionError = result.toErrorMessage() ) @@ -143,7 +151,7 @@ class SignUpViewModel @Inject constructor( workspace = s.workspace, branch = s.branch, userName = s.name, - position = s.position + position = s.position!!.name ) .onSuccess { _state.update { diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt index a76be26..cc5eef5 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt @@ -47,6 +47,7 @@ import androidx.paging.LoadState import androidx.paging.compose.LazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems import com.sampoom.android.R +import com.sampoom.android.core.model.UserPosition import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent import com.sampoom.android.core.ui.component.OrderItem @@ -55,7 +56,6 @@ import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.auth.domain.model.User -import com.sampoom.android.feature.auth.domain.model.UserRole import com.sampoom.android.feature.order.domain.model.Order @Composable @@ -71,17 +71,17 @@ fun DashboardScreen( val user by viewModel.user.collectAsStateWithLifecycle() val pullRefreshState = rememberPullToRefreshState() val orderListPaged = viewModel.orderListPaged.collectAsLazyPagingItems() - val isManager = when (user?.role) { - UserRole.STAFF, - UserRole.SENIOR_STAFF, - UserRole.ASSISTANT_MANAGER, - UserRole.MANAGER, - UserRole.DEPUTY_GENERAL_MANAGER, - UserRole.GENERAL_MANAGER, - UserRole.DIRECTOR, - UserRole.VICE_PRESIDENT, - UserRole.PRESIDENT, - UserRole.CHAIRMAN -> true + val isManager = when (user?.position) { + UserPosition.STAFF, + UserPosition.SENIOR_STAFF, + UserPosition.ASSISTANT_MANAGER, + UserPosition.MANAGER, + UserPosition.DEPUTY_GENERAL_MANAGER, + UserPosition.GENERAL_MANAGER, + UserPosition.DIRECTOR, + UserPosition.VICE_PRESIDENT, + UserPosition.PRESIDENT, + UserPosition.CHAIRMAN -> true else -> false } diff --git a/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt index 324a561..2d083f9 100644 --- a/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt @@ -42,6 +42,7 @@ import com.sampoom.android.core.ui.theme.disableColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.core.util.formatDate +import com.sampoom.android.core.util.positionToKorean import com.sampoom.android.feature.auth.domain.model.User @OptIn(ExperimentalMaterial3Api::class) @@ -69,12 +70,12 @@ fun SettingScreen( } } - LaunchedEffect(uiState.logoutSuccess) { - if (uiState.logoutSuccess) { - viewModel.clearSuccess() - onLogoutClick() - } - } +// LaunchedEffect(uiState.logoutSuccess) { +// if (uiState.logoutSuccess) { +// viewModel.clearSuccess() +// onLogoutClick() +// } +// } PullToRefreshBox( isRefreshing = false, @@ -136,6 +137,7 @@ fun SettingScreen( TextButton( onClick = { showLogoutDialog = false + onLogoutClick() } ) { Text(stringResource(R.string.common_confirm)) @@ -172,7 +174,7 @@ fun UserSection( color = textColor() ) Text( - text = user?.position ?: "", + text = positionToKorean(user?.position), style = MaterialTheme.typography.bodyMedium, color = textSecondaryColor() ) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1bf8cf7..8aa7007 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -128,6 +128,7 @@ 오류가 발생했습니다 + 내용을 입력해주세요 다시 시도 확인 취소 From b7dd1076e8ab5074ca5b086c8b59d0dda0a3d500 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Thu, 6 Nov 2025 09:37:22 +0900 Subject: [PATCH 83/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/AppNavHost.kt | 21 ------------------- .../core/ui/component/CommonTextField.kt | 3 +-- .../sampoom/android/core/util/DelayNetwork.kt | 9 +++++++- .../feature/auth/data/mapper/AuthMappers.kt | 2 +- .../android/feature/auth/ui/SignUpScreen.kt | 11 ---------- .../feature/setting/ui/SettingScreen.kt | 7 ------- 6 files changed, 10 insertions(+), 43 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt index dc3675c..e8f66bc 100644 --- a/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt +++ b/app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt @@ -104,14 +104,6 @@ fun AppNavHost( val isLoggedIn by authViewModel.isLoggedIn.collectAsState() val isLoading by authViewModel.isLoading.collectAsState() val user by viewModel.user.collectAsStateWithLifecycle() - - val navBackStackEntry by navController.currentBackStackEntryAsState() - val currentRoute = navBackStackEntry?.destination?.route - val activity = LocalContext.current as? ComponentActivity - val homeNavColor = backgroundCardColor() - val elseNavColor = backgroundColor() - val lightIcons = !isSystemInDarkTheme() - val snackBarHostState = rememberCommonSnackBarHostState() var currentMessage by remember { mutableStateOf(null) } @@ -128,19 +120,6 @@ fun AppNavHost( } } -// LaunchedEffect(currentRoute, homeNavColor, lightIcons) { -// val window = activity?.window ?: return@LaunchedEffect -// if (currentRoute == ROUTE_HOME) { -// window.navigationBarColor = homeNavColor.toArgb() -// WindowInsetsControllerCompat(window, window.decorView) -// .isAppearanceLightNavigationBars = lightIcons -// } else { -// window.navigationBarColor = elseNavColor.toArgb() -// WindowInsetsControllerCompat(window, window.decorView) -// .isAppearanceLightNavigationBars = lightIcons -// } -// } - if (isLoading) { Box( modifier = Modifier.fillMaxSize(), diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt b/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt index 1e3f525..33769b5 100644 --- a/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt +++ b/app/src/main/java/com/sampoom/android/core/ui/component/CommonTextField.kt @@ -40,8 +40,7 @@ fun CommonTextField( imeAction: ImeAction = ImeAction.Next, keyboardActions: KeyboardActions = KeyboardActions(), readOnly: Boolean = false, - singleLine: Boolean = true, - trailingIcon: @Composable (() -> Unit)? = null + singleLine: Boolean = true ) { var passwordVisible by remember { mutableStateOf(false) } diff --git a/app/src/main/java/com/sampoom/android/core/util/DelayNetwork.kt b/app/src/main/java/com/sampoom/android/core/util/DelayNetwork.kt index 6f78de2..9daf43b 100644 --- a/app/src/main/java/com/sampoom/android/core/util/DelayNetwork.kt +++ b/app/src/main/java/com/sampoom/android/core/util/DelayNetwork.kt @@ -1,6 +1,8 @@ package com.sampoom.android.core.util import kotlinx.coroutines.delay +import java.io.IOException +import java.net.SocketTimeoutException suspend fun retry( times: Int = 5, @@ -14,7 +16,12 @@ suspend fun retry( try { return block() } catch (t: Throwable) { - // 서버 반영 지연에서만 재시도하고, 다른 오류는 그대로 throw 하려면 필터링 가능 + when (t) { + is SocketTimeoutException, is IOException -> { + + } + else -> throw t + } } delay(currentDelay) currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay) diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt index 6a54986..9980d70 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt @@ -46,6 +46,6 @@ fun User.mergeWith(profile: User): User = this.copy( private fun String.toUserRole(): UserPosition = try { UserPosition.valueOf(this.uppercase()) -} catch (_: Exception) { +} catch (_: IllegalArgumentException) { UserPosition.STAFF } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt index 3515f95..9ab5c3d 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt @@ -159,16 +159,6 @@ fun SignUpScreen( text = stringResource(R.string.signup_title_position), fontSize = labelTextSize ) -// CommonTextField( -// modifier = Modifier.fillMaxWidth().focusRequester(positionFocus), -// value = state.position, -// onValueChange = { viewModel.onEvent(SignUpUiEvent.PositionChanged(it)) }, -// placeholder = stringResource(R.string.signup_placeholder_position), -// isError = state.positionError != null, -// errorMessage = state.positionError, -// imeAction = ImeAction.Next, -// keyboardActions = KeyboardActions(onNext = { emailFocus.requestFocus() }) -// ) ExposedDropdownMenuBox( expanded = positionMenuExpanded, onExpandedChange = { positionMenuExpanded = it } @@ -186,7 +176,6 @@ fun SignUpScreen( placeholder = stringResource(R.string.signup_placeholder_position), isError = state.positionError != null, errorMessage = state.positionError, - trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = positionMenuExpanded) }, singleLine = true ) ExposedDropdownMenu( diff --git a/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt index 2d083f9..46b47e0 100644 --- a/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/setting/ui/SettingScreen.kt @@ -70,13 +70,6 @@ fun SettingScreen( } } -// LaunchedEffect(uiState.logoutSuccess) { -// if (uiState.logoutSuccess) { -// viewModel.clearSuccess() -// onLogoutClick() -// } -// } - PullToRefreshBox( isRefreshing = false, onRefresh = { viewModel.onEvent(SettingUiEvent.LoadProfile) }, From 3b7cbbd317661ff59364e5eed3917de0033773d3 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Thu, 6 Nov 2025 09:42:16 +0900 Subject: [PATCH 84/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sampoom/android/feature/auth/data/mapper/AuthMappers.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt index 9980d70..a6d9427 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt @@ -29,7 +29,7 @@ fun GetProfileResponseDto.toModel(): User = User( accessToken = "", refreshToken = "", expiresIn = 0L, - position = position.toUserRole(), + position = position.toUserPosition(), workspace = workspace, branch = branch, agencyId = organizationId, @@ -44,7 +44,7 @@ fun User.mergeWith(profile: User): User = this.copy( branch = profile.branch ) -private fun String.toUserRole(): UserPosition = try { +private fun String.toUserPosition(): UserPosition = try { UserPosition.valueOf(this.uppercase()) } catch (_: IllegalArgumentException) { UserPosition.STAFF From b2f9ea78b338ee0744c1834e61dc82072355cfe0 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Thu, 6 Nov 2025 22:56:02 +0900 Subject: [PATCH 85/88] =?UTF-8?q?[FEAT]=20=EB=B6=80=ED=92=88=20=EA=B0=80?= =?UTF-8?q?=EA=B2=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/core/ui/component/OrderItem.kt | 72 --------------- .../sampoom/android/core/util/FormatPrice.kt | 7 ++ .../feature/auth/data/mapper/AuthMappers.kt | 21 +++-- .../feature/auth/data/remote/api/AuthApi.kt | 4 + .../data/remote/dto/GetVendorsResponseDto.kt | 11 +++ .../data/repository/AuthRepositoryImpl.kt | 18 +++- .../feature/auth/domain/model/Vendor.kt | 11 +++ .../feature/auth/domain/model/VendorList.kt | 11 +++ .../auth/domain/repository/AuthRepository.kt | 2 + .../auth/domain/usecase/GetVendorUseCase.kt | 11 +++ .../android/feature/auth/ui/SignUpScreen.kt | 55 +++++++++-- .../android/feature/auth/ui/SignUpUiEvent.kt | 4 +- .../android/feature/auth/ui/SignUpUiState.kt | 6 ++ .../feature/auth/ui/SignUpViewModel.kt | 38 +++++++- .../feature/cart/data/mapper/CartMappers.kt | 2 +- .../feature/cart/data/remote/dto/CartDto.kt | 3 +- .../android/feature/cart/domain/model/Cart.kt | 9 +- .../android/feature/cart/ui/CartListScreen.kt | 49 +++++----- .../feature/cart/ui/CartListUiState.kt | 11 ++- .../feature/dashboard/ui/DashboardScreen.kt | 2 +- .../feature/order/data/mapper/OrderMappers.kt | 2 +- .../feature/order/data/remote/api/OrderApi.kt | 5 +- .../feature/order/data/remote/dto/OrderDto.kt | 3 +- .../data/remote/dto/ReceiveStockItemDto.kt | 6 ++ .../data/remote/dto/ReceiveStockRequestDto.kt | 5 + .../data/repository/OrderRepositoryImpl.kt | 14 ++- .../feature/order/domain/model/Order.kt | 14 ++- .../domain/repository/OrderRepository.kt | 2 +- .../domain/usecase/ReceiveOrderUseCase.kt | 2 +- .../feature/order/ui/OrderDetailContent.kt | 87 ++++++++++++++---- .../feature/order/ui/OrderDetailScreen.kt | 9 -- .../feature/order/ui/OrderDetailViewModel.kt | 22 ++++- .../android/feature/order/ui/OrderItem.kt | 92 +++++++++++++++++++ .../feature/order/ui/OrderListScreen.kt | 32 +++---- .../outbound/data/mapper/OutboundMappers.kt | 2 +- .../outbound/data/remote/dto/OutboundDto.kt | 3 +- .../feature/outbound/domain/model/Outbound.kt | 9 +- .../feature/outbound/ui/OutboundListScreen.kt | 43 ++++----- .../outbound/ui/OutboundListUiState.kt | 11 ++- .../feature/part/data/mapper/PartMappers.kt | 2 +- .../feature/part/data/remote/dto/PartDto.kt | 3 +- .../android/feature/part/domain/model/Part.kt | 3 +- .../feature/part/ui/PartDetailBottomSheet.kt | 25 ++++- .../android/feature/part/ui/PartListScreen.kt | 18 +++- .../android/feature/part/ui/PartScreen.kt | 21 ++++- app/src/main/res/values/strings.xml | 5 +- 46 files changed, 552 insertions(+), 235 deletions(-) delete mode 100644 app/src/main/java/com/sampoom/android/core/ui/component/OrderItem.kt create mode 100644 app/src/main/java/com/sampoom/android/core/util/FormatPrice.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/GetVendorsResponseDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/domain/model/Vendor.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/domain/model/VendorList.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/GetVendorUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/ReceiveStockItemDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/ReceiveStockRequestDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/order/ui/OrderItem.kt diff --git a/app/src/main/java/com/sampoom/android/core/ui/component/OrderItem.kt b/app/src/main/java/com/sampoom/android/core/ui/component/OrderItem.kt deleted file mode 100644 index e971cc9..0000000 --- a/app/src/main/java/com/sampoom/android/core/ui/component/OrderItem.kt +++ /dev/null @@ -1,72 +0,0 @@ -package com.sampoom.android.core.ui.component - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import com.sampoom.android.R -import com.sampoom.android.core.ui.theme.backgroundCardColor -import com.sampoom.android.core.ui.theme.textSecondaryColor -import com.sampoom.android.core.util.buildOrderTitle -import com.sampoom.android.core.util.formatDate -import com.sampoom.android.feature.order.domain.model.Order - -@Composable -fun OrderItem( - order: Order, - onClick: () -> Unit -) { - Card( - onClick = { onClick() }, - modifier = Modifier.fillMaxWidth(), - colors = CardDefaults.cardColors(containerColor = backgroundCardColor()) - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Column( - modifier = Modifier - .weight(1f) - ) { - Text( - text = buildOrderTitle(order), - style = MaterialTheme.typography.bodyMedium, - maxLines = 1 - ) - Spacer(Modifier.height(4.dp)) - Text( - text = order.agencyName ?: stringResource(R.string.common_slash), - style = MaterialTheme.typography.labelMedium, - color = textSecondaryColor() - ) - } - - Spacer(Modifier.width(12.dp)) - - Column(horizontalAlignment = Alignment.End) { - Text( - text = order.createdAt?.let { formatDate(it) } ?: stringResource(R.string.common_slash), - style = MaterialTheme.typography.labelMedium, - color = textSecondaryColor() - ) - Spacer(Modifier.height(6.dp)) - StatusChip(status = order.status) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/core/util/FormatPrice.kt b/app/src/main/java/com/sampoom/android/core/util/FormatPrice.kt new file mode 100644 index 0000000..91adf0f --- /dev/null +++ b/app/src/main/java/com/sampoom/android/core/util/FormatPrice.kt @@ -0,0 +1,7 @@ +package com.sampoom.android.core.util + +import java.text.NumberFormat +import java.util.Locale + +fun formatWon(value: Long): String = + NumberFormat.getInstance(Locale.KOREA).format(value) + "원" \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt index a6d9427..206707c 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/mapper/AuthMappers.kt @@ -2,8 +2,10 @@ package com.sampoom.android.feature.auth.data.mapper import com.sampoom.android.core.model.UserPosition import com.sampoom.android.feature.auth.data.remote.dto.GetProfileResponseDto +import com.sampoom.android.feature.auth.data.remote.dto.GetVendorsResponseDto import com.sampoom.android.feature.auth.data.remote.dto.LoginResponseDto import com.sampoom.android.feature.auth.domain.model.User +import com.sampoom.android.feature.auth.domain.model.Vendor fun LoginResponseDto.toModel(): User = User( userId = userId, @@ -37,15 +39,18 @@ fun GetProfileResponseDto.toModel(): User = User( endedAt = endedAt ) -fun User.mergeWith(profile: User): User = this.copy( - userName = profile.userName, - position = profile.position, - workspace = profile.workspace, - branch = profile.branch -) - private fun String.toUserPosition(): UserPosition = try { UserPosition.valueOf(this.uppercase()) } catch (_: IllegalArgumentException) { UserPosition.STAFF -} \ No newline at end of file +} + +fun GetVendorsResponseDto.toModel(): Vendor = Vendor( + id = id, + vendorCode = vendorCode, + name = name, + businessNumber = businessNumber, + ceoName = ceoName, + address = address, + status = status +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt index 7f70e50..fbbf1fb 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/api/AuthApi.kt @@ -11,6 +11,7 @@ import com.sampoom.android.feature.auth.data.remote.dto.RefreshResponseDto import com.sampoom.android.feature.auth.data.remote.dto.UpdateProfileRequestDto import com.sampoom.android.feature.auth.data.remote.dto.UpdateProfileResponseDto import com.sampoom.android.feature.auth.data.remote.dto.GetProfileResponseDto +import com.sampoom.android.feature.auth.data.remote.dto.GetVendorsResponseDto import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.Headers @@ -38,4 +39,7 @@ interface AuthApi { @PATCH("user/profile") suspend fun updateProfile(@Body body: UpdateProfileRequestDto): ApiResponse + + @GET("site/vendors") + suspend fun getVendors(): ApiResponse> } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/GetVendorsResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/GetVendorsResponseDto.kt new file mode 100644 index 0000000..46e260f --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/remote/dto/GetVendorsResponseDto.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.auth.data.remote.dto + +data class GetVendorsResponseDto( + val id: Long, + val vendorCode: String, + val name: String, + val businessNumber: String, + val ceoName: String, + val address: String, + val status: String +) diff --git a/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt index 5273dce..cdc8642 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/data/repository/AuthRepositoryImpl.kt @@ -8,7 +8,10 @@ import com.sampoom.android.feature.auth.data.remote.dto.LoginRequestDto import com.sampoom.android.feature.auth.data.remote.dto.RefreshRequestDto import com.sampoom.android.feature.auth.data.remote.dto.SignUpRequestDto import com.sampoom.android.feature.auth.domain.model.User +import com.sampoom.android.feature.auth.domain.model.VendorList import com.sampoom.android.feature.auth.domain.repository.AuthRepository +import com.sampoom.android.feature.outbound.data.mapper.toModel +import kotlinx.coroutines.delay import javax.inject.Inject class AuthRepositoryImpl @Inject constructor( @@ -36,7 +39,11 @@ class AuthRepositoryImpl @Inject constructor( ) ) if (!signUpRes.success) throw Exception(signUpRes.message) - signIn(email, password).getOrThrow() + + delay(500) + retry(times = 5, initialDelay = 500) { + signIn(email, password).getOrThrow() + } } } @@ -126,4 +133,13 @@ class AuthRepositoryImpl @Inject constructor( dto.data.toModel() } } + + override suspend fun getVendorList(): Result { + return runCatching { + val dto = api.getVendors() + if (!dto.success) throw Exception(dto.message) + val vendorItems = dto.data.map { it.toModel() } + VendorList(items = vendorItems) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/model/Vendor.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/model/Vendor.kt new file mode 100644 index 0000000..2b47188 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/model/Vendor.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.auth.domain.model + +data class Vendor( + val id: Long, + val vendorCode: String, + val name: String, + val businessNumber: String, + val ceoName: String, + val address: String, + val status: String +) diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/model/VendorList.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/model/VendorList.kt new file mode 100644 index 0000000..0f3431c --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/model/VendorList.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.auth.domain.model + +data class VendorList( + val items: List, + val totalCount: Int = items.size, + val isEmpty: Boolean = items.isEmpty() +) { + companion object Companion { + fun empty() = VendorList(emptyList()) + } +} diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt index 866028a..7d9e833 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/repository/AuthRepository.kt @@ -1,6 +1,7 @@ package com.sampoom.android.feature.auth.domain.repository import com.sampoom.android.feature.auth.domain.model.User +import com.sampoom.android.feature.auth.domain.model.VendorList interface AuthRepository { suspend fun signUp( @@ -18,4 +19,5 @@ interface AuthRepository { suspend fun clearTokens(): Result suspend fun isSignedIn(): Boolean suspend fun getProfile(workspace: String): Result + suspend fun getVendorList(): Result } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/GetVendorUseCase.kt b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/GetVendorUseCase.kt new file mode 100644 index 0000000..e41b1f1 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/auth/domain/usecase/GetVendorUseCase.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.auth.domain.usecase + +import com.sampoom.android.feature.auth.domain.model.VendorList +import com.sampoom.android.feature.auth.domain.repository.AuthRepository +import javax.inject.Inject + +class GetVendorUseCase @Inject constructor( + private val repository: AuthRepository +) { + suspend operator fun invoke(): Result = repository.getVendorList() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt index 9ab5c3d..9ead5b9 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpScreen.kt @@ -82,6 +82,7 @@ fun SignUpScreen( val positionItems = remember { UserPosition.entries } var positionMenuExpanded by remember { mutableStateOf(false) } + var vendorMenuExpanded by remember { mutableStateOf(false) } Scaffold( topBar = { @@ -144,16 +145,50 @@ fun SignUpScreen( text = stringResource(R.string.signup_title_branch), fontSize = labelTextSize ) - CommonTextField( - modifier = Modifier.fillMaxWidth().focusRequester(branchFocus), - value = state.branch, - onValueChange = { viewModel.onEvent(SignUpUiEvent.BranchChanged(it)) }, - placeholder = stringResource(R.string.signup_placeholder_branch), - isError = state.branchError != null, - errorMessage = state.branchError, - imeAction = ImeAction.Next, - keyboardActions = KeyboardActions(onNext = { positionFocus.requestFocus() }) - ) + ExposedDropdownMenuBox( + expanded = vendorMenuExpanded, + onExpandedChange = { vendorMenuExpanded = it && !state.vendorsLoading } + ) { + CommonTextField( + modifier = Modifier + .menuAnchor( + type = ExposedDropdownMenuAnchorType.PrimaryNotEditable, + enabled = true + ) + .fillMaxWidth() + .focusRequester(branchFocus), + readOnly = true, + value = state.selectedVendor?.name ?: "", + onValueChange = {}, + placeholder = stringResource(R.string.signup_placeholder_branch), + isError = state.branchError != null, + errorMessage = state.branchError, + singleLine = true, + enabled = !state.vendorsLoading + ) + ExposedDropdownMenu( + expanded = vendorMenuExpanded, + onDismissRequest = { vendorMenuExpanded = false } + ) { + if (state.vendorsLoading) { + DropdownMenuItem( + text = { Text("로딩 중...") }, + onClick = {} + ) + } else { + state.vendors.forEach { vendor -> + DropdownMenuItem( + text = { Text(vendor.name) }, + onClick = { + viewModel.onEvent(SignUpUiEvent.VendorChanged(vendor)) + vendorMenuExpanded = false + positionFocus.requestFocus() + } + ) + } + } + } + } Spacer(Modifier.height(8.dp)) Text( text = stringResource(R.string.signup_title_position), diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt index dda938b..90bfe1d 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiEvent.kt @@ -1,10 +1,12 @@ package com.sampoom.android.feature.auth.ui import com.sampoom.android.core.model.UserPosition +import com.sampoom.android.feature.auth.domain.model.Vendor sealed interface SignUpUiEvent { data class NameChanged(val name: String) : SignUpUiEvent - data class BranchChanged(val branch: String) : SignUpUiEvent +// data class BranchChanged(val branch: String) : SignUpUiEvent + data class VendorChanged(val vendor: Vendor) : SignUpUiEvent data class PositionChanged(val position: UserPosition) : SignUpUiEvent data class EmailChanged(val email: String) : SignUpUiEvent data class PasswordChanged(val password: String) : SignUpUiEvent diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt index f8c7383..25a1814 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpUiState.kt @@ -1,6 +1,7 @@ package com.sampoom.android.feature.auth.ui import com.sampoom.android.core.model.UserPosition +import com.sampoom.android.feature.auth.domain.model.Vendor data class SignUpUiState( val name: String = "", @@ -11,6 +12,11 @@ data class SignUpUiState( val password: String = "", val passwordCheck: String = "", + // Vendor + val vendors: List = emptyList(), + val selectedVendor: Vendor? = null, + val vendorsLoading: Boolean = false, + // Error message val nameError: String? = null, val branchError: String? = null, diff --git a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt index 50d5633..a448e7b 100644 --- a/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/auth/ui/SignUpViewModel.kt @@ -12,6 +12,7 @@ import com.sampoom.android.feature.auth.domain.AuthValidator.validateEmail import com.sampoom.android.feature.auth.domain.AuthValidator.validatePassword import com.sampoom.android.feature.auth.domain.AuthValidator.validatePasswordCheck import com.sampoom.android.feature.auth.domain.ValidationResult +import com.sampoom.android.feature.auth.domain.usecase.GetVendorUseCase import com.sampoom.android.feature.auth.domain.usecase.SignUpUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -24,6 +25,7 @@ import javax.inject.Inject class SignUpViewModel @Inject constructor( private val messageHandler: GlobalMessageHandler, private val singUp: SignUpUseCase, + private val getVendorUseCase: GetVendorUseCase, private val application: Application ) : ViewModel() { @@ -39,6 +41,10 @@ class SignUpViewModel @Inject constructor( private var positionLabel: String = "" private var errorLabel: String = "" + init { + loadVendors() + } + fun bindLabels(name: String, branch: String, position: String, error: String) { nameLabel = name branchLabel = branch @@ -51,8 +57,15 @@ class SignUpViewModel @Inject constructor( _state.value = _state.value.copy(name = e.name) validateName() } - is SignUpUiEvent.BranchChanged -> { - _state.value = _state.value.copy(branch = e.branch) +// is SignUpUiEvent.BranchChanged -> { +// _state.value = _state.value.copy(branch = e.branch) +// validateBranch() +// } + is SignUpUiEvent.VendorChanged -> { + _state.value = _state.value.copy( + selectedVendor = e.vendor, + branch = e.vendor.name + ) validateBranch() } is SignUpUiEvent.PositionChanged -> { @@ -169,4 +182,25 @@ class SignUpViewModel @Inject constructor( } Log.d(TAG, "submit: ${_state.value}") } + + private fun loadVendors() { + viewModelScope.launch { + _state.update { it.copy(vendorsLoading = true) } + getVendorUseCase() + .onSuccess { vendorList -> + _state.update { + it.copy( + vendors = vendorList.items, + vendorsLoading = false + ) + } + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _state.update { it.copy(vendorsLoading = false) } + } + } + } } diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/mapper/CartMappers.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/mapper/CartMappers.kt index e6729c3..9f59d29 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/data/mapper/CartMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/mapper/CartMappers.kt @@ -9,4 +9,4 @@ import com.sampoom.android.feature.cart.domain.model.CartPart fun CartDto.toModel(): Cart = Cart(categoryId, categoryName, groups.map { it.toModel() }) fun CartGroupDto.toModel(): CartGroup = CartGroup(groupId, groupName, parts.map { it.toModel() }) -fun CartPartDto.toModel(): CartPart = CartPart(cartItemId, partId, code, name, quantity) \ No newline at end of file +fun CartPartDto.toModel(): CartPart = CartPart(cartItemId, partId, code, name, quantity, standardCost) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/CartDto.kt b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/CartDto.kt index 6f4b211..d144195 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/CartDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/data/remote/dto/CartDto.kt @@ -17,5 +17,6 @@ data class CartPartDto( val partId: Long, val code: String, val name: String, - val quantity: Long + val quantity: Long, + val standardCost: Long ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/domain/model/Cart.kt b/app/src/main/java/com/sampoom/android/feature/cart/domain/model/Cart.kt index 1caf613..41a5a32 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/domain/model/Cart.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/domain/model/Cart.kt @@ -17,5 +17,10 @@ data class CartPart( val partId: Long, val code: String, val name: String, - val quantity: Long -) \ No newline at end of file + val quantity: Long, + val standardCost: Long +) + +// 품목 합계(단가 x 수량) +val CartPart.subtotal: Long + get() = standardCost * quantity \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt index 28acaaf..d17be0e 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListScreen.kt @@ -46,7 +46,9 @@ import com.sampoom.android.core.ui.theme.FailRed import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.core.util.formatWon import com.sampoom.android.feature.cart.domain.model.CartPart +import com.sampoom.android.feature.cart.domain.model.subtotal import com.sampoom.android.feature.order.ui.OrderResultBottomSheet @Composable @@ -68,7 +70,7 @@ fun CartListScreen( uiState.processedOrder?.let { order -> OrderResultBottomSheet( order = order, - onDismiss = { viewModel.onEvent(CartListUiEvent.DismissOrderResult)} + onDismiss = { viewModel.onEvent(CartListUiEvent.DismissOrderResult) } ) } @@ -87,7 +89,9 @@ fun CartListScreen( ) } ) { - Column(Modifier.fillMaxSize().padding(paddingValues)) { + Column(Modifier + .fillMaxSize() + .padding(paddingValues)) { Row( modifier = Modifier .fillMaxWidth() @@ -192,7 +196,7 @@ fun CartListScreen( variant = ButtonVariant.Primary, size = ButtonSize.Large, onClick = { showConfirmDialog = true } - ) { Text(stringResource(R.string.cart_order_parts)) } + ) { Text("${formatWon(uiState.totalCost)} ${stringResource(R.string.cart_order_parts)}") } } } } @@ -364,30 +368,6 @@ private fun CartPartItem( style = MaterialTheme.typography.titleMedium, modifier = Modifier.padding(horizontal = 24.dp) ) -// OutlinedTextField( -// value = part.quantity.toString(), -// onValueChange = { newValue -> -// when { -// newValue.isEmpty() -> onEvent(OutboundListUiEvent.UpdateQuantity(part.outboundId, 1)) -// newValue == "0" -> onEvent(OutboundListUiEvent.UpdateQuantity(part.outboundId, 1)) -// else -> { -// val newQuantity = newValue.toLongOrNull() -// if (newQuantity != null && newQuantity > 0) onEvent(OutboundListUiEvent.UpdateQuantity(part.outboundId, newQuantity)) -// else onEvent(OutboundListUiEvent.UpdateQuantity(part.outboundId, 1)) -// } -// } -// }, -// modifier = Modifier.width(100.dp), -// singleLine = true, -// keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), -// textStyle = MaterialTheme.typography.titleMedium.copy(textAlign = TextAlign.Center), -// colors = OutlinedTextFieldDefaults.colors( -// focusedBorderColor = Color.Transparent, -// unfocusedBorderColor = Color.Transparent, -// disabledBorderColor = Color.Transparent, -// errorBorderColor = Color.Transparent -// ) -// ) CommonButton( variant = ButtonVariant.Neutral, size = ButtonSize.Large, @@ -408,6 +388,21 @@ private fun CartPartItem( } } } + + val subtotal = part.subtotal + + Spacer(Modifier.height(8.dp)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End, + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + text = formatWon(subtotal), + style = MaterialTheme.typography.titleLarge + ) + } } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt index 37e10e5..ade7798 100644 --- a/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/cart/ui/CartListUiState.kt @@ -15,4 +15,13 @@ data class CartListUiState( val isProcessing: Boolean = false, val processError: String? = null, val processedOrder: Order? = null -) +) { + val totalCost: Long + get() = cartList.sumOf { category -> + category.groups.sumOf { group -> + group.parts.sumOf { part -> + part.standardCost * part.quantity + } + } + } +} diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt index cc5eef5..096f645 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt @@ -50,7 +50,7 @@ import com.sampoom.android.R import com.sampoom.android.core.model.UserPosition import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent -import com.sampoom.android.core.ui.component.OrderItem +import com.sampoom.android.feature.order.ui.OrderItem import com.sampoom.android.core.ui.theme.Main500 import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/mapper/OrderMappers.kt b/app/src/main/java/com/sampoom/android/feature/order/data/mapper/OrderMappers.kt index fd25e78..e2d37c9 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/mapper/OrderMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/mapper/OrderMappers.kt @@ -12,4 +12,4 @@ import com.sampoom.android.feature.order.domain.model.OrderPart fun OrderDto.toModel(): Order = Order(orderId, orderNumber, createdAt, status, agencyName, items.map { it.toModel() }) fun OrderCategoryDto.toModel(): OrderCategory = OrderCategory(categoryId, categoryName, groups.map { it.toModel() }) fun OrderGroupDto.toModel(): OrderGroup = OrderGroup(groupId, groupName, parts.map { it.toModel() }) -fun OrderPartDto.toModel(): OrderPart = OrderPart(partId, code, name, quantity) \ No newline at end of file +fun OrderPartDto.toModel(): OrderPart = OrderPart(partId, code, name, quantity, standardCost) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt b/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt index 7b77436..f168398 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/remote/api/OrderApi.kt @@ -5,6 +5,7 @@ import com.sampoom.android.core.model.ApiSuccessResponse import com.sampoom.android.feature.order.data.remote.dto.OrderDto import com.sampoom.android.feature.order.data.remote.dto.OrderListDto import com.sampoom.android.feature.order.data.remote.dto.OrderRequestDto +import com.sampoom.android.feature.order.data.remote.dto.ReceiveStockRequestDto import retrofit2.http.Body import retrofit2.http.GET import retrofit2.http.PATCH @@ -30,10 +31,10 @@ interface OrderApi { suspend fun completeOrder(@Path("orderId") orderId: Long): ApiSuccessResponse // 주문 입고 처리 (대리점) - @PATCH("agency/{agencyId}/orders/{orderId}/receive") + @PATCH("agency/{agencyId}/stock") suspend fun receiveOrder( @Path("agencyId") agencyId: Long, - @Path("orderId") orderId: Long + @Body body: ReceiveStockRequestDto ): ApiSuccessResponse // 주문 상세 조회 diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderDto.kt b/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderDto.kt index 50a9129..6fe631d 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/OrderDto.kt @@ -27,5 +27,6 @@ data class OrderPartDto( val partId: Long, val code: String, val name: String, - val quantity: Long + val quantity: Long, + val standardCost: Long ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/ReceiveStockItemDto.kt b/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/ReceiveStockItemDto.kt new file mode 100644 index 0000000..677fe9e --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/ReceiveStockItemDto.kt @@ -0,0 +1,6 @@ +package com.sampoom.android.feature.order.data.remote.dto + +data class ReceiveStockItemDto( + val partId: Long, + val quantity: Long +) diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/ReceiveStockRequestDto.kt b/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/ReceiveStockRequestDto.kt new file mode 100644 index 0000000..4e658be --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/data/remote/dto/ReceiveStockRequestDto.kt @@ -0,0 +1,5 @@ +package com.sampoom.android.feature.order.data.remote.dto + +data class ReceiveStockRequestDto( + val items: List +) diff --git a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt index 4d10f48..8190a7c 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/data/repository/OrderRepositoryImpl.kt @@ -12,6 +12,8 @@ import com.sampoom.android.feature.order.data.remote.dto.OrderCategoryDto import com.sampoom.android.feature.order.data.remote.dto.OrderGroupDto import com.sampoom.android.feature.order.data.remote.dto.OrderPartDto import com.sampoom.android.feature.order.data.remote.dto.OrderRequestDto +import com.sampoom.android.feature.order.data.remote.dto.ReceiveStockItemDto +import com.sampoom.android.feature.order.data.remote.dto.ReceiveStockRequestDto import com.sampoom.android.feature.order.domain.model.Order import com.sampoom.android.feature.order.domain.repository.OrderRepository import kotlinx.coroutines.flow.Flow @@ -45,7 +47,8 @@ class OrderRepositoryImpl @Inject constructor( partId = part.partId, code = part.code, name = part.name, - quantity = part.quantity + quantity = part.quantity, + standardCost = part.standardCost ) } ) @@ -71,10 +74,15 @@ class OrderRepositoryImpl @Inject constructor( } } - override suspend fun receiveOrder(orderId: Long): Result { + override suspend fun receiveOrder(items: List>): Result { return runCatching { val agencyId = authPreferences.getStoredUser()?.agencyId ?: throw Exception() - val dto = api.receiveOrder(agencyId = agencyId, orderId = orderId) + val body = ReceiveStockRequestDto( + items = items.map { (partId, quantity) -> + ReceiveStockItemDto(partId = partId, quantity = quantity) + } + ) + val dto = api.receiveOrder(agencyId = agencyId, body = body) if (!dto.success) throw Exception(dto.message) } } diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/model/Order.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/model/Order.kt index 90da7f8..5258756 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/model/Order.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/model/Order.kt @@ -25,5 +25,17 @@ data class OrderPart( val partId: Long, val code: String, val name: String, - val quantity: Long + val quantity: Long, + val standardCost: Long ) + +// 파일 하단에 추가 +val OrderPart.subtotal: Long + get() = standardCost * quantity + +val Order.totalCost: Long + get() = items.sumOf { category -> + category.groups.sumOf { group -> + group.parts.sumOf { it.subtotal } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt index f103d37..3ea34cd 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/repository/OrderRepository.kt @@ -10,7 +10,7 @@ interface OrderRepository { fun getOrderList(): Flow> suspend fun createOrder(cartList: CartList): Result suspend fun completeOrder(orderId: Long): Result - suspend fun receiveOrder(orderId: Long): Result + suspend fun receiveOrder(items: List>): Result suspend fun getOrderDetail(orderId: Long): Result suspend fun cancelOrder(orderId: Long): Result } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/ReceiveOrderUseCase.kt b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/ReceiveOrderUseCase.kt index 5a05f03..c8829ce 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/ReceiveOrderUseCase.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/domain/usecase/ReceiveOrderUseCase.kt @@ -6,5 +6,5 @@ import javax.inject.Inject class ReceiveOrderUseCase @Inject constructor( private val repository: OrderRepository ) { - suspend operator fun invoke(orderId: Long): Result = repository.receiveOrder(orderId) + suspend operator fun invoke(items: List>): Result = repository.receiveOrder(items) } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailContent.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailContent.kt index f9d0c00..6109771 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailContent.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailContent.kt @@ -1,12 +1,16 @@ package com.sampoom.android.feature.order.ui +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material.Divider import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.MaterialTheme @@ -16,14 +20,19 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.sampoom.android.R import com.sampoom.android.core.ui.component.StatusChip import com.sampoom.android.core.ui.theme.backgroundCardColor +import com.sampoom.android.core.ui.theme.disableColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.core.util.formatWon import com.sampoom.android.feature.order.domain.model.Order import com.sampoom.android.feature.order.domain.model.OrderPart +import com.sampoom.android.feature.order.domain.model.subtotal +import com.sampoom.android.feature.order.domain.model.totalCost import kotlin.collections.forEach @Composable @@ -59,6 +68,7 @@ fun OrderDetailContent( } } } + item { Spacer(Modifier.height(50.dp).fillMaxWidth()) } } } @@ -99,6 +109,22 @@ private fun OrderInfoCard(order: Order) { StatusChip(status = order.status) } + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 8.dp), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = stringResource(R.string.order_detail_total_amount), + style = MaterialTheme.typography.bodyMedium, + color = textSecondaryColor() + ) + Text( + text = formatWon(order.totalCost), + style = MaterialTheme.typography.bodyMedium + ) + } } } } @@ -109,7 +135,9 @@ private fun OrderInfoRow( value: String ) { Row( - modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp), + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 4.dp), horizontalArrangement = Arrangement.SpaceBetween ) { Text( @@ -154,32 +182,53 @@ private fun OrderPartItem( modifier = Modifier.fillMaxWidth(), colors = CardDefaults.cardColors(containerColor = backgroundCardColor()) ) { - Row( + Column( modifier = Modifier .fillMaxWidth() - .padding(16.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically + .padding(16.dp) ) { - Column( - modifier = Modifier.weight(1F) + Row( + modifier = Modifier + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically ) { - Text( - text = part.name, - style = MaterialTheme.typography.titleMedium, - color = textColor() - ) - Text( - text = part.code, - style = MaterialTheme.typography.bodySmall, - color = textSecondaryColor() - ) + Column( + modifier = Modifier.weight(1F) + ) { + Text( + text = part.name, + style = MaterialTheme.typography.titleMedium, + color = textColor() + ) + Text( + text = part.code, + style = MaterialTheme.typography.bodySmall, + color = textSecondaryColor() + ) + } + + Column(horizontalAlignment = Alignment.End) { + Text( + text = formatWon(part.standardCost), + style = MaterialTheme.typography.bodyMedium + ) + Text( + text = "x ${part.quantity}", + style = MaterialTheme.typography.bodyMedium + ) + } } + Spacer(Modifier.padding(4.dp)) + Divider(Modifier.background(textSecondaryColor())) + Spacer(Modifier.padding(4.dp)) + Text( - text = part.quantity.toString(), + text = formatWon(part.subtotal), style = MaterialTheme.typography.titleMedium, - color = textColor() + textAlign = TextAlign.End, + modifier = Modifier.fillMaxWidth() ) } } diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt index 8c64f2d..fb72131 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailScreen.kt @@ -156,15 +156,6 @@ fun OrderDetailScreen( ) } -// uiState.orderDetail -> { -// EmptyContent( -// message = stringResource(R.string.order_empty_list), -// modifier = Modifier -// .height(200.dp) -// .fillMaxWidth() -// ) -// } - else -> { uiState.orderDetail?.let { order -> OrderDetailContent( diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt index d7122ea..494ed25 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderDetailViewModel.kt @@ -133,8 +133,26 @@ class OrderDetailViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(isProcessing = true) } try { - receiveOrderUseCase(orderId).getOrThrow() // 1단계 - completeOrderUseCase(orderId).getOrThrow() // 2단계 + val order = _uiState.value.orderDetail ?: throw Exception() + val items: List> = order.items.flatMap { category -> + category.groups.flatMap { group -> + group.parts.map { part -> part.partId to part.quantity } + } + } + completeOrderUseCase(orderId) + .onFailure { t -> + val error = t.serverMessageOrNull() ?: (t.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { it.copy(isProcessing = false) } + return@launch + } + receiveOrderUseCase(items) + .onFailure { t -> + val error = t.serverMessageOrNull() ?: (t.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + _uiState.update { it.copy(isProcessing = false) } + return@launch + } messageHandler.showMessage(message = receiveLabel, isError = false) _uiState.update { diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderItem.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderItem.kt new file mode 100644 index 0000000..8614242 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderItem.kt @@ -0,0 +1,92 @@ +package com.sampoom.android.feature.order.ui + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.sampoom.android.R +import com.sampoom.android.core.ui.component.StatusChip +import com.sampoom.android.core.ui.theme.backgroundCardColor +import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.core.util.buildOrderTitle +import com.sampoom.android.core.util.formatDate +import com.sampoom.android.core.util.formatWon +import com.sampoom.android.feature.order.domain.model.Order +import com.sampoom.android.feature.order.domain.model.totalCost + +@Composable +fun OrderItem( + order: Order, + onClick: () -> Unit +) { + Card( + onClick = { onClick() }, + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors(containerColor = backgroundCardColor()) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { + Row( + modifier = Modifier + .fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier + .weight(1f) + ) { + Text( + text = buildOrderTitle(order), + style = MaterialTheme.typography.bodyMedium, + maxLines = 1 + ) + Spacer(Modifier.height(4.dp)) + Text( + text = order.agencyName ?: stringResource(R.string.common_slash), + style = MaterialTheme.typography.labelMedium, + color = textSecondaryColor() + ) + } + + Spacer(Modifier.width(12.dp)) + + Column(horizontalAlignment = Alignment.End) { + Text( + text = order.createdAt?.let { formatDate(it) } + ?: stringResource(R.string.common_slash), + style = MaterialTheme.typography.labelMedium, + color = textSecondaryColor() + ) + Spacer(Modifier.height(6.dp)) + StatusChip(status = order.status) + } + } + + Spacer(Modifier.height(4.dp)) + + Text( + text = formatWon(order.totalCost), + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.End, + modifier = Modifier.fillMaxWidth() + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt index 58d2cc7..1e93c4e 100644 --- a/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/order/ui/OrderListScreen.kt @@ -35,7 +35,6 @@ import androidx.paging.compose.itemKey import com.sampoom.android.R import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent -import com.sampoom.android.core.ui.component.OrderItem import com.sampoom.android.core.ui.theme.FailRed import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.feature.order.domain.model.Order @@ -118,6 +117,20 @@ fun OrderListScreen( } else -> { + // 빈 상태 처리 + if (orderListPaged.loadState.refresh !is LoadState.Loading && orderListPaged.itemCount == 0) { + Box( + modifier = Modifier + .fillMaxSize() + .padding(16.dp), + contentAlignment = Alignment.Center + ) { + EmptyContent( + message = stringResource(R.string.order_empty_list), + modifier = Modifier.height(200.dp) + ) + } + } LazyColumn( state = listState, modifier = Modifier @@ -168,23 +181,6 @@ fun OrderListScreen( } } - // 빈 상태 처리 - if (orderListPaged.loadState.refresh !is LoadState.Loading && orderListPaged.itemCount == 0) { - item { - Box( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), - contentAlignment = Alignment.Center - ) { - EmptyContent( - message = stringResource(R.string.order_empty_list), - modifier = Modifier.height(200.dp) - ) - } - } - } - item { Spacer(Modifier.height(100.dp)) } } } diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/mapper/OutboundMappers.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/mapper/OutboundMappers.kt index 1f38519..ab25cfa 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/data/mapper/OutboundMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/mapper/OutboundMappers.kt @@ -9,4 +9,4 @@ import com.sampoom.android.feature.outbound.domain.model.OutboundPart fun OutboundDto.toModel(): Outbound = Outbound(categoryId, categoryName, groups.map { it.toModel() }) fun OutboundGroupDto.toModel(): OutboundGroup = OutboundGroup(groupId, groupName, parts.map { it.toModel() }) -fun OutboundPartDto.toModel(): OutboundPart = OutboundPart(outboundId, partId, code, name, quantity) \ No newline at end of file +fun OutboundPartDto.toModel(): OutboundPart = OutboundPart(outboundId, partId, code, name, quantity, standardCost) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/OutboundDto.kt b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/OutboundDto.kt index 462b63e..5c7174b 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/OutboundDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/data/remote/dto/OutboundDto.kt @@ -17,5 +17,6 @@ data class OutboundPartDto( val partId: Long, val code: String, val name: String, - val quantity: Long + val quantity: Long, + val standardCost: Long ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/domain/model/Outbound.kt b/app/src/main/java/com/sampoom/android/feature/outbound/domain/model/Outbound.kt index 1033bfc..2610cfe 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/domain/model/Outbound.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/domain/model/Outbound.kt @@ -17,5 +17,10 @@ data class OutboundPart( val partId: Long, val code: String, val name: String, - val quantity: Long -) \ No newline at end of file + val quantity: Long, + val standardCost: Long +) + +// 품목 합계(단가 x 수량) +val OutboundPart.subtotal: Long + get() = standardCost * quantity \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt index 2d681ee..dabc090 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListScreen.kt @@ -49,7 +49,10 @@ import com.sampoom.android.core.ui.theme.FailRed import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.core.util.formatWon +import com.sampoom.android.feature.cart.domain.model.subtotal import com.sampoom.android.feature.outbound.domain.model.OutboundPart +import com.sampoom.android.feature.outbound.domain.model.subtotal @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -198,7 +201,7 @@ fun OutboundListScreen( variant = ButtonVariant.Error, size = ButtonSize.Large, onClick = { showConfirmDialog = true } - ) { Text(stringResource(R.string.outbound_order_parts)) } + ) { Text("${formatWon(uiState.totalCost)} ${stringResource(R.string.outbound_order_parts)}") } } } } @@ -370,30 +373,6 @@ private fun OutboundPartItem( style = MaterialTheme.typography.titleMedium, modifier = Modifier.padding(horizontal = 24.dp) ) -// OutlinedTextField( -// value = part.quantity.toString(), -// onValueChange = { newValue -> -// when { -// newValue.isEmpty() -> onEvent(OutboundListUiEvent.UpdateQuantity(part.outboundId, 1)) -// newValue == "0" -> onEvent(OutboundListUiEvent.UpdateQuantity(part.outboundId, 1)) -// else -> { -// val newQuantity = newValue.toLongOrNull() -// if (newQuantity != null && newQuantity > 0) onEvent(OutboundListUiEvent.UpdateQuantity(part.outboundId, newQuantity)) -// else onEvent(OutboundListUiEvent.UpdateQuantity(part.outboundId, 1)) -// } -// } -// }, -// modifier = Modifier.width(100.dp), -// singleLine = true, -// keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), -// textStyle = MaterialTheme.typography.titleMedium.copy(textAlign = TextAlign.Center), -// colors = OutlinedTextFieldDefaults.colors( -// focusedBorderColor = Color.Transparent, -// unfocusedBorderColor = Color.Transparent, -// disabledBorderColor = Color.Transparent, -// errorBorderColor = Color.Transparent -// ) -// ) CommonButton( variant = ButtonVariant.Neutral, size = ButtonSize.Large, @@ -414,6 +393,20 @@ private fun OutboundPartItem( } } } + val subtotal = part.subtotal + + Spacer(Modifier.height(8.dp)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End, + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + text = formatWon(subtotal), + style = MaterialTheme.typography.titleLarge + ) + } } } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt index 3a49bc7..27758c9 100644 --- a/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/outbound/ui/OutboundListUiState.kt @@ -10,4 +10,13 @@ data class OutboundListUiState( val isUpdating: Boolean = false, val isDeleting: Boolean = false, val isOrderSuccess: Boolean = false -) \ No newline at end of file +) { + val totalCost: Long + get() = outboundList.sumOf { category -> + category.groups.sumOf { group -> + group.parts.sumOf { part -> + part.standardCost * part.quantity + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt b/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt index 998e90f..777918a 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/mapper/PartMappers.kt @@ -12,7 +12,7 @@ import com.sampoom.android.feature.part.domain.model.SearchResult fun CategoryDto.toModel(): Category = Category(id, code, name) fun GroupDto.toModel(): Group = Group(id, code, name, categoryId) -fun PartDto.toModel(): Part = Part(partId, code, name, quantity) +fun PartDto.toModel(): Part = Part(partId, code, name, quantity, standardCost) fun SearchCategoryDto.toModel(): List { return groups.flatMap { group -> diff --git a/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/PartDto.kt b/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/PartDto.kt index 41872f7..5af2766 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/PartDto.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/data/remote/dto/PartDto.kt @@ -4,5 +4,6 @@ data class PartDto( val partId: Long, val code: String, val name: String, - val quantity: Long + val quantity: Long, + val standardCost: Long ) diff --git a/app/src/main/java/com/sampoom/android/feature/part/domain/model/Part.kt b/app/src/main/java/com/sampoom/android/feature/part/domain/model/Part.kt index 019b63b..4899956 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/domain/model/Part.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/domain/model/Part.kt @@ -4,5 +4,6 @@ data class Part( val partId: Long, val code: String, val name: String, - val quantity: Long + val quantity: Long, + val standardCost: Long ) diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt index 6ee3f3f..2afbcfa 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartDetailBottomSheet.kt @@ -27,6 +27,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp @@ -38,6 +39,7 @@ import com.sampoom.android.core.ui.component.ButtonVariant import com.sampoom.android.core.ui.component.CommonButton import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.core.util.formatWon import com.sampoom.android.feature.part.domain.model.Part @Composable @@ -114,11 +116,24 @@ fun PartDetailBottomSheet( modifier = Modifier.fillMaxWidth() ) } - Text( - stringResource(R.string.part_current_quantity) + - part.quantity.toString() + - stringResource(R.string.common_EA) - ) + + Column( + horizontalAlignment = Alignment.End + ) { + Text( + text = formatWon(part.standardCost), + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold, + textAlign = TextAlign.End, + color = textColor() + ) + Text( + stringResource(R.string.part_current_quantity) + + part.quantity.toString() + + stringResource(R.string.common_EA) + ) + } + } Spacer(Modifier.height(16.dp)) diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt index 2d16093..cadb1ae 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartListScreen.kt @@ -50,6 +50,7 @@ import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.disableColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.core.util.formatWon import com.sampoom.android.feature.part.domain.model.Part import kotlinx.coroutines.launch @@ -238,11 +239,18 @@ private fun PartListItemCard( ) } - Text( - text = part.quantity.toString(), - color = textColor(), - style = MaterialTheme.typography.titleMedium - ) + Column(horizontalAlignment = Alignment.End) { + Text( + text = formatWon(part.standardCost), + color = textColor(), + style = MaterialTheme.typography.titleMedium + ) + Text( + text = part.quantity.toString(), + color = textColor(), + style = MaterialTheme.typography.titleMedium + ) + } Icon( painterResource(R.drawable.chevron_right), diff --git a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt index 7c10cf2..2791fed 100644 --- a/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/part/ui/PartScreen.kt @@ -63,6 +63,7 @@ import com.sampoom.android.core.ui.theme.backgroundColor import com.sampoom.android.core.ui.theme.disableColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor +import com.sampoom.android.core.util.formatWon import com.sampoom.android.feature.part.domain.model.Category import com.sampoom.android.feature.part.domain.model.Group import com.sampoom.android.feature.part.domain.model.Part @@ -579,6 +580,8 @@ fun SearchResultsList( else -> {} } } + + item { Spacer(Modifier.height(50.dp))} } } @@ -627,11 +630,19 @@ private fun SearchPartItem( ) } - Text( - text = "${part.quantity}", - style = MaterialTheme.typography.bodyMedium, - color = textColor() - ) + Column(horizontalAlignment = Alignment.End) { + Text( + text = formatWon(part.standardCost), + style = MaterialTheme.typography.titleMedium, + color = textColor() + ) + + Text( + text = "${part.quantity}", + style = MaterialTheme.typography.bodyMedium, + color = textColor() + ) + } Icon( painterResource(R.drawable.chevron_right), diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8aa7007..29599f8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -81,7 +81,7 @@ 출고 처리하시겠습니까? 출고목록을 비우시겠습니까? 출고 처리되었습니다 - 부품 출고처리 + 출고처리 장바구니 @@ -92,7 +92,7 @@ 장바구니 목록의 상품을 주문하시겠습니까? 장바구니를 비우시겠습니까? 주문이 완료되었습니다 - 부품 주문 + 주문하기 주문관리 @@ -109,6 +109,7 @@ 입고처리 입고 처리하시겠습니까? 입고 처리되었습니다 + 총 가격 대기중 From 4f326093aca041429032d019f71434dcfc4c44dc Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Fri, 7 Nov 2025 00:16:54 +0900 Subject: [PATCH 86/88] =?UTF-8?q?[FEAT]=20=EB=8C=80=EC=8B=9C=EB=B3=B4?= =?UTF-8?q?=EB=93=9C=20api=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/data/local/database/.gitkeep | 0 .../dashboard/data/local/preferences/.gitkeep | 0 .../feature/dashboard/data/mapper/.gitkeep | 0 .../dashboard/data/mapper/DashboardMappers.kt | 9 ++ .../dashboard/data/remote/api/.gitkeep | 0 .../dashboard/data/remote/api/DashboardApi.kt | 17 +++ .../dashboard/data/remote/dto/.gitkeep | 0 .../data/remote/dto/DashboardResponseDto.kt | 8 ++ .../remote/dto/WeeklySummaryResponseDto.kt | 7 + .../dashboard/data/repository/.gitkeep | 0 .../repository/DashboardRepositoryImpl.kt | 30 +++++ .../android/feature/dashboard/di/.gitkeep | 0 .../feature/dashboard/di/DashboardModules.kt | 26 ++++ .../feature/dashboard/domain/model/.gitkeep | 0 .../dashboard/domain/model/Dashboard.kt | 8 ++ .../dashboard/domain/model/WeeklySummary.kt | 7 + .../dashboard/domain/repository/.gitkeep | 0 .../domain/repository/DashboardRepository.kt | 9 ++ .../feature/dashboard/domain/usecase/.gitkeep | 0 .../domain/usecase/GetDashboardUseCase.kt | 11 ++ .../domain/usecase/WeeklySummaryUseCase.kt | 11 ++ .../feature/dashboard/ui/DashboardScreen.kt | 120 ++++++++++++++---- .../feature/dashboard/ui/DashboardUiState.kt | 6 +- .../dashboard/ui/DashboardViewModel.kt | 105 ++++++++++----- app/src/main/res/drawable/block.xml | 9 ++ app/src/main/res/drawable/car.xml | 9 ++ app/src/main/res/values/strings.xml | 9 +- 27 files changed, 344 insertions(+), 57 deletions(-) delete mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/data/local/database/.gitkeep delete mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/data/local/preferences/.gitkeep delete mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/data/mapper/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/data/mapper/DashboardMappers.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/api/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/api/DashboardApi.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/dto/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/dto/DashboardResponseDto.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/dto/WeeklySummaryResponseDto.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/data/repository/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/data/repository/DashboardRepositoryImpl.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/di/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/di/DashboardModules.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/domain/model/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/domain/model/Dashboard.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/domain/model/WeeklySummary.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/domain/repository/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/domain/repository/DashboardRepository.kt delete mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/domain/usecase/.gitkeep create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/domain/usecase/GetDashboardUseCase.kt create mode 100644 app/src/main/java/com/sampoom/android/feature/dashboard/domain/usecase/WeeklySummaryUseCase.kt create mode 100644 app/src/main/res/drawable/block.xml create mode 100644 app/src/main/res/drawable/car.xml diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/data/local/database/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/data/local/database/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/data/local/preferences/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/data/local/preferences/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/data/mapper/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/data/mapper/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/data/mapper/DashboardMappers.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/data/mapper/DashboardMappers.kt new file mode 100644 index 0000000..830b38e --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/data/mapper/DashboardMappers.kt @@ -0,0 +1,9 @@ +package com.sampoom.android.feature.dashboard.data.mapper + +import com.sampoom.android.feature.dashboard.data.remote.dto.DashboardResponseDto +import com.sampoom.android.feature.dashboard.data.remote.dto.WeeklySummaryResponseDto +import com.sampoom.android.feature.dashboard.domain.model.Dashboard +import com.sampoom.android.feature.dashboard.domain.model.WeeklySummary + +fun DashboardResponseDto.toModel(): Dashboard = Dashboard(totalParts, outOfStockParts, lowStockParts, totalQuantity) +fun WeeklySummaryResponseDto.toModel(): WeeklySummary = WeeklySummary(inStockParts, outStockParts, weekPeriod) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/api/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/api/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/api/DashboardApi.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/api/DashboardApi.kt new file mode 100644 index 0000000..fde49dc --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/api/DashboardApi.kt @@ -0,0 +1,17 @@ +package com.sampoom.android.feature.dashboard.data.remote.api + +import com.sampoom.android.core.model.ApiResponse +import com.sampoom.android.feature.dashboard.data.remote.dto.DashboardResponseDto +import com.sampoom.android.feature.dashboard.data.remote.dto.WeeklySummaryResponseDto +import retrofit2.http.GET +import retrofit2.http.Path + +interface DashboardApi { + // 대시보드 조회 + @GET("agency/{agencyId}/dashboard") + suspend fun getDashboard(@Path("agencyId") agencyId: Long): ApiResponse + + // 주간 히스토리 조회 + @GET("agency/{agencyId}/weekly-summary") + suspend fun getWeeklySummary(@Path("agencyId") agencyId: Long): ApiResponse +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/dto/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/dto/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/dto/DashboardResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/dto/DashboardResponseDto.kt new file mode 100644 index 0000000..54c0643 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/dto/DashboardResponseDto.kt @@ -0,0 +1,8 @@ +package com.sampoom.android.feature.dashboard.data.remote.dto + +data class DashboardResponseDto( + val totalParts: Long, + val outOfStockParts: Long, + val lowStockParts: Long, + val totalQuantity: Long +) diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/dto/WeeklySummaryResponseDto.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/dto/WeeklySummaryResponseDto.kt new file mode 100644 index 0000000..2b4d4b9 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/data/remote/dto/WeeklySummaryResponseDto.kt @@ -0,0 +1,7 @@ +package com.sampoom.android.feature.dashboard.data.remote.dto + +data class WeeklySummaryResponseDto( + val inStockParts: Long, + val outStockParts: Long, + val weekPeriod: String +) diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/data/repository/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/data/repository/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/data/repository/DashboardRepositoryImpl.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/data/repository/DashboardRepositoryImpl.kt new file mode 100644 index 0000000..5f0f1d9 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/data/repository/DashboardRepositoryImpl.kt @@ -0,0 +1,30 @@ +package com.sampoom.android.feature.dashboard.data.repository + +import com.sampoom.android.core.preferences.AuthPreferences +import com.sampoom.android.feature.dashboard.data.mapper.toModel +import com.sampoom.android.feature.dashboard.data.remote.api.DashboardApi +import com.sampoom.android.feature.dashboard.domain.model.Dashboard +import com.sampoom.android.feature.dashboard.domain.model.WeeklySummary +import com.sampoom.android.feature.dashboard.domain.repository.DashboardRepository +import javax.inject.Inject + +class DashboardRepositoryImpl @Inject constructor( + private val api: DashboardApi, + private val authPreferences: AuthPreferences +) : DashboardRepository { + override suspend fun getDashboard(): Result { + return runCatching { + val agencyId = authPreferences.getStoredUser()?.agencyId ?: throw Exception() + val dto = api.getDashboard(agencyId) + dto.data.toModel() + } + } + + override suspend fun getWeeklySummary(): Result { + return runCatching { + val agencyId = authPreferences.getStoredUser()?.agencyId ?: throw Exception() + val dto = api.getWeeklySummary(agencyId) + dto.data.toModel() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/di/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/di/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/di/DashboardModules.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/di/DashboardModules.kt new file mode 100644 index 0000000..597d466 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/di/DashboardModules.kt @@ -0,0 +1,26 @@ +package com.sampoom.android.feature.dashboard.di + +import com.sampoom.android.feature.dashboard.data.remote.api.DashboardApi +import com.sampoom.android.feature.dashboard.data.repository.DashboardRepositoryImpl +import com.sampoom.android.feature.dashboard.domain.repository.DashboardRepository +import dagger.Binds +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import retrofit2.Retrofit +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +abstract class DashboardBinModule { + @Binds @Singleton + abstract fun bindDashboardRepository(impl: DashboardRepositoryImpl): DashboardRepository +} + +@Module +@InstallIn(SingletonComponent::class) +object DashboardModule { + @Provides @Singleton + fun provideDashboardApi(retrofit: Retrofit): DashboardApi = retrofit.create(DashboardApi::class.java) +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/domain/model/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/domain/model/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/domain/model/Dashboard.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/domain/model/Dashboard.kt new file mode 100644 index 0000000..12c75bd --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/domain/model/Dashboard.kt @@ -0,0 +1,8 @@ +package com.sampoom.android.feature.dashboard.domain.model + +data class Dashboard( + val totalParts: Long, + val outOfStockParts: Long, + val lowStockParts: Long, + val totalQuantity: Long +) diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/domain/model/WeeklySummary.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/domain/model/WeeklySummary.kt new file mode 100644 index 0000000..e2b38ba --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/domain/model/WeeklySummary.kt @@ -0,0 +1,7 @@ +package com.sampoom.android.feature.dashboard.domain.model + +data class WeeklySummary( + val inStockParts: Long, + val outStockParts: Long, + val weekPeriod: String +) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/domain/repository/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/domain/repository/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/domain/repository/DashboardRepository.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/domain/repository/DashboardRepository.kt new file mode 100644 index 0000000..f26b53a --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/domain/repository/DashboardRepository.kt @@ -0,0 +1,9 @@ +package com.sampoom.android.feature.dashboard.domain.repository + +import com.sampoom.android.feature.dashboard.domain.model.Dashboard +import com.sampoom.android.feature.dashboard.domain.model.WeeklySummary + +interface DashboardRepository { + suspend fun getDashboard(): Result + suspend fun getWeeklySummary(): Result +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/domain/usecase/.gitkeep b/app/src/main/java/com/sampoom/android/feature/dashboard/domain/usecase/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/domain/usecase/GetDashboardUseCase.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/domain/usecase/GetDashboardUseCase.kt new file mode 100644 index 0000000..f19af0f --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/domain/usecase/GetDashboardUseCase.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.dashboard.domain.usecase + +import com.sampoom.android.feature.dashboard.domain.model.Dashboard +import com.sampoom.android.feature.dashboard.domain.repository.DashboardRepository +import javax.inject.Inject + +class GetDashboardUseCase @Inject constructor( + private val repository: DashboardRepository +) { + suspend operator fun invoke(): Result = repository.getDashboard() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/domain/usecase/WeeklySummaryUseCase.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/domain/usecase/WeeklySummaryUseCase.kt new file mode 100644 index 0000000..51620c6 --- /dev/null +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/domain/usecase/WeeklySummaryUseCase.kt @@ -0,0 +1,11 @@ +package com.sampoom.android.feature.dashboard.domain.usecase + +import com.sampoom.android.feature.dashboard.domain.model.WeeklySummary +import com.sampoom.android.feature.dashboard.domain.repository.DashboardRepository +import javax.inject.Inject + +class WeeklySummaryUseCase @Inject constructor( + private val repository: DashboardRepository +) { + suspend operator fun invoke(): Result = repository.getWeeklySummary() +} \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt index 096f645..7b34360 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt @@ -1,5 +1,6 @@ package com.sampoom.android.feature.dashboard.ui +import android.R.attr.onClick import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -50,12 +51,16 @@ import com.sampoom.android.R import com.sampoom.android.core.model.UserPosition import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent +import com.sampoom.android.core.ui.theme.FailRed import com.sampoom.android.feature.order.ui.OrderItem import com.sampoom.android.core.ui.theme.Main500 +import com.sampoom.android.core.ui.theme.SuccessGreen import com.sampoom.android.core.ui.theme.backgroundCardColor import com.sampoom.android.core.ui.theme.textColor import com.sampoom.android.core.ui.theme.textSecondaryColor import com.sampoom.android.feature.auth.domain.model.User +import com.sampoom.android.feature.dashboard.domain.model.Dashboard +import com.sampoom.android.feature.dashboard.domain.model.WeeklySummary import com.sampoom.android.feature.order.domain.model.Order @Composable @@ -159,11 +164,10 @@ fun DashboardScreen( ) { item { TitleSection(user) } - item { ButtonSection(isManager) } + item { ButtonSection(isManager, uiState.dashboard) } item { OrderListSection( - viewModel = viewModel, orderListPaged = orderListPaged, onNavigateOrderDetail = { order -> onNavigateOrderDetail(order) @@ -174,6 +178,12 @@ fun DashboardScreen( ) } + item { Spacer(Modifier.height(32.dp)) } + + item { + WeeklySummarySection(modifier = Modifier, weeklySummary = uiState.weeklySummary) + } + item { Spacer(Modifier.height(100.dp)) } } } @@ -225,7 +235,8 @@ fun TitleSection( @Composable fun ButtonSection( - isManager: Boolean + isManager: Boolean, + dashboard: Dashboard? ) { Column( modifier = Modifier @@ -248,48 +259,48 @@ fun ButtonSection( ) } - // 보유 부품, 진행중 주문 + // 총 부품, 품절 부품 Row( horizontalArrangement = Arrangement.spacedBy(16.dp) ) { ButtonCard( modifier = Modifier.weight(1f), - painter = painterResource(R.drawable.parts), - painterDescription = stringResource(R.string.dashboard_parts_on_hand), - text = 1234.toString(), // TODO : API 연동 - subText = stringResource(R.string.dashboard_parts_on_hand), + painter = painterResource(R.drawable.car), + painterDescription = stringResource(R.string.dashboard_parts_all), + text = (dashboard?.totalParts ?: 0L).toString(), + subText = stringResource(R.string.dashboard_parts_all), onClick = { } ) ButtonCard( modifier = Modifier.weight(1f), - painter = painterResource(R.drawable.orders), - painterDescription = stringResource(R.string.dashboard_parts_in_progress), - text = 23.toString(), // TODO : API 연동 - subText = stringResource(R.string.dashboard_parts_in_progress), + painter = painterResource(R.drawable.block), + painterDescription = stringResource(R.string.dashboard_parts_out_of_stock), + text = (dashboard?.outOfStockParts ?: 0L).toString(), + subText = stringResource(R.string.dashboard_parts_out_of_stock), onClick = { } ) } - // 부족 부품, 주문 금액 + // 부족 부품, 보유 부품 Row( horizontalArrangement = Arrangement.spacedBy(16.dp) ) { ButtonCard( modifier = Modifier.weight(1f), painter = painterResource(R.drawable.warning), - painterDescription = stringResource(R.string.dashboard_shortage_of_parts), - text = 19.toString(), // TODO : API 연동 - subText = stringResource(R.string.dashboard_shortage_of_parts), + painterDescription = stringResource(R.string.dashboard_parts_low_stock), + text = (dashboard?.lowStockParts ?: 0L).toString(), + subText = stringResource(R.string.dashboard_parts_low_stock), onClick = { } ) ButtonCard( modifier = Modifier.weight(1f), - painter = painterResource(R.drawable.money), - painterDescription = stringResource(R.string.dashboard_order_amount), - text = 4123200.toString(), // TODO : API 연동 - subText = stringResource(R.string.dashboard_order_amount), + painter = painterResource(R.drawable.parts), + painterDescription = stringResource(R.string.dashboard_parts_on_hand), + text = (dashboard?.totalQuantity ?: 0L).toString(), + subText = stringResource(R.string.dashboard_parts_on_hand), onClick = { } ) } @@ -349,12 +360,10 @@ fun ButtonCard( @Composable fun OrderListSection( - viewModel: DashboardViewModel, orderListPaged: LazyPagingItems, onNavigateOrderDetail: (Order) -> Unit, onNavigationOrder: () -> Unit ) { - Column( modifier = Modifier.fillMaxWidth() ) { @@ -441,4 +450,71 @@ fun OrderListSection( } } } +} + +@Composable +fun WeeklySummarySection( + modifier: Modifier, + weeklySummary: WeeklySummary? +) { + Card( + modifier = modifier + .fillMaxWidth(), + colors = CardDefaults.cardColors( + containerColor = backgroundCardColor() + ), + onClick = { }, + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { + Text( + text = stringResource(R.string.dashboard_weekly_summary_title), + style = MaterialTheme.typography.headlineMedium, + fontWeight = FontWeight.Bold, + color = textColor() + ) + + Row( + modifier = Modifier.fillMaxWidth() + ) { + Column( + modifier = Modifier.weight(1f), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = (weeklySummary?.inStockParts ?: 0L).toString(), + style = MaterialTheme.typography.headlineMedium, + fontWeight = FontWeight.Bold, + color = SuccessGreen + ) + Text( + text = stringResource(R.string.dashboard_weekly_summary_in_stock), + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.Light, + color = textSecondaryColor() + ) + } + Column( + modifier = Modifier.weight(1f), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = (weeklySummary?.outStockParts ?: 0L).toString(), + style = MaterialTheme.typography.headlineMedium, + fontWeight = FontWeight.Bold, + color = FailRed + ) + Text( + text = stringResource(R.string.dashboard_weekly_summary_out_stock), + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.Light, + color = textSecondaryColor() + ) + } + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardUiState.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardUiState.kt index 91da8e1..e6583a9 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardUiState.kt @@ -1,9 +1,13 @@ package com.sampoom.android.feature.dashboard.ui +import com.sampoom.android.feature.dashboard.domain.model.Dashboard +import com.sampoom.android.feature.dashboard.domain.model.WeeklySummary import com.sampoom.android.feature.order.domain.model.Order data class DashboardUiState( val orderList: List = emptyList(), + val dashboard: Dashboard? = null, + val weeklySummary: WeeklySummary? = null, val dashboardLoading: Boolean = false, - val dashboardError: String? = null, + val dashboardError: String? = null ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt index 768d537..7afa497 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt @@ -4,9 +4,12 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.paging.PagingData import androidx.paging.cachedIn +import com.sampoom.android.core.network.serverMessageOrNull import com.sampoom.android.core.util.GlobalMessageHandler import com.sampoom.android.feature.auth.domain.model.User import com.sampoom.android.feature.auth.domain.usecase.GetStoredUserUseCase +import com.sampoom.android.feature.dashboard.domain.usecase.GetDashboardUseCase +import com.sampoom.android.feature.dashboard.domain.usecase.WeeklySummaryUseCase import com.sampoom.android.feature.order.domain.model.Order import com.sampoom.android.feature.order.domain.usecase.GetOrderUseCase import dagger.hilt.android.lifecycle.HiltViewModel @@ -14,6 +17,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject @@ -21,7 +25,9 @@ import javax.inject.Inject class DashboardViewModel @Inject constructor( private val messageHandler: GlobalMessageHandler, private val getOrderListUseCase: GetOrderUseCase, - private val getStoredUserUseCase: GetStoredUserUseCase + private val getStoredUserUseCase: GetStoredUserUseCase, + private val getDashboardUseCase: GetDashboardUseCase, + private val getWeeklySummaryUseCase: WeeklySummaryUseCase ): ViewModel() { private companion object { @@ -38,13 +44,14 @@ class DashboardViewModel @Inject constructor( .cachedIn(viewModelScope) private var errorLabel: String = "" - private var loadJob: Job? = null fun bindLabel(error: String) { errorLabel = error } init { + loadDashboard() + loadWeeklySummary() viewModelScope.launch { _user.value = getStoredUserUseCase() } @@ -52,36 +59,72 @@ class DashboardViewModel @Inject constructor( fun onEvent(event: DashboardUiEvent) { when (event) { - is DashboardUiEvent.LoadDashboard -> {}//loadOrderList() - is DashboardUiEvent.RetryDashboard -> {}//loadOrderList() + is DashboardUiEvent.LoadDashboard -> { + loadDashboard() + loadWeeklySummary() + } + is DashboardUiEvent.RetryDashboard -> { + loadDashboard() + loadWeeklySummary() + } } } -// private fun loadOrderList() { -// if (loadJob?.isActive == true) return -// loadJob = viewModelScope.launch { -// _uiState.update { it.copy(dashboardLoading = true, dashboardError = null) } -// -// getOrderListUseCase() -// .onSuccess { orderList -> -// _uiState.update { -// it.copy( -// orderList = orderList.items.take(5), -// dashboardLoading = false, -// dashboardError = null -// ) -// } -// } -// .onFailure { throwable -> -// val backendMessage = throwable.serverMessageOrNull() -// _uiState.update { -// it.copy( -// dashboardLoading = false, -// dashboardError = backendMessage ?: (throwable.message ?: errorLabel) -// ) -// } -// } -// Log.d(TAG, "submit: ${_uiState.value}") -// } -// } + private fun loadDashboard() { + viewModelScope.launch { + _uiState.update { it.copy(dashboardLoading = true, dashboardError = null) } + + getDashboardUseCase() + .onSuccess { dashboard -> + _uiState.update { + it.copy( + dashboard = dashboard, + dashboardLoading = false, + dashboardError = null + ) + } + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + + _uiState.update { + it.copy( + dashboardLoading = false, + dashboardError = error + ) + } + } + } + } + + private fun loadWeeklySummary() { + viewModelScope.launch { + _uiState.update { it.copy(dashboardLoading = true, dashboardError = null) } + + getWeeklySummaryUseCase() + .onSuccess { weeklySummary -> + _uiState.update { + it.copy( + weeklySummary = weeklySummary, + dashboardLoading = false, + dashboardError = null + ) + } + } + .onFailure { throwable -> + val backendMessage = throwable.serverMessageOrNull() + val error = backendMessage ?: (throwable.message ?: errorLabel) + messageHandler.showMessage(message = error, isError = true) + + _uiState.update { + it.copy( + dashboardLoading = false, + dashboardError = error + ) + } + } + } + } } \ No newline at end of file diff --git a/app/src/main/res/drawable/block.xml b/app/src/main/res/drawable/block.xml new file mode 100644 index 0000000..2ce7fd6 --- /dev/null +++ b/app/src/main/res/drawable/block.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/car.xml b/app/src/main/res/drawable/car.xml new file mode 100644 index 0000000..f89b46b --- /dev/null +++ b/app/src/main/res/drawable/car.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 29599f8..1001f02 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -44,11 +44,14 @@ 님! 오늘도 효율적인 재고 관리를 시작해보세요. 직원 관리 + 총 부품 + 품절 부품 + 부족 부품 보유 부품 - 진행중 부품 - 부족 부품 - 주문 금액 최근 주문 + 이번 주 요약 + 입고 부품 + 출고 부품 부품조회 From 8cfecd36014501ed644467d05581572a67b50380 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Fri, 7 Nov 2025 13:38:16 +0900 Subject: [PATCH 87/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=9D=BC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/dashboard/ui/DashboardScreen.kt | 3 +-- .../android/feature/dashboard/ui/DashboardUiState.kt | 4 +++- .../android/feature/dashboard/ui/DashboardViewModel.kt | 10 +++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt index 7b34360..ffb7936 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt @@ -1,6 +1,5 @@ package com.sampoom.android.feature.dashboard.ui -import android.R.attr.onClick import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -52,7 +51,6 @@ import com.sampoom.android.core.model.UserPosition import com.sampoom.android.core.ui.component.EmptyContent import com.sampoom.android.core.ui.component.ErrorContent import com.sampoom.android.core.ui.theme.FailRed -import com.sampoom.android.feature.order.ui.OrderItem import com.sampoom.android.core.ui.theme.Main500 import com.sampoom.android.core.ui.theme.SuccessGreen import com.sampoom.android.core.ui.theme.backgroundCardColor @@ -62,6 +60,7 @@ import com.sampoom.android.feature.auth.domain.model.User import com.sampoom.android.feature.dashboard.domain.model.Dashboard import com.sampoom.android.feature.dashboard.domain.model.WeeklySummary import com.sampoom.android.feature.order.domain.model.Order +import com.sampoom.android.feature.order.ui.OrderItem @Composable fun DashboardScreen( diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardUiState.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardUiState.kt index e6583a9..4986b22 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardUiState.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardUiState.kt @@ -9,5 +9,7 @@ data class DashboardUiState( val dashboard: Dashboard? = null, val weeklySummary: WeeklySummary? = null, val dashboardLoading: Boolean = false, - val dashboardError: String? = null + val dashboardError: String? = null, + val weeklySummaryLoading: Boolean = false, + val weeklySummaryError: String? = null, ) \ No newline at end of file diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt index 7afa497..f0e6e4e 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardViewModel.kt @@ -101,15 +101,15 @@ class DashboardViewModel @Inject constructor( private fun loadWeeklySummary() { viewModelScope.launch { - _uiState.update { it.copy(dashboardLoading = true, dashboardError = null) } + _uiState.update { it.copy(weeklySummaryLoading = true, weeklySummaryError = null) } getWeeklySummaryUseCase() .onSuccess { weeklySummary -> _uiState.update { it.copy( weeklySummary = weeklySummary, - dashboardLoading = false, - dashboardError = null + weeklySummaryLoading = false, + weeklySummaryError = null ) } } @@ -120,8 +120,8 @@ class DashboardViewModel @Inject constructor( _uiState.update { it.copy( - dashboardLoading = false, - dashboardError = error + weeklySummaryLoading = false, + weeklySummaryError = error ) } } From c050c319d06b2d8704a3ec96118ad9c4d4f4b453 Mon Sep 17 00:00:00 2001 From: Sangyoon Date: Fri, 7 Nov 2025 14:25:01 +0900 Subject: [PATCH 88/88] =?UTF-8?q?[FIX]=20=EC=BD=94=EB=93=9C=20=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=9D=BC=EB=B7=B0=20=EC=82=AC=ED=95=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/dashboard/ui/DashboardScreen.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt index ffb7936..4971cc0 100644 --- a/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt +++ b/app/src/main/java/com/sampoom/android/feature/dashboard/ui/DashboardScreen.kt @@ -266,7 +266,7 @@ fun ButtonSection( modifier = Modifier.weight(1f), painter = painterResource(R.drawable.car), painterDescription = stringResource(R.string.dashboard_parts_all), - text = (dashboard?.totalParts ?: 0L).toString(), + text = (dashboard?.totalParts ?: stringResource(R.string.common_slash)).toString(), subText = stringResource(R.string.dashboard_parts_all), onClick = { } ) @@ -275,7 +275,7 @@ fun ButtonSection( modifier = Modifier.weight(1f), painter = painterResource(R.drawable.block), painterDescription = stringResource(R.string.dashboard_parts_out_of_stock), - text = (dashboard?.outOfStockParts ?: 0L).toString(), + text = (dashboard?.outOfStockParts ?: stringResource(R.string.common_slash)).toString(), subText = stringResource(R.string.dashboard_parts_out_of_stock), onClick = { } ) @@ -289,7 +289,7 @@ fun ButtonSection( modifier = Modifier.weight(1f), painter = painterResource(R.drawable.warning), painterDescription = stringResource(R.string.dashboard_parts_low_stock), - text = (dashboard?.lowStockParts ?: 0L).toString(), + text = (dashboard?.lowStockParts ?: stringResource(R.string.common_slash)).toString(), subText = stringResource(R.string.dashboard_parts_low_stock), onClick = { } ) @@ -298,7 +298,7 @@ fun ButtonSection( modifier = Modifier.weight(1f), painter = painterResource(R.drawable.parts), painterDescription = stringResource(R.string.dashboard_parts_on_hand), - text = (dashboard?.totalQuantity ?: 0L).toString(), + text = (dashboard?.totalQuantity ?: stringResource(R.string.common_slash)).toString(), subText = stringResource(R.string.dashboard_parts_on_hand), onClick = { } ) @@ -484,7 +484,7 @@ fun WeeklySummarySection( horizontalAlignment = Alignment.CenterHorizontally ) { Text( - text = (weeklySummary?.inStockParts ?: 0L).toString(), + text = (weeklySummary?.inStockParts ?: stringResource(R.string.common_slash)).toString(), style = MaterialTheme.typography.headlineMedium, fontWeight = FontWeight.Bold, color = SuccessGreen @@ -501,7 +501,7 @@ fun WeeklySummarySection( horizontalAlignment = Alignment.CenterHorizontally ) { Text( - text = (weeklySummary?.outStockParts ?: 0L).toString(), + text = (weeklySummary?.outStockParts ?: stringResource(R.string.common_slash)).toString(), style = MaterialTheme.typography.headlineMedium, fontWeight = FontWeight.Bold, color = FailRed