diff --git a/core/src/main/java/com/terning/core/designsystem/component/topappbar/CalendarTopAppBar.kt b/core/src/main/java/com/terning/core/designsystem/component/topappbar/CalendarTopAppBar.kt index 30364b680..f7c7d0a60 100644 --- a/core/src/main/java/com/terning/core/designsystem/component/topappbar/CalendarTopAppBar.kt +++ b/core/src/main/java/com/terning/core/designsystem/component/topappbar/CalendarTopAppBar.kt @@ -40,7 +40,6 @@ import java.time.YearMonth @Composable fun CalendarTopAppBar( date: YearMonth, - isWeekExpanded: Boolean, isListExpanded: Boolean, onListButtonClicked: () -> Unit, onMonthNavigationButtonClicked: (Int) -> Unit, @@ -59,28 +58,26 @@ fun CalendarTopAppBar( modifier = Modifier.align(Alignment.Center), verticalAlignment = Alignment.CenterVertically ) { - if(!isWeekExpanded || isListExpanded) { Icon( painter = painterResource(id = R.drawable.ic_calendar_previous), contentDescription = stringResource(id = R.string.calendar_button_description_previous), tint = TerningMain, modifier = Modifier.noRippleClickable { onMonthNavigationButtonClicked(-1) } ) - } + Text( text = LocalDate.of(date.year, date.month, 1).getStringAsTitle(), style = TerningTheme.typography.title2, color = Black, modifier = Modifier.padding(horizontal = 8.dp) ) - if(!isWeekExpanded || isListExpanded) { Icon( painter = painterResource(id = R.drawable.ic_calendar_next), contentDescription = stringResource(id = R.string.calendar_button_description_next), tint = TerningMain, modifier = Modifier.noRippleClickable { onMonthNavigationButtonClicked(1) } ) - } + } Box( modifier = Modifier @@ -109,8 +106,6 @@ fun CalendarTopBarPreview() { CalendarTopAppBar( date = YearMonth.now(), isListExpanded = false, - isWeekExpanded = false - , onListButtonClicked = {}, onMonthNavigationButtonClicked = {} ) diff --git a/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt b/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt index d173cbd4b..fd8e24bd2 100644 --- a/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt +++ b/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt @@ -1,5 +1,6 @@ package com.terning.feature.calendar.calendar +import androidx.compose.animation.core.tween import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutHorizontally @@ -8,11 +9,10 @@ import androidx.compose.animation.togetherWith import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope @@ -27,12 +27,13 @@ import com.terning.core.designsystem.theme.Grey200 import com.terning.core.designsystem.theme.White import com.terning.feature.calendar.calendar.component.ScreenTransition import com.terning.feature.calendar.calendar.component.WeekDaysHeader +import com.terning.feature.calendar.calendar.model.CalendarModel.Companion.getLocalDateByPage import com.terning.feature.calendar.calendar.model.CalendarModel.Companion.getYearMonthByPage import com.terning.feature.calendar.calendar.model.CalendarUiState +import com.terning.feature.calendar.calendar.model.LocalPagerState import com.terning.feature.calendar.list.CalendarListRoute import com.terning.feature.calendar.month.CalendarMonthRoute import com.terning.feature.calendar.week.CalendarWeekRoute -import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.launch import java.time.LocalDate @@ -49,16 +50,11 @@ fun CalendarRoute( modifier = modifier, uiState = uiState, navigateToAnnouncement = navigateToAnnouncement, + onClickNewDate = viewModel::onSelectNewDate, updateSelectedDate = viewModel::updateSelectedDate, - updatePage = viewModel::updatePage, disableListVisibility = { viewModel.updateListVisibility(false) }, - disableWeekVisibility = { viewModel.updateSelectedDate(uiState.selectedDate) }, - onClickListButton = { - viewModel.updateListVisibility(!uiState.isListEnabled) - if (uiState.isWeekEnabled) { - viewModel.updateWeekVisibility(false) - } - } + disableWeekVisibility = { viewModel.updateWeekVisibility(false) }, + onClickListButton = { viewModel.updateListVisibility(!uiState.isListEnabled) } ) } @@ -66,102 +62,107 @@ fun CalendarRoute( private fun CalendarScreen( uiState: CalendarUiState, navigateToAnnouncement: (Long) -> Unit, + onClickNewDate: (LocalDate) -> Unit, updateSelectedDate: (LocalDate) -> Unit, disableListVisibility: () -> Unit, disableWeekVisibility: () -> Unit, - updatePage: (Int) -> Unit, onClickListButton: () -> Unit, modifier: Modifier = Modifier, ) { val coroutineScope = rememberCoroutineScope() - val listState = rememberLazyListState( - initialFirstVisibleItemIndex = uiState.calendarModel.initialPage + val pagerState = rememberPagerState( + initialPage = uiState.calendarModel.initialPage, + pageCount = { uiState.calendarModel.pageCount } ) - LaunchedEffect(key1 = listState) { - snapshotFlow { listState.firstVisibleItemIndex } - .distinctUntilChanged() - .collect { - updatePage(listState.firstVisibleItemIndex) + LaunchedEffect(key1 = pagerState, key2 = uiState.selectedDate) { + snapshotFlow { pagerState.currentPage } + .collect { current -> + val date = getLocalDateByPage(current) + val newDate = LocalDate.of(date.year, date.month, uiState.selectedDate.dayOfMonth) + updateSelectedDate(newDate) } } - Column( - modifier = modifier, - ){ - CalendarTopAppBar( - date = getYearMonthByPage(uiState.currentPage), - isListExpanded = uiState.isListEnabled, - isWeekExpanded = uiState.isWeekEnabled, - onListButtonClicked = onClickListButton, - onMonthNavigationButtonClicked = { direction -> - coroutineScope.launch { - listState.animateScrollToItem( - index = listState.firstVisibleItemIndex + direction, - ) + CompositionLocalProvider( + LocalPagerState provides pagerState + ) { + Column( + modifier = modifier, + ) { + CalendarTopAppBar( + date = getYearMonthByPage(pagerState.settledPage), + isListExpanded = uiState.isListEnabled, + onListButtonClicked = onClickListButton, + onMonthNavigationButtonClicked = { direction -> + coroutineScope.launch { + pagerState.animateScrollToPage( + page = pagerState.settledPage + direction, + animationSpec = tween(500) + ) + } } - } - ) - ScreenTransition( - targetState = !uiState.isListEnabled, - transitionOne = slideInHorizontally { fullWidth -> -fullWidth } togetherWith - slideOutHorizontally { fullWidth -> fullWidth }, - transitionTwo = slideInHorizontally { fullWidth -> fullWidth } togetherWith - slideOutHorizontally { fullWidth -> -fullWidth }, - contentOne = { - Column( - modifier = Modifier - .fillMaxSize() - ) { - WeekDaysHeader() + ) + ScreenTransition( + targetState = !uiState.isListEnabled, + transitionOne = slideInHorizontally { fullWidth -> -fullWidth } togetherWith + slideOutHorizontally { fullWidth -> fullWidth }, + transitionTwo = slideInHorizontally { fullWidth -> fullWidth } togetherWith + slideOutHorizontally { fullWidth -> -fullWidth }, + contentOne = { + Column( + modifier = Modifier + .fillMaxSize() + ) { + WeekDaysHeader() - HorizontalDivider( - thickness = 1.dp, - color = Grey200 - ) + HorizontalDivider( + thickness = 1.dp, + color = Grey200 + ) - ScreenTransition( - targetState = !uiState.isWeekEnabled, - transitionOne = slideInVertically { fullHeight -> -fullHeight } togetherWith - slideOutVertically { fullHeight -> fullHeight }, - transitionTwo = slideInVertically { fullHeight -> fullHeight } togetherWith - slideOutVertically { fullHeight -> -fullHeight }, - contentOne = { - CalendarMonthRoute( - listState = listState, - pages = uiState.calendarModel.pageCount, - selectedDate = uiState.selectedDate, - updateSelectedDate = updateSelectedDate, - modifier = Modifier - .fillMaxSize() - .background(White), - ) - }, - contentTwo = { - CalendarWeekRoute( - calendarUiState = uiState, - modifier = Modifier - .fillMaxSize(), - navigateUp = disableWeekVisibility, - navigateToAnnouncement = navigateToAnnouncement, - updateSelectedDate = updateSelectedDate - ) - } + ScreenTransition( + targetState = !uiState.isWeekEnabled, + transitionOne = slideInVertically { fullHeight -> -fullHeight } togetherWith + slideOutVertically { fullHeight -> fullHeight }, + transitionTwo = slideInVertically { fullHeight -> fullHeight } togetherWith + slideOutVertically { fullHeight -> -fullHeight }, + contentOne = { + CalendarMonthRoute( + selectedDate = uiState.selectedDate, + updateSelectedDate = { newDate -> + if(!pagerState.isScrollInProgress) + onClickNewDate(newDate) + }, + modifier = Modifier + .fillMaxSize() + .background(White), + ) + }, + contentTwo = { + CalendarWeekRoute( + calendarUiState = uiState, + modifier = Modifier + .fillMaxSize(), + navigateUp = disableWeekVisibility, + navigateToAnnouncement = navigateToAnnouncement, + updateSelectedDate = onClickNewDate + ) + } + ) + } + }, + contentTwo = { + CalendarListRoute( + navigateToAnnouncement = navigateToAnnouncement, + navigateUp = disableListVisibility, + modifier = Modifier + .fillMaxSize() ) - } - }, - contentTwo = { - CalendarListRoute( - listState = listState, - pages = uiState.calendarModel.pageCount, - navigateToAnnouncement = navigateToAnnouncement, - navigateUp = disableListVisibility, - modifier = Modifier - .fillMaxSize() - ) - }, - ) + }, + ) + } } } diff --git a/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt b/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt index 4b525140a..5280ae0af 100644 --- a/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt +++ b/feature/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt @@ -16,30 +16,32 @@ class CalendarViewModel @Inject constructor() : ViewModel() { private var _uiState: MutableStateFlow = MutableStateFlow(CalendarUiState()) val uiState get() = _uiState.asStateFlow() - fun updateSelectedDate(date: LocalDate) = viewModelScope.launch { - if (_uiState.value.selectedDate != date) { + fun onSelectNewDate(selectedDate: LocalDate) = viewModelScope.launch { + if (_uiState.value.selectedDate == selectedDate) { _uiState.update { currentState -> currentState.copy( - selectedDate = date + isWeekEnabled = !_uiState.value.isWeekEnabled ) } - updateWeekVisibility(true) } else { - updateWeekVisibility(!_uiState.value.isWeekEnabled) + _uiState.update { currentState -> + currentState.copy( + selectedDate = selectedDate, + isWeekEnabled = true + ) + } } } - fun updatePage(page: Int) = viewModelScope.launch { + fun updateSelectedDate(date: LocalDate) = viewModelScope.launch { _uiState.update { currentState -> currentState.copy( - currentPage = page + selectedDate = date ) } } - fun updateListVisibility( - visibility: Boolean - ) { + fun updateListVisibility(visibility: Boolean) = viewModelScope.launch { _uiState.update { currentState -> currentState.copy( isListEnabled = visibility @@ -47,9 +49,7 @@ class CalendarViewModel @Inject constructor() : ViewModel() { } } - fun updateWeekVisibility( - visibility: Boolean - ) { + fun updateWeekVisibility(visibility: Boolean) = viewModelScope.launch { _uiState.update { currentState -> currentState.copy( isWeekEnabled = visibility diff --git a/feature/src/main/java/com/terning/feature/calendar/calendar/model/CalendarDefault.kt b/feature/src/main/java/com/terning/feature/calendar/calendar/model/CalendarDefault.kt deleted file mode 100644 index 1d2cf981a..000000000 --- a/feature/src/main/java/com/terning/feature/calendar/calendar/model/CalendarDefault.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.terning.feature.calendar.calendar.model - -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.gestures.FlingBehavior -import androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider -import androidx.compose.foundation.gestures.snapping.SnapPosition -import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember - -internal object CalendarDefaults { - /** - * Returns the fling behavior for the given [LazyListState]. - * From Github [https://github.com/kizitonwose/Calendar] - */ - @OptIn(ExperimentalFoundationApi::class) - @Composable - fun flingBehavior(state: LazyListState): FlingBehavior { - val snappingLayout = remember(state) { - val provider = SnapLayoutInfoProvider(state, SnapPosition.Start) - CalendarSnapLayoutInfoProvider(provider) - } - return rememberSnapFlingBehavior(snappingLayout) - } -} - -@ExperimentalFoundationApi -@Suppress("FunctionName") -private fun CalendarSnapLayoutInfoProvider( - snapLayoutInfoProvider: SnapLayoutInfoProvider, -): SnapLayoutInfoProvider = object : SnapLayoutInfoProvider by snapLayoutInfoProvider { - override fun calculateApproachOffset(velocity: Float, decayOffset: Float): Float = 0f -} \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt b/feature/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt index e4d75e7ef..6231be95b 100644 --- a/feature/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt +++ b/feature/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt @@ -1,11 +1,16 @@ package com.terning.feature.calendar.calendar.model +import androidx.compose.foundation.pager.PagerState +import androidx.compose.runtime.compositionLocalOf import java.time.LocalDate data class CalendarUiState( val selectedDate: LocalDate = LocalDate.now(), val calendarModel: CalendarModel = CalendarModel(), - val currentPage: Int = 0, val isListEnabled: Boolean = false, val isWeekEnabled: Boolean = false ) + +val LocalPagerState = compositionLocalOf { + error("No PagerState provided") +} diff --git a/feature/src/main/java/com/terning/feature/calendar/calendar/navigation/CalendarNavigation.kt b/feature/src/main/java/com/terning/feature/calendar/calendar/navigation/CalendarNavigation.kt index 7aa5db891..61c158402 100644 --- a/feature/src/main/java/com/terning/feature/calendar/calendar/navigation/CalendarNavigation.kt +++ b/feature/src/main/java/com/terning/feature/calendar/calendar/navigation/CalendarNavigation.kt @@ -1,7 +1,5 @@ package com.terning.feature.calendar.calendar.navigation -import androidx.compose.animation.EnterTransition -import androidx.compose.animation.ExitTransition import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.padding import androidx.compose.ui.Modifier @@ -26,20 +24,7 @@ fun NavGraphBuilder.calendarNavGraph( navHostController: NavController, paddingValues: PaddingValues ) { - composable( - exitTransition = { - ExitTransition.None - }, - popEnterTransition = { - EnterTransition.None - }, - enterTransition = { - EnterTransition.None - }, - popExitTransition = { - ExitTransition.None - } - ) { + composable { CalendarRoute( modifier = Modifier.padding(paddingValues), navigateToAnnouncement = navHostController::navigateIntern diff --git a/feature/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt b/feature/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt index 6e145abbc..cddf094bd 100644 --- a/feature/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt +++ b/feature/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt @@ -3,15 +3,14 @@ package com.terning.feature.calendar.list import androidx.activity.compose.BackHandler import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxHeight 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.foundation.lazy.LazyListState -import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.PagerState import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -33,35 +32,32 @@ import com.terning.core.designsystem.theme.Back import com.terning.core.designsystem.theme.Black import com.terning.core.designsystem.theme.Grey400 import com.terning.core.designsystem.theme.TerningTheme -import com.terning.core.designsystem.theme.White import com.terning.core.extension.getFullDateStringInKorean import com.terning.core.extension.isListNotEmpty import com.terning.core.extension.toast import com.terning.core.state.UiState import com.terning.domain.entity.calendar.CalendarScrapDetail import com.terning.feature.R -import com.terning.feature.calendar.calendar.model.CalendarDefaults.flingBehavior import com.terning.feature.calendar.calendar.model.CalendarModel.Companion.getLocalDateByPage +import com.terning.feature.calendar.calendar.model.LocalPagerState import com.terning.feature.calendar.list.component.CalendarScrapList import com.terning.feature.calendar.list.model.CalendarListUiState import com.terning.feature.dialog.cancel.ScrapCancelDialog import com.terning.feature.dialog.detail.ScrapDialog -import kotlinx.coroutines.flow.distinctUntilChanged import java.time.LocalDate @Composable fun CalendarListRoute( - pages: Int, - listState: LazyListState, modifier: Modifier = Modifier, navigateUp: () -> Unit, navigateToAnnouncement: (Long) -> Unit, viewModel: CalendarListViewModel = hiltViewModel() ) { + val pagerState = LocalPagerState.current val lifecycleOwner = LocalLifecycleOwner.current val uiState by viewModel.uiState.collectAsStateWithLifecycle(lifecycleOwner) - val context = LocalContext.current + LaunchedEffect(viewModel.sideEffect, lifecycleOwner) { viewModel.sideEffect.flowWithLifecycle(lifecycle = lifecycleOwner.lifecycle) .collect { sideEffect -> @@ -71,12 +67,10 @@ fun CalendarListRoute( } } - LaunchedEffect(key1 = listState) { - snapshotFlow { listState.firstVisibleItemIndex } - .distinctUntilChanged() - .collect { - val page = listState.firstVisibleItemIndex - val date = getLocalDateByPage(page) + LaunchedEffect(key1 = pagerState) { + snapshotFlow { pagerState.settledPage } + .collect { settled -> + val date = getLocalDateByPage(settled) viewModel.updateCurrentDate(date) viewModel.getScrapMonthList(date) } @@ -87,24 +81,11 @@ fun CalendarListRoute( } CalendarListScreen( - pages = pages, - listState = listState, + pagerState = pagerState, uiState = uiState, modifier = modifier, - navigateToAnnouncement = { announcementId -> - navigateToAnnouncement(announcementId) - viewModel.updateInternDialogVisibility(false) - }, - onDismissCancelDialog = { isCancelled -> - viewModel.updateScrapCancelDialogVisibility(false) - if (isCancelled) { viewModel.getScrapMonthList(uiState.currentDate) } - }, - onDismissInternDialog = { viewModel.updateInternDialogVisibility(false) }, - onClickChangeColor = { - viewModel.getScrapMonthList(uiState.currentDate) - }, onClickScrapButton = { scrapId -> - with(viewModel){ + with(viewModel) { updateAnnouncementId(scrapId) updateScrapCancelDialogVisibility(true) } @@ -112,7 +93,32 @@ fun CalendarListRoute( onClickInternship = { calendarScrapDetail -> with(viewModel) { updateInternshipModel(calendarScrapDetail) - updateInternDialogVisibility(true) + updateScrapDetailDialogVisibility(true) + } + } + ) + + CalendarListScrapPatchDialog( + currentDate = uiState.currentDate, + dialogVisibility = uiState.scrapDetailDialogVisibility, + internshipModel = uiState.internshipModel, + navigateToAnnouncement = { announcementId -> + navigateToAnnouncement(announcementId) + viewModel.updateScrapDetailDialogVisibility(false) + }, + onDismissInternDialog = { viewModel.updateScrapDetailDialogVisibility(false) }, + onClickChangeColor = { + viewModel.getScrapMonthList(uiState.currentDate) + }, + ) + + CalendarListScrapCancelDialog( + scrapVisibility = uiState.scrapCancelDialogVisibility, + internshipAnnouncementId = uiState.internshipAnnouncementId, + onDismissCancelDialog = { isCancelled -> + viewModel.updateScrapCancelDialogVisibility(false) + if (isCancelled) { + viewModel.getScrapMonthList(uiState.currentDate) } } ) @@ -120,134 +126,73 @@ fun CalendarListRoute( @Composable private fun CalendarListScreen( - pages: Int, - listState: LazyListState, + pagerState: PagerState, uiState: CalendarListUiState, - navigateToAnnouncement: (Long) -> Unit, - onDismissCancelDialog: (Boolean) -> Unit, - onDismissInternDialog: () -> Unit, - onClickChangeColor: () -> Unit, onClickInternship: (CalendarScrapDetail) -> Unit, onClickScrapButton: (Long) -> Unit, modifier: Modifier = Modifier ) { - Box { - LazyRow( - modifier = modifier - .background(White), - state = listState, - userScrollEnabled = true, - flingBehavior = flingBehavior( - state = listState - ) - ) { - items(pages) { page -> - val getDate = getLocalDateByPage(page) + HorizontalPager( + state = pagerState, + modifier = modifier + ) { page -> + val getDate = getLocalDateByPage(page) - LazyColumn( - modifier = Modifier - .fillParentMaxWidth() - .fillMaxHeight() - .background(Back) - ) { - when (uiState.loadState) { - UiState.Loading -> { - item { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { - Text( - modifier = Modifier - .padding(top = 42.dp) - .fillMaxWidth(), - text = stringResource(id = R.string.calendar_text_friday), - textAlign = TextAlign.Center, - style = TerningTheme.typography.body5, - color = Grey400 - ) - } - } - } - UiState.Empty -> { - item { - Column( - modifier = Modifier.fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - CalendarListEmpty() - } - } + LazyColumn( + modifier = Modifier + .fillMaxSize() + .fillMaxHeight() + .background(Back) + ) { + when (uiState.loadState) { + UiState.Loading -> {} + UiState.Empty -> { + item { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + CalendarListEmpty() } + } + } - is UiState.Failure -> {} - is UiState.Success -> { - val scrapMap = uiState.loadState.data - items(getDate.lengthOfMonth()) { day -> - val currentDate = LocalDate.of(getDate.year, getDate.monthValue, day + 1) - val dateInKorean = currentDate.getFullDateStringInKorean() + is UiState.Failure -> {} + is UiState.Success -> { + val scrapMap = uiState.loadState.data + items(getDate.lengthOfMonth()) { day -> + val currentDate = + LocalDate.of(getDate.year, getDate.monthValue, day + 1) + val dateInKorean = currentDate.getFullDateStringInKorean() - if (scrapMap[dateInKorean].isListNotEmpty()) { - Text( - text = dateInKorean, - style = TerningTheme.typography.title5, - color = Black, - modifier = Modifier - .padding(start = 24.dp, top = 16.dp, bottom = 15.dp) - ) + if (scrapMap[dateInKorean].isListNotEmpty()) { + Text( + text = dateInKorean, + style = TerningTheme.typography.title5, + color = Black, + modifier = Modifier + .padding(start = 24.dp, top = 16.dp, bottom = 15.dp) + ) - CalendarScrapList( - selectedDate = currentDate, - scrapList = scrapMap[dateInKorean].orEmpty(), - onScrapButtonClicked = onClickScrapButton, - onInternshipClicked = onClickInternship, - isFromList = true, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 24.dp) - ) - } - } + CalendarScrapList( + selectedDate = currentDate, + scrapList = scrapMap[dateInKorean].orEmpty(), + onScrapButtonClicked = onClickScrapButton, + onInternshipClicked = onClickInternship, + isFromList = true, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 24.dp) + ) } } } } } } - - if (uiState.scrapDialogVisibility) { - uiState.internshipAnnouncementId?.run { - ScrapCancelDialog( - internshipAnnouncementId = this, - onDismissRequest = onDismissCancelDialog - ) - } - } - - if (uiState.internDialogVisibility) { - uiState.internshipModel?.let { - val scrapColor = Color( - android.graphics.Color.parseColor( - uiState.internshipModel.color - ) - ) - ScrapDialog( - title = uiState.internshipModel.title, - scrapColor = scrapColor, - deadline = uiState.currentDate.getFullDateStringInKorean(), - startYearMonth = uiState.internshipModel.startYearMonth, - workingPeriod = uiState.internshipModel.workingPeriod, - internshipAnnouncementId = uiState.internshipModel.internshipAnnouncementId, - companyImage = uiState.internshipModel.companyImage, - isScrapped = true, - onDismissRequest = onDismissInternDialog, - onClickChangeColor = onClickChangeColor, - onClickNavigateButton = navigateToAnnouncement - ) - } - } } + @Composable private fun CalendarListEmpty( modifier: Modifier = Modifier @@ -261,8 +206,7 @@ private fun CalendarListEmpty( ) Text( - modifier = modifier - .fillMaxWidth(), + modifier = modifier.fillMaxWidth(), text = stringResource(id = R.string.calendar_empty_scrap), textAlign = TextAlign.Center, style = TerningTheme.typography.body5, @@ -270,4 +214,51 @@ private fun CalendarListEmpty( ) } +@Composable +private fun CalendarListScrapCancelDialog( + scrapVisibility: Boolean, + internshipAnnouncementId: Long?, + onDismissCancelDialog: (Boolean) -> Unit +) { + if (scrapVisibility) { + internshipAnnouncementId?.run { + ScrapCancelDialog( + internshipAnnouncementId = this, + onDismissRequest = onDismissCancelDialog + ) + } + } +} +@Composable +private fun CalendarListScrapPatchDialog( + currentDate: LocalDate, + dialogVisibility: Boolean, + internshipModel: CalendarScrapDetail?, + navigateToAnnouncement: (Long) -> Unit, + onDismissInternDialog: () -> Unit, + onClickChangeColor: () -> Unit, +) { + if (dialogVisibility) { + internshipModel?.let { internship -> + val scrapColor = Color( + android.graphics.Color.parseColor( + internship.color + ) + ) + ScrapDialog( + title = internship.title, + scrapColor = scrapColor, + deadline = currentDate.getFullDateStringInKorean(), + startYearMonth = internship.startYearMonth, + workingPeriod = internship.workingPeriod, + internshipAnnouncementId = internship.internshipAnnouncementId, + companyImage = internship.companyImage, + isScrapped = true, + onDismissRequest = onDismissInternDialog, + onClickChangeColor = onClickChangeColor, + onClickNavigateButton = navigateToAnnouncement + ) + } + } +} diff --git a/feature/src/main/java/com/terning/feature/calendar/list/CalendarListViewModel.kt b/feature/src/main/java/com/terning/feature/calendar/list/CalendarListViewModel.kt index 6491ae47a..ffd9f161b 100644 --- a/feature/src/main/java/com/terning/feature/calendar/list/CalendarListViewModel.kt +++ b/feature/src/main/java/com/terning/feature/calendar/list/CalendarListViewModel.kt @@ -21,52 +21,57 @@ import javax.inject.Inject @HiltViewModel class CalendarListViewModel @Inject constructor( private val calendarRepository: CalendarRepository -): ViewModel(){ +) : ViewModel() { private val _uiState = MutableStateFlow(CalendarListUiState()) val uiState = _uiState.asStateFlow() private val _sideEffect: MutableSharedFlow = MutableSharedFlow() val sideEffect = _sideEffect.asSharedFlow() - fun updateCurrentDate(date: LocalDate) { - _uiState.update { currentState -> - currentState.copy( - currentDate = date - ) + fun updateCurrentDate(date: LocalDate) = + viewModelScope.launch { + _uiState.update { currentState -> + currentState.copy( + currentDate = date + ) + } } - } - fun updateScrapCancelDialogVisibility(visibility: Boolean) { - _uiState.update { currentState -> - currentState.copy( - scrapDialogVisibility = visibility - ) + fun updateAnnouncementId(announcementId: Long? = null) = + viewModelScope.launch { + _uiState.update { currentState -> + currentState.copy( + internshipAnnouncementId = announcementId + ) + } } - } - fun updateAnnouncementId(announcementId: Long? = null) { - _uiState.update { currentState -> - currentState.copy( - internshipAnnouncementId = announcementId - ) + fun updateScrapCancelDialogVisibility(visibility: Boolean) = + viewModelScope.launch { + _uiState.update { currentState -> + currentState.copy( + scrapCancelDialogVisibility = visibility + ) + } } - } - fun updateInternDialogVisibility(visibility: Boolean) { - _uiState.update { currentState -> - currentState.copy( - internDialogVisibility = visibility - ) + fun updateScrapDetailDialogVisibility(visibility: Boolean) = + viewModelScope.launch { + _uiState.update { currentState -> + currentState.copy( + scrapDetailDialogVisibility = visibility + ) + } } - } - fun updateInternshipModel(scrapDetailModel: CalendarScrapDetail?) { - _uiState.update { currentState -> - currentState.copy( - internshipModel = scrapDetailModel - ) + fun updateInternshipModel(scrapDetailModel: CalendarScrapDetail?) = + viewModelScope.launch { + _uiState.update { currentState -> + currentState.copy( + internshipModel = scrapDetailModel + ) + } } - } fun getScrapMonthList( date: LocalDate diff --git a/feature/src/main/java/com/terning/feature/calendar/list/component/CalendarScrapList.kt b/feature/src/main/java/com/terning/feature/calendar/list/component/CalendarScrapList.kt index a2ff8bb49..6ac83ab5b 100644 --- a/feature/src/main/java/com/terning/feature/calendar/list/component/CalendarScrapList.kt +++ b/feature/src/main/java/com/terning/feature/calendar/list/component/CalendarScrapList.kt @@ -2,19 +2,12 @@ package com.terning.feature.calendar.list.component import androidx.compose.foundation.layout.Column 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.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.terning.core.designsystem.theme.Black -import com.terning.core.designsystem.theme.TerningTheme -import com.terning.core.extension.getDateStringInKorean -import com.terning.core.extension.isListNotEmpty import com.terning.domain.entity.calendar.CalendarScrapDetail import java.time.LocalDate diff --git a/feature/src/main/java/com/terning/feature/calendar/list/model/CalendarListUiState.kt b/feature/src/main/java/com/terning/feature/calendar/list/model/CalendarListUiState.kt index 1e7fb236f..ca214a28f 100644 --- a/feature/src/main/java/com/terning/feature/calendar/list/model/CalendarListUiState.kt +++ b/feature/src/main/java/com/terning/feature/calendar/list/model/CalendarListUiState.kt @@ -7,8 +7,8 @@ import java.time.LocalDate data class CalendarListUiState( val loadState: UiState>> = UiState.Loading, val currentDate: LocalDate = LocalDate.now(), - val scrapDialogVisibility: Boolean = false, - val internDialogVisibility: Boolean = false, + val scrapCancelDialogVisibility: Boolean = false, + val scrapDetailDialogVisibility: Boolean = false, val internshipAnnouncementId: Long? = null, val internshipModel: CalendarScrapDetail? = null ) \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt b/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt index 5ebbabdd4..b0bade11e 100644 --- a/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt +++ b/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt @@ -1,7 +1,8 @@ package com.terning.feature.calendar.month -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.PagerState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -14,25 +15,22 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.flowWithLifecycle import com.terning.core.extension.toast import com.terning.core.state.UiState -import com.terning.domain.entity.calendar.CalendarScrap -import com.terning.feature.calendar.calendar.model.CalendarDefaults.flingBehavior import com.terning.feature.calendar.calendar.model.CalendarModel.Companion.getLocalDateByPage -import com.terning.feature.calendar.month.model.MonthModel +import com.terning.feature.calendar.calendar.model.LocalPagerState import com.terning.feature.calendar.month.component.CalendarMonth import com.terning.feature.calendar.month.model.CalendarMonthUiState -import kotlinx.coroutines.flow.distinctUntilChanged +import com.terning.feature.calendar.month.model.MonthModel import java.time.LocalDate import java.time.YearMonth @Composable fun CalendarMonthRoute( - listState: LazyListState, - pages: Int, selectedDate: LocalDate, updateSelectedDate: (LocalDate) -> Unit, modifier: Modifier = Modifier, viewModel: CalendarMonthViewModel = hiltViewModel() ) { + val pagerState = LocalPagerState.current val context = LocalContext.current val lifecycleOwner = LocalLifecycleOwner.current val monthUiState by viewModel.uiState.collectAsStateWithLifecycle(lifecycleOwner) @@ -46,21 +44,17 @@ fun CalendarMonthRoute( } } - LaunchedEffect(key1 = listState) { - snapshotFlow { listState.firstVisibleItemIndex } - .distinctUntilChanged() - .collect { - val page = listState.firstVisibleItemIndex - val date = getLocalDateByPage(page) - viewModel.getScrapMonth(date.year, date.monthValue) + LaunchedEffect(key1 = pagerState) { + snapshotFlow { pagerState.currentPage } + .collect { currentPage-> + viewModel.getScrapMonth(currentPage) } } CalendarMonthScreen( + pagerState = pagerState, selectedDate = selectedDate, - calendarMonthUiState = monthUiState, - listState = listState, - pages = pages, + uiState = monthUiState, updateSelectedDate = updateSelectedDate, modifier = modifier ) @@ -68,62 +62,33 @@ fun CalendarMonthRoute( @Composable private fun CalendarMonthScreen( - listState: LazyListState, - calendarMonthUiState: CalendarMonthUiState, - pages: Int, + pagerState: PagerState, selectedDate: LocalDate, + uiState: CalendarMonthUiState, updateSelectedDate: (LocalDate) -> Unit, modifier: Modifier = Modifier, ) { - when (calendarMonthUiState.loadState) { - UiState.Loading -> {} - UiState.Empty -> {} - is UiState.Failure -> {} - is UiState.Success -> { - val scrapMap = calendarMonthUiState.loadState.data - MonthSuccessScreen( - pages = pages, - listState = listState, - scrapMap = scrapMap, - onDateSelected = updateSelectedDate, - selectedDate = selectedDate, - modifier = modifier - ) - } - } -} + HorizontalPager( + state = pagerState, + modifier = modifier.fillMaxSize() + ) {page -> + val date = getLocalDateByPage(page) + val monthModel = MonthModel(YearMonth.of(date.year, date.month)) -@Composable -private fun MonthSuccessScreen( - pages: Int, - listState: LazyListState, - selectedDate: LocalDate, - scrapMap: Map>, - onDateSelected: (LocalDate) -> Unit, - modifier: Modifier = Modifier, -) { - LazyRow( - modifier = modifier, - state = listState, - userScrollEnabled = true, - flingBehavior = flingBehavior( - state = listState + CalendarMonth( + modifier = Modifier.fillMaxSize(), + onDateSelected = updateSelectedDate, + monthModel = monthModel, + selectedDate = selectedDate, + isWeekEnabled = false, + scrapMap = when (uiState.loadState) { + UiState.Loading -> emptyMap() + UiState.Empty -> emptyMap() + is UiState.Failure -> emptyMap() + is UiState.Success -> uiState.loadState.data + }, ) - ) { - items(pages) { page -> - val date = getLocalDateByPage(page) - val monthModel = MonthModel(YearMonth.of(date.year, date.month)) - - CalendarMonth( - modifier = Modifier.fillParentMaxSize(), - onDateSelected = onDateSelected, - monthModel = monthModel, - scrapMap = scrapMap, - selectedDate = selectedDate, - isWeekEnabled = false - ) - } } } diff --git a/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthViewModel.kt b/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthViewModel.kt index fbcd6dcb1..c3307f779 100644 --- a/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthViewModel.kt +++ b/feature/src/main/java/com/terning/feature/calendar/month/CalendarMonthViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope import com.terning.core.state.UiState import com.terning.domain.repository.CalendarRepository import com.terning.feature.R +import com.terning.feature.calendar.calendar.model.CalendarModel.Companion.getLocalDateByPage import com.terning.feature.calendar.month.model.CalendarMonthUiState import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers @@ -27,9 +28,10 @@ class CalendarMonthViewModel @Inject constructor( val sideEffect = _sideEffect.asSharedFlow() fun getScrapMonth( - year: Int, month: Int + currentPage: Int ) = viewModelScope.launch(Dispatchers.IO) { - calendarRepository.getScrapMonth(year, month) + val date = getLocalDateByPage(currentPage) + calendarRepository.getScrapMonth(date.year, date.monthValue) .fold( onSuccess = { _uiState.update { currentState -> diff --git a/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt b/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt index ca882549f..206530448 100644 --- a/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt +++ b/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt @@ -4,8 +4,11 @@ import androidx.activity.compose.BackHandler import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Card import androidx.compose.material3.Text @@ -41,6 +44,7 @@ import com.terning.core.state.UiState import com.terning.domain.entity.calendar.CalendarScrapDetail import com.terning.feature.R import com.terning.feature.calendar.calendar.model.CalendarUiState +import com.terning.feature.calendar.calendar.model.LocalPagerState import com.terning.feature.calendar.list.component.CalendarScrapList import com.terning.feature.calendar.week.component.HorizontalCalendarWeek import com.terning.feature.calendar.week.model.CalendarWeekUiState @@ -58,6 +62,7 @@ fun CalendarWeekRoute( modifier: Modifier = Modifier, viewModel: CalendarWeekViewModel = hiltViewModel() ) { + val pagerState = LocalPagerState.current val lifecycleOwner = LocalLifecycleOwner.current val uiState by viewModel.uiState.collectAsStateWithLifecycle(lifecycleOwner) @@ -72,11 +77,7 @@ fun CalendarWeekRoute( } LaunchedEffect(key1 = calendarUiState.selectedDate) { - viewModel.updateSelectedDate(selectedDate = calendarUiState.selectedDate) - } - - LaunchedEffect(key1 = uiState.selectedDate) { - viewModel.getScrapWeekList(selectedDate = uiState.selectedDate) + viewModel.getScrapWeekList(selectedDate = calendarUiState.selectedDate) } BackHandler { @@ -85,21 +86,10 @@ fun CalendarWeekRoute( CalendarWeekScreen( modifier = modifier, + pagerState = pagerState, uiState = uiState, selectedDate = calendarUiState.selectedDate, updateSelectedDate = updateSelectedDate, - navigateToAnnouncement = { announcementId -> - navigateToAnnouncement(announcementId) - viewModel.updateInternDialogVisibility(false) - }, - onDismissCancelDialog = { isCancelled -> - viewModel.updateScrapCancelDialogVisibility(false) - if (isCancelled) { - viewModel.getScrapWeekList(uiState.selectedDate) - } - }, - onDismissInternDialog = { viewModel.updateInternDialogVisibility(false) }, - onClickChangeColor = { viewModel.getScrapWeekList(uiState.selectedDate) }, onClickScrapButton = { scrapId -> with(viewModel) { updateInternshipAnnouncementId(scrapId) @@ -108,24 +98,46 @@ fun CalendarWeekRoute( }, onClickInternship = { scrapDetail -> with(viewModel) { - updateInternDialogVisibility(true) + updateScrapDetailDialogVisibility(true) updateInternshipModel(scrapDetail) } }, ) + + CalendarWeekScrapPatchDialog( + currentDate = calendarUiState.selectedDate, + dialogVisibility = uiState.scrapDetailDialogVisibility, + internshipModel = uiState.internshipModel, + navigateToAnnouncement = { announcementId -> + navigateToAnnouncement(announcementId) + viewModel.updateScrapDetailDialogVisibility(false) + }, + onDismissInternDialog = { viewModel.updateScrapDetailDialogVisibility(false) }, + onClickChangeColor = { + viewModel.getScrapWeekList(calendarUiState.selectedDate) + }, + ) + + CalendarWeekScrapCancelDialog( + scrapVisibility = uiState.scrapCancelDialogVisibility, + internshipAnnouncementId = uiState.internshipAnnouncementId, + onDismissCancelDialog = { isCancelled -> + viewModel.updateScrapCancelDialogVisibility(false) + if (isCancelled) { + viewModel.getScrapWeekList(calendarUiState.selectedDate) + } + } + ) } @Composable private fun CalendarWeekScreen( uiState: CalendarWeekUiState, + pagerState: PagerState, selectedDate: LocalDate, updateSelectedDate: (LocalDate) -> Unit, - onDismissCancelDialog: (Boolean) -> Unit, - onDismissInternDialog: () -> Unit, - onClickChangeColor: () -> Unit, onClickInternship: (CalendarScrapDetail) -> Unit, onClickScrapButton: (Long) -> Unit, - navigateToAnnouncement: (Long) -> Unit, modifier: Modifier = Modifier ) { var swiped by remember { mutableStateOf(false) } @@ -160,67 +172,46 @@ private fun CalendarWeekScreen( ) } - Text( - text = selectedDate.getDateStringInKorean(), - style = TerningTheme.typography.title5, - color = Black, - modifier = Modifier - .fillMaxWidth() - .padding(start = 24.dp, top = 16.dp, bottom = 15.dp) - ) + HorizontalPager( + state = pagerState, + modifier = Modifier.fillMaxSize(), + userScrollEnabled = false + ) { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = selectedDate.getDateStringInKorean(), + style = TerningTheme.typography.title5, + color = Black, + modifier = Modifier + .fillMaxWidth() + .padding(start = 24.dp, top = 16.dp, bottom = 15.dp) + ) - when (uiState.loadState) { - is UiState.Loading -> {} - is UiState.Empty -> { - CalendarWeekEmpty() - } + when (uiState.loadState) { + is UiState.Loading -> {} + is UiState.Empty -> { + CalendarWeekEmpty() + } - is UiState.Failure -> { - CalendarWeekEmpty() - } + is UiState.Failure -> { + CalendarWeekEmpty() + } - is UiState.Success -> { - CalendarWeekSuccess( - scrapList = uiState.loadState.data.toImmutableList(), - selectedDate = uiState.selectedDate, - onScrapButtonClicked = onClickScrapButton, - onInternshipClicked = onClickInternship - ) + is UiState.Success -> { + CalendarWeekSuccess( + scrapList = uiState.loadState.data.toImmutableList(), + selectedDate = selectedDate, + onScrapButtonClicked = onClickScrapButton, + onInternshipClicked = onClickInternship + ) + } + } } } } - - if (uiState.scrapDialogVisibility) { - uiState.internshipAnnouncementId?.run { - ScrapCancelDialog( - internshipAnnouncementId = this, - onDismissRequest = onDismissCancelDialog - ) - } - } - - if (uiState.internDialogVisibility) { - uiState.internshipModel?.let { - val scrapColor = Color( - android.graphics.Color.parseColor( - uiState.internshipModel.color - ) - ) - ScrapDialog( - title = uiState.internshipModel.title, - scrapColor = scrapColor, - deadline = uiState.selectedDate.getFullDateStringInKorean(), - startYearMonth = uiState.internshipModel.startYearMonth, - workingPeriod = uiState.internshipModel.workingPeriod, - internshipAnnouncementId = uiState.internshipModel.internshipAnnouncementId, - companyImage = uiState.internshipModel.companyImage, - isScrapped = true, - onDismissRequest = onDismissInternDialog, - onClickChangeColor = onClickChangeColor, - onClickNavigateButton = navigateToAnnouncement - ) - } - } } @Composable @@ -262,6 +253,55 @@ private fun CalendarWeekSuccess( ) } +@Composable +private fun CalendarWeekScrapCancelDialog( + scrapVisibility: Boolean, + internshipAnnouncementId: Long?, + onDismissCancelDialog: (Boolean) -> Unit +) { + if (scrapVisibility) { + internshipAnnouncementId?.run { + ScrapCancelDialog( + internshipAnnouncementId = this, + onDismissRequest = onDismissCancelDialog + ) + } + } +} + +@Composable +private fun CalendarWeekScrapPatchDialog( + currentDate: LocalDate, + dialogVisibility: Boolean, + internshipModel: CalendarScrapDetail?, + navigateToAnnouncement: (Long) -> Unit, + onDismissInternDialog: () -> Unit, + onClickChangeColor: () -> Unit, +) { + if (dialogVisibility) { + internshipModel?.let { internship -> + val scrapColor = Color( + android.graphics.Color.parseColor( + internship.color + ) + ) + ScrapDialog( + title = internship.title, + scrapColor = scrapColor, + deadline = currentDate.getFullDateStringInKorean(), + startYearMonth = internship.startYearMonth, + workingPeriod = internship.workingPeriod, + internshipAnnouncementId = internship.internshipAnnouncementId, + companyImage = internship.companyImage, + isScrapped = true, + onDismissRequest = onDismissInternDialog, + onClickChangeColor = onClickChangeColor, + onClickNavigateButton = navigateToAnnouncement + ) + } + } +} + diff --git a/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekViewModel.kt b/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekViewModel.kt index 0ebe403c3..1e4c17d4e 100644 --- a/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekViewModel.kt +++ b/feature/src/main/java/com/terning/feature/calendar/week/CalendarWeekViewModel.kt @@ -21,46 +21,39 @@ import javax.inject.Inject @HiltViewModel class CalendarWeekViewModel @Inject constructor( private val calendarRepository: CalendarRepository -): ViewModel() { +) : ViewModel() { private val _uiState = MutableStateFlow(CalendarWeekUiState()) val uiState = _uiState.asStateFlow() private val _sideEffect: MutableSharedFlow = MutableSharedFlow() val sideEffect = _sideEffect.asSharedFlow() - fun updateSelectedDate(selectedDate: LocalDate) { - _uiState.update { currentState -> - currentState.copy( - selectedDate = selectedDate - ) - } - } - - fun updateScrapCancelDialogVisibility(visibility: Boolean) { - _uiState.update { currentState -> - currentState.copy( - scrapDialogVisibility = visibility - ) + fun updateInternshipAnnouncementId(internshipAnnouncementId: Long? = null) = + viewModelScope.launch { + _uiState.update { currentState -> + currentState.copy( + internshipAnnouncementId = internshipAnnouncementId + ) + } } - } - fun updateInternshipAnnouncementId(internshipAnnouncementId: Long? = null) { + fun updateScrapDetailDialogVisibility(visibility: Boolean) = viewModelScope.launch { _uiState.update { currentState -> currentState.copy( - internshipAnnouncementId = internshipAnnouncementId + scrapDetailDialogVisibility = visibility ) } } - fun updateInternDialogVisibility(visibility: Boolean) { + fun updateScrapCancelDialogVisibility(visibility: Boolean) = viewModelScope.launch { _uiState.update { currentState -> currentState.copy( - internDialogVisibility = visibility + scrapCancelDialogVisibility = visibility ) } } - fun updateInternshipModel(scrapDetailModel: CalendarScrapDetail?) { + fun updateInternshipModel(scrapDetailModel: CalendarScrapDetail?) = viewModelScope.launch { _uiState.update { currentState -> currentState.copy( internshipModel = scrapDetailModel diff --git a/feature/src/main/java/com/terning/feature/calendar/week/component/HorizontalCalendarWeek.kt b/feature/src/main/java/com/terning/feature/calendar/week/component/HorizontalCalendarWeek.kt index 593a927dd..e179cc7cc 100644 --- a/feature/src/main/java/com/terning/feature/calendar/week/component/HorizontalCalendarWeek.kt +++ b/feature/src/main/java/com/terning/feature/calendar/week/component/HorizontalCalendarWeek.kt @@ -8,6 +8,7 @@ import androidx.compose.foundation.lazy.items import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.terning.core.extension.getWeekIndexContainingSelectedDate @@ -31,6 +32,10 @@ fun HorizontalCalendarWeek( pageCount = { monthModel.totalDays / 7 } ) + LaunchedEffect(selectedDate) { + pagerState.animateScrollToPage(selectedDate.getWeekIndexContainingSelectedDate(monthModel.inDays)) + } + HorizontalPager( modifier = modifier, state = pagerState diff --git a/feature/src/main/java/com/terning/feature/calendar/week/model/CalendarWeekUiState.kt b/feature/src/main/java/com/terning/feature/calendar/week/model/CalendarWeekUiState.kt index 08932e1e7..e0326f7e8 100644 --- a/feature/src/main/java/com/terning/feature/calendar/week/model/CalendarWeekUiState.kt +++ b/feature/src/main/java/com/terning/feature/calendar/week/model/CalendarWeekUiState.kt @@ -2,13 +2,11 @@ package com.terning.feature.calendar.week.model import com.terning.core.state.UiState import com.terning.domain.entity.calendar.CalendarScrapDetail -import java.time.LocalDate data class CalendarWeekUiState( val loadState: UiState> = UiState.Loading, - val selectedDate: LocalDate = LocalDate.now(), - val scrapDialogVisibility: Boolean = false, - val internDialogVisibility: Boolean = false, + val scrapCancelDialogVisibility: Boolean = false, + val scrapDetailDialogVisibility: Boolean = false, val internshipAnnouncementId: Long? = null, val internshipModel: CalendarScrapDetail? = null ) \ No newline at end of file