Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions app/src/main/java/com/sampoom/android/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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()
Expand Down
21 changes: 0 additions & 21 deletions app/src/main/java/com/sampoom/android/app/navigation/AppNavHost.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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<SnackBarMessage?>(null) }

Expand All @@ -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(),
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/com/sampoom/android/core/model/UserPosition.kt
Original file line number Diff line number Diff line change
@@ -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 // 회장
}
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ fun CommonTextField(
isError: Boolean = false,
errorMessage: String? = null,
imeAction: ImeAction = ImeAction.Next,
keyboardActions: KeyboardActions = KeyboardActions()
keyboardActions: KeyboardActions = KeyboardActions(),
readOnly: Boolean = false,
singleLine: Boolean = true
) {
var passwordVisible by remember { mutableStateOf(false) }

Expand Down Expand Up @@ -84,7 +86,8 @@ fun CommonTextField(
modifier = modifier
.fillMaxWidth()
.padding(vertical = 4.dp),
singleLine = true,
readOnly = readOnly,
singleLine = singleLine,
enabled = enabled,
isError = isError,
trailingIcon = trailingIconView,
Expand Down
30 changes: 30 additions & 0 deletions app/src/main/java/com/sampoom/android/core/util/DelayNetwork.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.sampoom.android.core.util

import kotlinx.coroutines.delay
import java.io.IOException
import java.net.SocketTimeoutException

suspend fun <T> 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) {
when (t) {
is SocketTimeoutException, is IOException -> {

}
else -> throw t
}
}
delay(currentDelay)
currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay)
}
return block()
}
Original file line number Diff line number Diff line change
@@ -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 -> "-"
}
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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.toUserPosition(),
workspace = workspace,
branch = branch,
agencyId = organizationId,
Expand All @@ -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())
} catch (_: Exception) {
UserRole.STAFF
private fun String.toUserPosition(): UserPosition = try {
UserPosition.valueOf(this.uppercase())
} catch (_: IllegalArgumentException) {
UserPosition.STAFF
}
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
Loading