diff --git a/data/build.gradle.kts b/data/build.gradle.kts index e1a9b7af..bd36e54e 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -57,7 +57,7 @@ dependencies { implementation(libs.bundles.logging) debugImplementation(libs.okhttp3.logging.interceptor) - implementation(libs.bundles.kakao) + implementation(libs.kakao.friend) } fun getLocalProperty(propertyKey: String): String { diff --git a/data/src/main/kotlin/ac/dnd/mour/android/data/remote/network/model/statistics/GetGroupStatisticsRes.kt b/data/src/main/kotlin/ac/dnd/mour/android/data/remote/network/model/statistics/GetGroupStatisticsRes.kt index cdf5b6e3..87079063 100644 --- a/data/src/main/kotlin/ac/dnd/mour/android/data/remote/network/model/statistics/GetGroupStatisticsRes.kt +++ b/data/src/main/kotlin/ac/dnd/mour/android/data/remote/network/model/statistics/GetGroupStatisticsRes.kt @@ -20,7 +20,7 @@ data class GetGroupStatisticsItemRes( @SerialName("event") val event: String, @SerialName("amount") - val amount: Long + val amount: Double ) : DataMapper { override fun toDomain(): GroupStatistics { return GroupStatistics( diff --git a/data/src/main/kotlin/ac/dnd/mour/android/data/repository/feature/statistics/MockStatisticsRepository.kt b/data/src/main/kotlin/ac/dnd/mour/android/data/repository/feature/statistics/MockStatisticsRepository.kt index 38e39828..93666078 100644 --- a/data/src/main/kotlin/ac/dnd/mour/android/data/repository/feature/statistics/MockStatisticsRepository.kt +++ b/data/src/main/kotlin/ac/dnd/mour/android/data/repository/feature/statistics/MockStatisticsRepository.kt @@ -83,31 +83,31 @@ class MockStatisticsRepository @Inject constructor() : StatisticsRepository { listOf( GroupStatistics( event = "결혼", - amount = Random.nextLong(50_000, 200_000) + amount = Random.nextDouble(50_000.0, 200_000.0) ), GroupStatistics( event = "생일", - amount = Random.nextLong(50_000, 400_000) + amount = Random.nextDouble(50_000.0, 400_000.0) ), GroupStatistics( event = "돌잔치", - amount = Random.nextLong(0, 50_000) + amount = Random.nextDouble(0.0, 50_000.0) ), GroupStatistics( event = "출산", - amount = Random.nextLong(0, 50_000) + amount = Random.nextDouble(0.0, 50_000.0) ), GroupStatistics( event = "개업", - amount = Random.nextLong(40_000, 300_000) + amount = Random.nextDouble(40_000.0, 300_000.0) ), GroupStatistics( event = "랜덤이벤트1", - amount = Random.nextLong(0, 500_000) + amount = Random.nextDouble(0.0, 500_000.0) ), GroupStatistics( event = "랜덤이벤트2", - amount = Random.nextLong(50_000, 100_000) + amount = Random.nextDouble(50_000.0, 100_000.0) ), ) ) diff --git a/domain/src/main/kotlin/ac/dnd/mour/android/domain/model/feature/statistics/GroupStatistics.kt b/domain/src/main/kotlin/ac/dnd/mour/android/domain/model/feature/statistics/GroupStatistics.kt index 027fe9a0..604ac07f 100644 --- a/domain/src/main/kotlin/ac/dnd/mour/android/domain/model/feature/statistics/GroupStatistics.kt +++ b/domain/src/main/kotlin/ac/dnd/mour/android/domain/model/feature/statistics/GroupStatistics.kt @@ -2,12 +2,12 @@ package ac.dnd.mour.android.domain.model.feature.statistics data class GroupStatistics( val event: String, - val amount: Long + val amount: Double ) { companion object { val empty = GroupStatistics( event = "", - amount = 0 + amount = 0.0 ) } } diff --git a/presentation/build.gradle.kts b/presentation/build.gradle.kts index ca61e1fe..5c22239c 100644 --- a/presentation/build.gradle.kts +++ b/presentation/build.gradle.kts @@ -70,6 +70,8 @@ dependencies { implementation(platform(libs.firebase.bom)) implementation(libs.bundles.logging) + implementation(libs.kakao.user) + debugImplementation(libs.androidx.compose.ui.tooling) debugImplementation(libs.androidx.compose.ui.test.manifest) diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/common/util/KakaoLoginUtil.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/common/util/KakaoLoginUtil.kt new file mode 100644 index 00000000..1ba7d024 --- /dev/null +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/common/util/KakaoLoginUtil.kt @@ -0,0 +1,51 @@ +package ac.dnd.mour.android.presentation.common.util + +import android.content.Context +import com.kakao.sdk.auth.model.OAuthToken +import com.kakao.sdk.common.model.ClientError +import com.kakao.sdk.common.model.ClientErrorCause +import com.kakao.sdk.user.UserApiClient + +fun loginWithKakao( + context: Context, + onSuccess: (OAuthToken) -> Unit, + onFailure: (Throwable) -> Unit +) { + loginWithKakaoTalk( + context = context, + onSuccess = onSuccess, + onFailure = { exception -> + if ((exception as? ClientError)?.reason == ClientErrorCause.NotSupported) { + loginWithKakaoAccount( + context = context, + onSuccess = onSuccess, + onFailure = onFailure + ) + } else { + onFailure(exception) + } + } + ) +} + +fun loginWithKakaoTalk( + context: Context, + onSuccess: (OAuthToken) -> Unit, + onFailure: (Throwable) -> Unit +) { + UserApiClient.instance.loginWithKakaoTalk(context) { token, error -> + token?.let { onSuccess(it) } + error?.let { onFailure(it) } + } +} + +fun loginWithKakaoAccount( + context: Context, + onSuccess: (OAuthToken) -> Unit, + onFailure: (Throwable) -> Unit +) { + UserApiClient.instance.loginWithKakaoAccount(context) { token, error -> + token?.let { onSuccess(it) } + error?.let { onFailure(it) } + } +} diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/common/view/calendar/CalendarComponent.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/common/view/calendar/CalendarComponent.kt index a3290330..696978e4 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/common/view/calendar/CalendarComponent.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/common/view/calendar/CalendarComponent.kt @@ -67,7 +67,7 @@ fun CalendarComponent( LaunchedEffect(selectedYear, selectedMonth) { dayItems.clear() dayItems.addAll(calendarConfig.getCurrentCalendarDate(selectedYear, selectedMonth)) - onDaySelect(calendarConfig.getCalendarDay()) + onDaySelect(selectedDay) } Column( diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/MainSystemUiState.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/MainSystemUiState.kt index f5df2c71..eb2c1db8 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/MainSystemUiState.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/MainSystemUiState.kt @@ -20,7 +20,7 @@ fun ManageSystemUiState( }.orEmpty() when (route) { - HomeConstant.ROUTE, + HomeConstant.ROUTE_STRUCTURE, ScheduleAddConstant.ROUTE -> { SideEffect { appState.systemUiController.setStatusBarColor(Gray000) diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/HomeDestination.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/HomeDestination.kt index 44dce97f..4017792e 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/HomeDestination.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/HomeDestination.kt @@ -8,6 +8,8 @@ import ac.dnd.mour.android.presentation.ui.main.home.history.historyDestination import ac.dnd.mour.android.presentation.ui.main.home.mypage.myPageDestination import ac.dnd.mour.android.presentation.ui.main.home.schedule.scheduleDestination import ac.dnd.mour.android.presentation.ui.main.home.statistics.statisticsDestination +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -27,9 +29,20 @@ fun NavGraphBuilder.homeDestination( defaultValue = "" } ) - ) { + ) { entry -> + + val message = entry.savedStateHandle.getStateFlow( + HomeConstant.ROUTE_ARGUMENT_MESSAGE, + initialValue = "" + ).collectAsState() val viewModel: HomeViewModel = hiltViewModel() + if(message.value.isNotEmpty()){ + LaunchedEffect(Unit) { + viewModel.viewMessage(message.value) + entry.savedStateHandle.remove(HomeConstant.ROUTE_ARGUMENT_MESSAGE) + } + } val model: HomeModel = let { val state by viewModel.state.collectAsStateWithLifecycle() diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/HomeViewModel.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/HomeViewModel.kt index a03af584..f40a2278 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/HomeViewModel.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/HomeViewModel.kt @@ -26,20 +26,13 @@ class HomeViewModel @Inject constructor( savedStateHandle.get(HomeConstant.ROUTE_ARGUMENT_MESSAGE) ?: "" } - init { - if (message.isNotEmpty()) { - viewMessage(message) - } - } - fun onIntent(intent: HomeIntent) { } - private fun viewMessage(message: String) { + fun viewMessage(message: String) { launch { _event.emit(HomeEvent.ShowSnackBar(message)) } - savedStateHandle.remove(HomeConstant.ROUTE_ARGUMENT_MESSAGE) } } diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/common/relation/RelationScreen.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/common/relation/RelationScreen.kt index 21446713..a0acecac 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/common/relation/RelationScreen.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/common/relation/RelationScreen.kt @@ -188,15 +188,20 @@ fun RelationScreen( ) appState.navController.navigate(route) } else { - val route = makeRoute( - HomeConstant.ROUTE, - listOf(HomeConstant.ROUTE_ARGUMENT_MESSAGE to "등록이 완료되었습니다.") + appState.navController.previousBackStackEntry?.savedStateHandle?.set( + HomeConstant.ROUTE_ARGUMENT_MESSAGE, + "등록이 완료되었습니다.", ) - appState.navController.navigate(route) { - popUpTo(RelationConstant.ROUTE) { - inclusive = true - } - } + appState.navController.popBackStack() +// val route = makeRoute( +// HomeConstant.ROUTE, +// listOf(HomeConstant.ROUTE_ARGUMENT_MESSAGE to "등록이 완료되었습니다.") +// ) +// appState.navController.navigate(route) { +// popUpTo(RelationConstant.ROUTE) { +// inclusive = true +// } +// } } } } diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/history/HistoryPageScreen.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/history/HistoryPageScreen.kt index 46adb159..cf5a86e9 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/history/HistoryPageScreen.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/history/HistoryPageScreen.kt @@ -78,7 +78,8 @@ fun HistoryPageScreen( handler: CoroutineExceptionHandler, viewType: HistoryViewType, searchText: String, - onRecord: () -> Unit + onRecord: () -> Unit, + isExpanded: Boolean ) { var selectedGroupId by remember { mutableLongStateOf(-1) } var isDropDownMenuExpanded by remember { mutableStateOf(false) } @@ -97,12 +98,6 @@ fun HistoryPageScreen( ) }.sortedByDescending { it.relationList.size - }.filter { - if (searchText.isNotEmpty()) { - it.name.contains(searchText) - } else { - true - } } val relations = groups.flatMap { it.relationList } @@ -121,6 +116,13 @@ fun HistoryPageScreen( else if (selectedGroupId < 0) false else it.group.id == selectedGroupId } + .filter { + if (searchText.isNotEmpty()) { + it.name.contains(searchText) + } else { + true + } + } fun navigateToHistoryDetail(id: Long) { val route = makeRoute( @@ -217,7 +219,8 @@ fun HistoryPageScreen( contentAlignment = Alignment.Center ) { EmptyRelationView( - onRecord = onRecord + onRecord = onRecord, + isExpanded = isExpanded ) } } else { @@ -373,6 +376,7 @@ private fun GroupChipListComponent( @Composable private fun EmptyRelationView( + isExpanded: Boolean, onRecord: () -> Unit ) { Column( @@ -382,7 +386,7 @@ private fun EmptyRelationView( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { - Spacer(modifier = Modifier.weight(60f)) + Spacer(modifier = Modifier.weight(if (isExpanded) 1f else 60f)) Text( text = "아직 주고 받은 내역이 없어요.", style = Body1.merge( @@ -427,7 +431,7 @@ private fun EmptyRelationView( letterSpacing = (-0.25).sp ) } - Spacer(modifier = Modifier.weight(118f)) + Spacer(modifier = Modifier.weight(if (isExpanded) 1f else 118f)) } } @@ -436,7 +440,8 @@ private fun EmptyRelationView( private fun EmptyRelationViewPreview() { Box(modifier = Modifier.height(198.dp)) { EmptyRelationView( - onRecord = {} + onRecord = {}, + isExpanded = true ) } } diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/history/HistoryScreen.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/history/HistoryScreen.kt index 390b844b..cdbffeb5 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/history/HistoryScreen.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/history/HistoryScreen.kt @@ -224,6 +224,7 @@ private fun HistoryScreen( } } } + val searchBoxHeightState = animateDpAsState( targetValue = when (swipeState.progress.to) { HistoryViewSwipingType.COLLAPSED -> 0.dp @@ -497,7 +498,8 @@ private fun HistoryScreen( searchText = searchText, onRecord = { navigateToAddRelation() - } + }, + isExpanded = swipeState.progress.to == HistoryViewSwipingType.EXPANDED ) } } diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/history/detail/HistoryDetailBackgroundComponent.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/history/detail/HistoryDetailBackgroundComponent.kt index 3aed588e..3d17f404 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/history/detail/HistoryDetailBackgroundComponent.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/history/detail/HistoryDetailBackgroundComponent.kt @@ -10,7 +10,6 @@ import ac.dnd.mour.android.presentation.common.theme.Gray000 import ac.dnd.mour.android.presentation.common.theme.Gray100 import ac.dnd.mour.android.presentation.common.theme.Headline0 import ac.dnd.mour.android.presentation.common.theme.Headline3 -import ac.dnd.mour.android.presentation.common.util.expansion.measureTextWidth import ac.dnd.mour.android.presentation.model.history.HistoryDetailGrowthType import ac.dnd.mour.android.presentation.model.history.HistoryTagType import androidx.compose.foundation.Image @@ -48,6 +47,7 @@ import com.airbnb.lottie.compose.LottieCompositionSpec import com.airbnb.lottie.compose.LottieConstants import com.airbnb.lottie.compose.rememberLottieComposition import kotlinx.datetime.LocalDate +import java.text.DecimalFormat @Composable fun HistoryDetailBackgroundComponent( @@ -216,7 +216,10 @@ fun HistoryDetailBackgroundComponent( Row(verticalAlignment = Alignment.CenterVertically) { val nameLength = model.relationDetail.name.length Text( - text = if (nameLength < 8) model.relationDetail.name else model.relationDetail.name.substring(0,8), + text = if (nameLength < 8) model.relationDetail.name else model.relationDetail.name.substring( + 0, + 8 + ), fontWeight = FontWeight.SemiBold, style = Headline0.merge(color = Gray000), overflow = TextOverflow.Ellipsis, @@ -248,7 +251,7 @@ fun HistoryDetailBackgroundComponent( ) Spacer(modifier = Modifier.width(14.dp)) Text( - text = "${model.relationDetail.takeMoney}원", + text = DecimalFormat("#,###").format(model.relationDetail.takeMoney) + "원", style = Headline3.merge( color = Gray000, fontWeight = FontWeight.SemiBold @@ -266,7 +269,7 @@ fun HistoryDetailBackgroundComponent( ) Spacer(modifier = Modifier.width(14.dp)) Text( - text = "-${model.relationDetail.giveMoney}원", + text = "-" + DecimalFormat("#,###").format(model.relationDetail.giveMoney) + "원", style = Headline3.merge( color = Gray000, fontWeight = FontWeight.SemiBold diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/history/registration/HistoryRegistrationScreen.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/history/registration/HistoryRegistrationScreen.kt index 0f2aec2e..7ddd18a2 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/history/registration/HistoryRegistrationScreen.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/history/registration/HistoryRegistrationScreen.kt @@ -73,6 +73,7 @@ import androidx.compose.runtime.mutableStateListOf 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 import androidx.compose.ui.Modifier @@ -107,21 +108,21 @@ fun HistoryRegistrationScreen( val scope = rememberCoroutineScope() val focusManager = LocalFocusManager.current val scrollState = rememberScrollState() - var isContinuousState by remember { mutableStateOf(false) } - var historyTypeState by remember { mutableStateOf(HistoryRegistrationType.TAKE) } - var priceText by remember { mutableStateOf("") } - var userNameText by remember { mutableStateOf(name) } - var relationId by remember { mutableLongStateOf(id) } - var selectedYear by remember { mutableIntStateOf(calendarConfig.getCalendarYear()) } - var selectedMonth by remember { mutableIntStateOf(calendarConfig.getCalendarMonth()) } - var selectedDay by remember { mutableIntStateOf(calendarConfig.getCalendarDay()) } - var eventTypeText by remember { mutableStateOf("") } - var selectedEventId by remember { mutableLongStateOf(-1) } - var memoText by remember { mutableStateOf("") } + var isContinuousState by rememberSaveable { mutableStateOf(false) } + var historyTypeState by rememberSaveable { mutableStateOf(HistoryRegistrationType.TAKE) } + var priceText by rememberSaveable { mutableStateOf("") } + var userNameText by rememberSaveable { mutableStateOf(name) } + var relationId by rememberSaveable { mutableLongStateOf(id) } + var selectedYear by rememberSaveable { mutableIntStateOf(calendarConfig.getCalendarYear()) } + var selectedMonth by rememberSaveable { mutableIntStateOf(calendarConfig.getCalendarMonth()) } + var selectedDay by rememberSaveable { mutableIntStateOf(calendarConfig.getCalendarDay()) } + var eventTypeText by rememberSaveable { mutableStateOf("") } + var selectedEventId by rememberSaveable { mutableLongStateOf(-1) } + var memoText by rememberSaveable { mutableStateOf("") } val tagIdList = remember { mutableStateListOf() } - var isCalendarShowingState by remember { mutableStateOf(false) } - var isAddNameShowingState by remember { mutableStateOf(false) } + var isCalendarShowingState by rememberSaveable { mutableStateOf(false) } + var isAddNameShowingState by rememberSaveable { mutableStateOf(false) } var isViewUnRecordMessage by remember { mutableStateOf("") } diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/ScheduleScreen.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/ScheduleScreen.kt index 96d2a052..b0d3211b 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/ScheduleScreen.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/ScheduleScreen.kt @@ -12,10 +12,10 @@ import ac.dnd.mour.android.presentation.common.theme.Gray500 import ac.dnd.mour.android.presentation.common.theme.Gray600 import ac.dnd.mour.android.presentation.common.theme.Gray700 import ac.dnd.mour.android.presentation.common.theme.Gray800 +import ac.dnd.mour.android.presentation.common.theme.Gray900 import ac.dnd.mour.android.presentation.common.theme.Headline1 import ac.dnd.mour.android.presentation.common.theme.Headline3 import ac.dnd.mour.android.presentation.common.theme.Shapes -import ac.dnd.mour.android.presentation.common.theme.Space20 import ac.dnd.mour.android.presentation.common.util.ErrorObserver import ac.dnd.mour.android.presentation.common.util.LaunchedEffectWithLifecycle import ac.dnd.mour.android.presentation.common.util.coroutine.event.EventFlow @@ -37,12 +37,14 @@ 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.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.lazy.items import androidx.compose.material.FloatingActionButton @@ -121,8 +123,24 @@ private fun ScheduleScreen( val scheduleList = model.scheduleList.filter { it.day == selectedDate } val formattedTitle = "${selectedDate.month.number}월 ${selectedDate.dayOfMonth}일" + val formattedDate = Unit.let { + val year = showingDate.year + val month = showingDate.month.number + + "${year}년 ${month}월" + } + + fun navigateToScheduleAdd() { - appState.navController.navigate(ScheduleAddConstant.ROUTE) + val route = makeRoute( + ScheduleAddConstant.ROUTE, + listOf( + ScheduleAddConstant.ROUTE_ARGUMENT_SCHEDULE_YEAR to selectedDate.year, + ScheduleAddConstant.ROUTE_ARGUMENT_SCHEDULE_MONTH to selectedDate.monthNumber, + ScheduleAddConstant.ROUTE_ARGUMENT_SCHEDULE_DAY to selectedDate.dayOfMonth + ) + ) + appState.navController.navigate(route) } fun navigateToNotification() { @@ -191,107 +209,151 @@ private fun ScheduleScreen( ) } } - ScheduleScreenHeader( - appState = appState, - model = model, - event = event, - intent = intent, - handler = handler, - showingDate = showingDate, - selectedDate = selectedDate, - onClickDate = { - isDatePickerShowing = true - }, - onClickDay = { - selectedDate = it + Column( + modifier = Modifier + .fillMaxWidth() + .background(color = Gray000) + ) { + Spacer(modifier = Modifier.height(8.dp)) + Row( + modifier = Modifier + .clickable { + isDatePickerShowing = true + }, + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Spacer(modifier = Modifier.width(20.dp)) + Text( + text = formattedDate, + style = Headline1.merge(Gray900) + ) + Icon( + modifier = Modifier.size(20.dp), + painter = painterResource(R.drawable.ic_drop_down), + contentDescription = null, + tint = Gray900 + ) } - ) + Spacer(modifier = Modifier.height(5.dp)) + } - Spacer(modifier = Modifier.height(20.dp)) - Text( - text = formattedTitle, - style = Headline3, - modifier = Modifier.padding(start = 20.dp) - ) - Spacer(modifier = Modifier.height(14.dp)) if (scheduleList.isEmpty()) { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center + ScheduleScreenHeader( + appState = appState, + model = model, + event = event, + intent = intent, + handler = handler, + showingDate = showingDate, + selectedDate = selectedDate, + onClickDay = { + selectedDate = it + } + ) + Spacer(modifier = Modifier.height(20.dp)) + Text( + text = formattedTitle, + style = Headline3, + modifier = Modifier.padding(start = 20.dp) + ) + Spacer(modifier = Modifier.height(14.dp)) + Spacer(modifier = Modifier.weight(100f)) + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 20.dp) + .height(103.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center ) { - Column( + Spacer(modifier = Modifier.weight(7f)) + Text( + text = "아직 작성한 일정이 없어요", + fontWeight = FontWeight.SemiBold, + style = Body1.merge(Gray700), + letterSpacing = (-0.25).sp, + + ) + Spacer(modifier = Modifier.weight(6f)) + Text( + text = "일정을 등록하고 미리 알림 받아보세요", + fontWeight = FontWeight.Normal, + style = Body2.merge(Gray600), + letterSpacing = (-0.25).sp + ) + Spacer(modifier = Modifier.weight(24f)) + Box( modifier = Modifier - .fillMaxWidth() - .height(103.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center + .clip(Shapes.medium) + .background(color = Gray000) + .clickable { + navigateToScheduleAdd() + } + .border( + width = 1.dp, + color = Gray500, + shape = Shapes.medium + ) + .padding( + horizontal = 16.dp, + vertical = 6.5.dp + ) ) { - Spacer(modifier = Modifier.weight(7f)) Text( - text = "아직 작성한 일정이 없어요", + text = "일정 등록하기", fontWeight = FontWeight.SemiBold, - style = Body1.merge(Gray700), - letterSpacing = (-0.25).sp, - - ) - Spacer(modifier = Modifier.weight(6f)) - Text( - text = "일정을 등록하고 미리 알림 받아보세요", - fontWeight = FontWeight.Normal, - style = Body2.merge(Gray600), + style = Body1.merge(color = Gray600), letterSpacing = (-0.25).sp ) - Spacer(modifier = Modifier.weight(24f)) - Box( - modifier = Modifier - .clip(Shapes.medium) - .background(color = Gray000) - .clickable { - navigateToScheduleAdd() - } - .border( - width = 1.dp, - color = Gray500, - shape = Shapes.medium - ) - .padding( - horizontal = 16.dp, - vertical = 6.5.dp - ) - ) { - Text( - text = "일정 등록하기", - fontWeight = FontWeight.SemiBold, - style = Body1.merge(color = Gray600), - letterSpacing = (-0.25).sp - ) - } } } + Spacer(modifier = Modifier.weight(176f)) } else { - LazyColumn( - modifier = Modifier - .weight(1f) - .padding(horizontal = 20.dp), - verticalArrangement = Arrangement.spacedBy(Space20) - ) { - items(scheduleList) { schedule -> - ScheduleScreenItem( - schedule = schedule, - onClickSchedule = { - navigateToScheduleEdit( - id = schedule.id - ) - }, - onClickInvitation = { - navigateToInvitation( - link = schedule.link - ) + LazyColumn(modifier = Modifier.fillMaxWidth()) { + item { + ScheduleScreenHeader( + appState = appState, + model = model, + event = event, + intent = intent, + handler = handler, + showingDate = showingDate, + selectedDate = selectedDate, + onClickDay = { + selectedDate = it } ) + Spacer(modifier = Modifier.height(20.dp)) + Text( + text = formattedTitle, + style = Headline3, + modifier = Modifier.padding(start = 20.dp) + ) + Spacer(modifier = Modifier.height(14.dp)) + } + items(scheduleList) { schedule -> + Column( + modifier = Modifier.padding(horizontal = 20.dp) + ) { + ScheduleScreenItem( + schedule = schedule, + onClickSchedule = { + navigateToScheduleEdit( + id = schedule.id + ) + }, + onClickInvitation = { + navigateToInvitation( + link = schedule.link + ) + } + ) + Spacer(modifier = Modifier.height(20.dp)) + } } item { - Spacer(modifier = Modifier.height(80.dp)) + Spacer(modifier = Modifier.height(60.dp)) } } } diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/ScheduleScreenHeader.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/ScheduleScreenHeader.kt index 253adeac..93a9ba85 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/ScheduleScreenHeader.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/ScheduleScreenHeader.kt @@ -71,18 +71,10 @@ fun ScheduleScreenHeader( handler: CoroutineExceptionHandler, showingDate: LocalDate, selectedDate: LocalDate, - onClickDate: () -> Unit, onClickDay: (LocalDate) -> Unit ) { var isExpanded: Boolean by remember { mutableStateOf(true) } - val formattedDate = Unit.let { - val year = showingDate.year - val month = showingDate.month.number - - "${year}년 ${month}월" - } - Card( shape = RoundedCornerShape(bottomStart = 12.dp, bottomEnd = 12.dp), backgroundColor = Gray000, @@ -93,25 +85,25 @@ fun ScheduleScreenHeader( .fillMaxWidth() .padding(horizontal = 20.dp) ) { - Spacer(modifier = Modifier.height(8.dp)) - Row( - modifier = Modifier.clickable { - onClickDate() - }, - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - text = formattedDate, - style = Headline1.merge(Gray900) - ) - Icon( - modifier = Modifier.size(20.dp), - painter = painterResource(R.drawable.ic_drop_down), - contentDescription = null, - tint = Gray900 - ) - } +// Spacer(modifier = Modifier.height(8.dp)) +// Row( +// modifier = Modifier.clickable { +// onClickDate() +// }, +// horizontalArrangement = Arrangement.SpaceBetween, +// verticalAlignment = Alignment.CenterVertically +// ) { +// Text( +// text = formattedDate, +// style = Headline1.merge(Gray900) +// ) +// Icon( +// modifier = Modifier.size(20.dp), +// painter = painterResource(R.drawable.ic_drop_down), +// contentDescription = null, +// tint = Gray900 +// ) +// } Spacer(modifier = Modifier.height(20.dp)) ScheduleScreenHeaderCalendar( appState = appState, @@ -426,7 +418,6 @@ private fun ScheduleScreenHeaderPreview() { handler = CoroutineExceptionHandler { _, _ -> }, showingDate = LocalDate(2024, 2, 25), selectedDate = LocalDate(2024, 2, 1), - onClickDate = {}, onClickDay = {} ) } diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/ScheduleScreenItem.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/ScheduleScreenItem.kt index 5457c8b1..34750179 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/ScheduleScreenItem.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/ScheduleScreenItem.kt @@ -81,7 +81,7 @@ fun ScheduleScreenItem( ) { Box( modifier = Modifier - .size(40.dp) + .size(32.dp) .clip(CircleShape) .background(Gray000), contentAlignment = Alignment.Center diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddConstant.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddConstant.kt index 65a7d0b1..4f212455 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddConstant.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddConstant.kt @@ -6,5 +6,12 @@ object ScheduleAddConstant { const val ROUTE: String = "${ScheduleConstant.ROUTE}/add" const val ROUTE_ARGUMENT_SCHEDULE_ID = "id" - const val ROUTE_STRUCTURE = "$ROUTE?$ROUTE_ARGUMENT_SCHEDULE_ID={$ROUTE_ARGUMENT_SCHEDULE_ID}" + const val ROUTE_ARGUMENT_SCHEDULE_YEAR = "year" + const val ROUTE_ARGUMENT_SCHEDULE_MONTH = "month" + const val ROUTE_ARGUMENT_SCHEDULE_DAY = "day" + const val ROUTE_STRUCTURE = + "${ROUTE}?${ROUTE_ARGUMENT_SCHEDULE_ID}={${ROUTE_ARGUMENT_SCHEDULE_ID}}&" + + "${ROUTE_ARGUMENT_SCHEDULE_YEAR}={${ROUTE_ARGUMENT_SCHEDULE_YEAR}}&" + + "${ROUTE_ARGUMENT_SCHEDULE_MONTH}={${ROUTE_ARGUMENT_SCHEDULE_MONTH}}&" + + "${ROUTE_ARGUMENT_SCHEDULE_DAY}={${ROUTE_ARGUMENT_SCHEDULE_DAY}}" } diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddDestination.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddDestination.kt index 881d92d8..307ffd23 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddDestination.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddDestination.kt @@ -19,7 +19,19 @@ fun NavGraphBuilder.scheduleAddDestination( navArgument(ScheduleAddConstant.ROUTE_ARGUMENT_SCHEDULE_ID) { type = NavType.LongType defaultValue = -1L - } + }, + navArgument(ScheduleAddConstant.ROUTE_ARGUMENT_SCHEDULE_YEAR){ + type = NavType.IntType + defaultValue = 1 + }, + navArgument(ScheduleAddConstant.ROUTE_ARGUMENT_SCHEDULE_MONTH){ + type = NavType.IntType + defaultValue = 1 + }, + navArgument(ScheduleAddConstant.ROUTE_ARGUMENT_SCHEDULE_DAY){ + type = NavType.IntType + defaultValue = 1 + }, ) ) { val viewModel: ScheduleAddViewModel = hiltViewModel() diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddEvent.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddEvent.kt index d0db1988..846d85b4 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddEvent.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddEvent.kt @@ -1,12 +1,17 @@ package ac.dnd.mour.android.presentation.ui.main.home.schedule.add import ac.dnd.mour.android.domain.model.feature.schedule.Schedule +import kotlinx.datetime.LocalDate sealed interface ScheduleAddEvent { sealed interface LoadSchedule : ScheduleAddEvent { data class Success(val schedule: Schedule) : LoadSchedule } + sealed interface LoadLocalDate : ScheduleAddEvent { + data class Success(val date: LocalDate) : LoadLocalDate + } + sealed interface AddSchedule : ScheduleAddEvent { data object Success : AddSchedule } diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddScreen.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddScreen.kt index 3d80f054..849d3fec 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddScreen.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddScreen.kt @@ -24,7 +24,7 @@ import ac.dnd.mour.android.presentation.common.util.coroutine.event.MutableEvent import ac.dnd.mour.android.presentation.common.util.coroutine.event.eventObserve import ac.dnd.mour.android.presentation.common.view.DialogScreen import ac.dnd.mour.android.presentation.common.view.SnackBarScreen -import ac.dnd.mour.android.presentation.common.view.calendar.CalendarPicker +import ac.dnd.mour.android.presentation.common.view.calendar.CalendarConfig import ac.dnd.mour.android.presentation.common.view.calendar.TimePicker import ac.dnd.mour.android.presentation.common.view.chip.ChipItem import ac.dnd.mour.android.presentation.common.view.chip.ChipType @@ -38,6 +38,7 @@ import ac.dnd.mour.android.presentation.common.view.textfield.TypingTextFieldTyp import ac.dnd.mour.android.presentation.model.history.HistoryEventType import ac.dnd.mour.android.presentation.model.schedule.ScheduleAlarmType import ac.dnd.mour.android.presentation.ui.main.ApplicationState +import ac.dnd.mour.android.presentation.ui.main.common.calendar.HistoryCalendarScreen import ac.dnd.mour.android.presentation.ui.main.home.HomeConstant import ac.dnd.mour.android.presentation.ui.main.home.common.relation.get.SearchRelationScreen import ac.dnd.mour.android.presentation.ui.main.home.schedule.add.notification.ScheduleAddNotificationScreen @@ -131,7 +132,6 @@ fun ScheduleAddScreen( var isDatePickerShowing: Boolean by remember { mutableStateOf(false) } var isAlarmDatePickerShowing: Boolean by remember { mutableStateOf(false) } var isTimePickerShowing: Boolean by remember { mutableStateOf(false) } - var isAddSuccessShowing: Boolean by remember { mutableStateOf(false) } var isEditSuccessShowing: Boolean by remember { mutableStateOf(false) } var isRemoveSuccessShowing: Boolean by remember { mutableStateOf(false) } var isOutPageShowing: Boolean by remember { mutableStateOf(false) } @@ -170,12 +170,17 @@ fun ScheduleAddScreen( } if (isDatePickerShowing) { - CalendarPicker( - localDate = date, - isDaySelectable = true, - onDismissRequest = { isDatePickerShowing = false }, - onConfirm = { - date = it + HistoryCalendarScreen( + calendarConfig = CalendarConfig(), + selectedYear = date.year, + selectedMonth = date.monthNumber, + selectedDay = date.dayOfMonth, + onClose = { + isDatePickerShowing = false + }, + onConfirm = { year, month, day -> + date = LocalDate(year, month, day) + isDatePickerShowing = false } ) } @@ -201,22 +206,6 @@ fun ScheduleAddScreen( ) } - if (isAddSuccessShowing) { - DialogScreen( - title = "일정 추가하기", - message = "일정을 추가하였습니다.", - isCancelable = false, - onConfirm = { - // TODO : 뒤로가기 메시지 전달 추가 + 다이얼 로그 삭제 - appState.navController.popBackStack() - - }, - onDismissRequest = { - isAddSuccessShowing = false - } - ) - } - if (isRemoveSuccessShowing) { DialogScreen( title = "일정 수정하기", @@ -520,7 +509,7 @@ fun ScheduleAddScreen( Row( verticalAlignment = Alignment.CenterVertically ) { - Icon( + Image( modifier = Modifier.size(16.dp), painter = painterResource(id = R.drawable.ic_alarm_gray), contentDescription = null, @@ -761,6 +750,14 @@ fun ScheduleAddScreen( } + fun loadDate(event: ScheduleAddEvent.LoadLocalDate) { + when (event) { + is ScheduleAddEvent.LoadLocalDate.Success -> { + date = event.date + } + } + } + fun loadSchedule(event: ScheduleAddEvent.LoadSchedule) { when (event) { is ScheduleAddEvent.LoadSchedule.Success -> { @@ -805,7 +802,11 @@ fun ScheduleAddScreen( fun addSchedule(event: ScheduleAddEvent.AddSchedule) { when (event) { ScheduleAddEvent.AddSchedule.Success -> { - isAddSuccessShowing = true + appState.navController.previousBackStackEntry?.savedStateHandle?.set( + HomeConstant.ROUTE_ARGUMENT_MESSAGE, + "일정이 추가되었습니다.", + ) + appState.navController.popBackStack() } } } @@ -848,6 +849,10 @@ fun ScheduleAddScreen( is ScheduleAddEvent.RemoveSchedule -> { removeSchedule(event) } + + is ScheduleAddEvent.LoadLocalDate -> { + loadDate(event) + } } } } diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddViewModel.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddViewModel.kt index ca47564b..e36d2b36 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddViewModel.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/schedule/add/ScheduleAddViewModel.kt @@ -13,7 +13,6 @@ import ac.dnd.mour.android.presentation.common.util.coroutine.event.asEventFlow import ac.dnd.mour.android.presentation.model.schedule.ScheduleAlarmType import androidx.lifecycle.SavedStateHandle import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow @@ -22,6 +21,7 @@ import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDateTime import kotlinx.datetime.LocalTime import kotlinx.datetime.minus +import javax.inject.Inject @HiltViewModel class ScheduleAddViewModel @Inject constructor( @@ -38,7 +38,7 @@ class ScheduleAddViewModel @Inject constructor( private val _event: MutableEventFlow = MutableEventFlow() val event: EventFlow = _event.asEventFlow() - val scheduleId: Long by lazy { + private val scheduleId: Long by lazy { savedStateHandle.get(ScheduleAddConstant.ROUTE_ARGUMENT_SCHEDULE_ID) ?: -1L } @@ -46,9 +46,29 @@ class ScheduleAddViewModel @Inject constructor( scheduleId != -1L } + private val scheduleDate: LocalDate by lazy { + val year = + savedStateHandle.get(ScheduleAddConstant.ROUTE_ARGUMENT_SCHEDULE_YEAR) ?: 1 + val month = + savedStateHandle.get(ScheduleAddConstant.ROUTE_ARGUMENT_SCHEDULE_MONTH) ?: 1 + val day = + savedStateHandle.get(ScheduleAddConstant.ROUTE_ARGUMENT_SCHEDULE_DAY) ?: 1 + LocalDate(year, month, day) + } + init { if (scheduleId != -1L) { loadSchedule() + } else { + if (scheduleDate.year != 1) { + setSelectedDate() + } + } + } + + private fun setSelectedDate() { + launch { + _event.emit(ScheduleAddEvent.LoadLocalDate.Success(scheduleDate)) } } diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/statistics/user/StatisticsUserScreen.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/statistics/user/StatisticsUserScreen.kt index 2b2e1a47..6aa616a4 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/statistics/user/StatisticsUserScreen.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/home/statistics/user/StatisticsUserScreen.kt @@ -295,31 +295,31 @@ private fun StatisticsUserScreenPreview1() { groupStatistics = listOf( GroupStatistics( event = "결혼", - amount = Random.nextLong(50_000, 200_000) + amount = Random.nextDouble(50_000.0, 200_000.0) ), GroupStatistics( event = "생일", - amount = Random.nextLong(50_000, 400_000) + amount = Random.nextDouble(50_000.0, 400_000.0) ), GroupStatistics( event = "돌잔치", - amount = Random.nextLong(0, 50_000) + amount = Random.nextDouble(0.0, 50_000.0) ), GroupStatistics( event = "출산", - amount = Random.nextLong(0, 50_000) + amount = Random.nextDouble(0.0, 50_000.0) ), GroupStatistics( event = "개업", - amount = Random.nextLong(40_000, 300_000) + amount = Random.nextDouble(40_000.0, 300_000.0) ), GroupStatistics( event = "랜덤이벤트1", - amount = Random.nextLong(0, 500_000) + amount = Random.nextDouble(0.0, 500_000.0) ), GroupStatistics( event = "랜덤이벤트2", - amount = Random.nextLong(50_000, 100_000) + amount = Random.nextDouble(50_000.0, 100_000.0) ), ) ), diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/login/main/LoginMainScreen.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/login/main/LoginMainScreen.kt index 90c84e3a..ba385ccc 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/login/main/LoginMainScreen.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/login/main/LoginMainScreen.kt @@ -6,11 +6,13 @@ import ac.dnd.mour.android.presentation.common.theme.Body2 import ac.dnd.mour.android.presentation.common.theme.Gray000 import ac.dnd.mour.android.presentation.common.theme.Gray700 import ac.dnd.mour.android.presentation.common.theme.Gray800 +import ac.dnd.mour.android.presentation.common.theme.Gray900 import ac.dnd.mour.android.presentation.common.theme.Shapes import ac.dnd.mour.android.presentation.common.util.LaunchedEffectWithLifecycle import ac.dnd.mour.android.presentation.common.util.coroutine.event.EventFlow import ac.dnd.mour.android.presentation.common.util.coroutine.event.MutableEventFlow import ac.dnd.mour.android.presentation.common.util.coroutine.event.eventObserve +import ac.dnd.mour.android.presentation.common.util.loginWithKakao import ac.dnd.mour.android.presentation.common.view.DialogScreen import ac.dnd.mour.android.presentation.model.login.KakaoUserInformationModel import ac.dnd.mour.android.presentation.ui.main.ApplicationState @@ -45,6 +47,7 @@ import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.Font @@ -65,7 +68,7 @@ fun LoginMainScreen( handler: CoroutineExceptionHandler ) { var isDialogShowing by remember { mutableStateOf(false) } - + val context = LocalContext.current fun navigateToOnBoarding(kakaoUserModel: KakaoUserInformationModel) { appState.navController.sendKakaoUserModel(kakaoUserModel) } @@ -193,7 +196,17 @@ fun LoginMainScreen( shape = Shapes.medium ) .clickable { - if (model.state == LoginMainState.Init) intent(LoginMainIntent.Click) + if (model.state == LoginMainState.Init) { + loginWithKakao( + context = context, + onSuccess = { + intent(LoginMainIntent.Click) + }, + onFailure = { + isDialogShowing = true + } + ) + } } .padding(horizontal = 17.dp), ) { @@ -208,7 +221,7 @@ fun LoginMainScreen( modifier = Modifier.align(Alignment.Center), fontWeight = FontWeight.SemiBold, fontFamily = FontFamily(Font(R.font.pretendard)), - color = Gray700, + color = Gray900, letterSpacing = (-0.25).sp, fontSize = 16.sp ) diff --git a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/login/main/LoginMainViewModel.kt b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/login/main/LoginMainViewModel.kt index 36cc9f70..d5aa4bcd 100644 --- a/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/login/main/LoginMainViewModel.kt +++ b/presentation/src/main/kotlin/ac/dnd/mour/android/presentation/ui/main/login/main/LoginMainViewModel.kt @@ -12,10 +12,10 @@ import ac.dnd.mour.android.presentation.model.login.KakaoUserInformationModel import ac.dnd.mour.android.presentation.model.login.toUiModel import androidx.lifecycle.SavedStateHandle import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import javax.inject.Inject @HiltViewModel class LoginMainViewModel @Inject constructor( @@ -44,29 +44,10 @@ class LoginMainViewModel @Inject constructor( private fun loginFlow() { launch { _state.emit(LoginMainState.Loading) - loginKakao() + getUserInfo() } } - private fun loginKakao() = launch { - loginKakaoUseCase() - .onSuccess { - getUserInfo() - } - .onFailure { error -> - when (error) { - is ServerException -> { - _event.emit(LoginMainEvent.Login.Failure(error)) - } - - else -> { - _event.emit(LoginMainEvent.Login.Error(error)) - } - } - _state.emit(LoginMainState.Init) - } - } - private fun getUserInfo() = launch { getKakaoUserInfoUseCase.invoke() .onSuccess { userInfo -> diff --git a/presentation/src/main/res/drawable/ic_event_birthday.xml b/presentation/src/main/res/drawable/ic_event_birthday.xml index d0fb6235..df747822 100644 --- a/presentation/src/main/res/drawable/ic_event_birthday.xml +++ b/presentation/src/main/res/drawable/ic_event_birthday.xml @@ -1,30 +1,12 @@ - - - - - - - - - + + + + + + + + + diff --git a/presentation/src/main/res/drawable/ic_event_childbirth.xml b/presentation/src/main/res/drawable/ic_event_childbirth.xml index eaffb6b8..73ce93d6 100644 --- a/presentation/src/main/res/drawable/ic_event_childbirth.xml +++ b/presentation/src/main/res/drawable/ic_event_childbirth.xml @@ -1,43 +1,23 @@ - - - - - - - - + + + + + + + + diff --git a/presentation/src/main/res/drawable/ic_event_etc.xml b/presentation/src/main/res/drawable/ic_event_etc.xml index cfe6ff16..bbb59f31 100644 --- a/presentation/src/main/res/drawable/ic_event_etc.xml +++ b/presentation/src/main/res/drawable/ic_event_etc.xml @@ -1,21 +1,9 @@ - - - - - - + + + + + + diff --git a/presentation/src/main/res/drawable/ic_event_first_birthday_party.xml b/presentation/src/main/res/drawable/ic_event_first_birthday_party.xml index ec4f6dbc..ace11772 100644 --- a/presentation/src/main/res/drawable/ic_event_first_birthday_party.xml +++ b/presentation/src/main/res/drawable/ic_event_first_birthday_party.xml @@ -1,27 +1,11 @@ - - - - - - - - + + + + + + + + diff --git a/presentation/src/main/res/drawable/ic_event_marriage.xml b/presentation/src/main/res/drawable/ic_event_marriage.xml index 1c9e8d41..14e5fb79 100644 --- a/presentation/src/main/res/drawable/ic_event_marriage.xml +++ b/presentation/src/main/res/drawable/ic_event_marriage.xml @@ -1,33 +1,15 @@ - - - - - - - - - - + + + + + + + + + + + + diff --git a/presentation/src/main/res/drawable/ic_event_opening_of_business.xml b/presentation/src/main/res/drawable/ic_event_opening_of_business.xml index e17c4b92..440f3cda 100644 --- a/presentation/src/main/res/drawable/ic_event_opening_of_business.xml +++ b/presentation/src/main/res/drawable/ic_event_opening_of_business.xml @@ -1,30 +1,14 @@ - + - - - - - - - - + + + + + + + +