From 0a01f9ddd4001e192951210633d000faa550a49a Mon Sep 17 00:00:00 2001 From: boiledegg Date: Tue, 10 Dec 2024 18:56:29 +0900 Subject: [PATCH 01/10] =?UTF-8?q?[UI/#305]=20=EC=A3=BC=EA=B0=84=EB=8B=AC?= =?UTF-8?q?=EB=A0=A5=20=ED=84=B0=EC=B9=98=EC=98=81=EC=97=AD=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../calendar/week/CalendarWeekScreen.kt | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt index cb7141ef..36d5795a 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt @@ -4,13 +4,17 @@ 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.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size 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.CardDefaults +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -31,13 +35,14 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.flowWithLifecycle -import com.terning.core.designsystem.state.UiState import com.terning.core.designsystem.extension.getDateStringInKorean import com.terning.core.designsystem.extension.getFullDateStringInKorean import com.terning.core.designsystem.extension.swipableVertically import com.terning.core.designsystem.extension.toast +import com.terning.core.designsystem.state.UiState import com.terning.core.designsystem.theme.Back import com.terning.core.designsystem.theme.Black +import com.terning.core.designsystem.theme.Grey200 import com.terning.core.designsystem.theme.Grey400 import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.designsystem.theme.White @@ -160,7 +165,9 @@ private fun CalendarWeekScreen( shape = RoundedCornerShape(bottomStart = 20.dp, bottomEnd = 20.dp), elevation = 1.dp ), - + colors = CardDefaults.cardColors( + containerColor = White + ), shape = RoundedCornerShape(bottomStart = 20.dp, bottomEnd = 20.dp), ) { HorizontalCalendarWeek( @@ -168,7 +175,14 @@ private fun CalendarWeekScreen( onDateSelected = updateSelectedDate, modifier = Modifier .fillMaxWidth() - .background(White) + ) + + Spacer( + modifier = Modifier + .padding(top = 4.dp, bottom = 8.dp) + .size(width = 55.dp, height = 4.dp) + .background(color = Grey200, shape = RoundedCornerShape(2.dp)) + .align(Alignment.CenterHorizontally), ) } From d2ba1a26761cc085e54de9069e4caace673bc409 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Tue, 10 Dec 2024 22:07:51 +0900 Subject: [PATCH 02/10] =?UTF-8?q?[REFACTOR/#305]=20=EB=8B=AC=EB=A0=A5?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EB=AA=A8=EB=8D=B8=20=EC=A0=84=EB=A9=B4?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - TerningCalendarModel 도입 - 기존 static 함수 제거 - MonthModel 및 DayModel 코드 정리 --- .../calendar/calendar/CalendarRoute.kt | 12 +-- .../calendar/component/CalendarDay.kt | 8 +- .../calendar/calendar/model/CalendarModel.kt | 34 -------- .../calendar/model/CalendarUiState.kt | 2 +- .../calendar/calendar/model/DayModel.kt | 19 +++++ .../calendar/calendar/model/MonthModel.kt | 54 +++++++++++++ .../calendar/model/TerningCalendarModel.kt | 78 +++++++++++++++++++ .../calendar/list/CalendarListScreen.kt | 9 ++- .../calendar/month/CalendarMonthScreen.kt | 14 ++-- .../calendar/month/CalendarMonthViewModel.kt | 5 +- .../calendar/month/component/CalendarMonth.kt | 4 +- .../feature/calendar/month/model/DayModel.kt | 10 --- .../calendar/month/model/MonthModel.kt | 55 ------------- .../calendar/week/CalendarWeekScreen.kt | 1 - .../week/component/HorizontalCalendarWeek.kt | 9 ++- 15 files changed, 185 insertions(+), 129 deletions(-) delete mode 100644 feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarModel.kt create mode 100644 feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/DayModel.kt create mode 100644 feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/MonthModel.kt create mode 100644 feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/TerningCalendarModel.kt delete mode 100644 feature/calendar/src/main/java/com/terning/feature/calendar/month/model/DayModel.kt delete mode 100644 feature/calendar/src/main/java/com/terning/feature/calendar/month/model/MonthModel.kt diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt index 5f63d6dc..de9bc1c0 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt @@ -29,8 +29,7 @@ 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.TerningCalendarModel.Companion.LocalCalendarModel import com.terning.feature.calendar.calendar.model.CalendarUiState import com.terning.feature.calendar.calendar.model.LocalPagerState import com.terning.feature.calendar.list.CalendarListRoute @@ -90,7 +89,9 @@ private fun CalendarScreen( LaunchedEffect(key1 = pagerState, key2 = uiState.selectedDate) { snapshotFlow { pagerState.currentPage } .collect { current -> - val date = getLocalDateByPage(current) + //val date = getLocalDateByPage(current) + val date = uiState.calendarModel.getLocalDateByPage(current) + val newDate = LocalDate.of( date.year, @@ -102,13 +103,14 @@ private fun CalendarScreen( } CompositionLocalProvider( - LocalPagerState provides pagerState + LocalPagerState provides pagerState, + LocalCalendarModel provides uiState.calendarModel ) { Column( modifier = modifier, ) { CalendarTopAppBar( - date = getYearMonthByPage(pagerState.settledPage), + date = uiState.calendarModel.getYearMonthByPage(pagerState.settledPage), isListExpanded = uiState.isListEnabled, onListButtonClicked = onClickListButton, onMonthNavigationButtonClicked = { direction -> diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/CalendarDay.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/CalendarDay.kt index 73813311..c54a3b53 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/CalendarDay.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/CalendarDay.kt @@ -20,7 +20,7 @@ import com.terning.core.designsystem.theme.TerningMain import com.terning.core.designsystem.theme.TerningPointTheme import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.designsystem.theme.White -import com.terning.feature.calendar.month.model.DayModel +import com.terning.feature.calendar.calendar.model.DayModel import java.time.LocalDate @Composable @@ -79,19 +79,19 @@ fun CalendarDayPreview() { TerningPointTheme { Row { CalendarDay( - dayData = DayModel(LocalDate.now(), false), + dayData = DayModel(LocalDate.now(), 0, false), isSelected = true, isToday = true, onDateSelected = {} ) CalendarDay( - dayData = DayModel(LocalDate.now(), false), + dayData = DayModel(LocalDate.now(), 0, false), isSelected = false, isToday = true, onDateSelected = {} ) CalendarDay( - dayData = DayModel(LocalDate.now(), false), + dayData = DayModel(LocalDate.now(), 0, false), isSelected = false, isToday = false, onDateSelected = {} diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarModel.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarModel.kt deleted file mode 100644 index 9d5c69e9..00000000 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarModel.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.terning.feature.calendar.calendar.model - -import androidx.compose.runtime.Immutable -import java.time.LocalDate -import java.time.YearMonth - -@Immutable -class CalendarModel internal constructor( - startYear: Int = START_YEAR, - endYear: Int = END_YEAR -) { - private val currentDate = LocalDate.now() - private val startYearDate = LocalDate.of(startYear, 1, 1) - private val endYearDate = LocalDate.of(endYear, 12, 31) - - val pageCount = (endYearDate.year - startYearDate.year) * 12 - val initialPage = (currentDate.year - startYearDate.year) * 12 + currentDate.monthValue - 1 - - companion object { - const val START_YEAR = 2020 - const val END_YEAR = 2030 - - fun getLocalDateByPage(page: Int): LocalDate = LocalDate.of( - START_YEAR + page / 12, - page % 12 + 1, - 1 - ) - - fun getYearMonthByPage(page: Int): YearMonth = YearMonth.of( - START_YEAR + page / 12, - page % 12 + 1, - ) - } -} \ No newline at end of file diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt index 6231be95..5aa07853 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt @@ -6,7 +6,7 @@ import java.time.LocalDate data class CalendarUiState( val selectedDate: LocalDate = LocalDate.now(), - val calendarModel: CalendarModel = CalendarModel(), + val calendarModel: TerningCalendarModel = TerningCalendarModel(), val isListEnabled: Boolean = false, val isWeekEnabled: Boolean = false ) diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/DayModel.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/DayModel.kt new file mode 100644 index 00000000..9c1df5ce --- /dev/null +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/DayModel.kt @@ -0,0 +1,19 @@ +package com.terning.feature.calendar.calendar.model + +import androidx.compose.runtime.Immutable +import java.time.LocalDate + +/** + * 달력의 하루를 나타내는 데이터클래스 모델 + * + * @param date 날짜 + * @param weekIndex 속한 주의 인덱스 + * @param isOutDate 이번 월에 포함되지 않는 날인지에 대한 불리언 값 + */ + +@Immutable +data class DayModel( + val date: LocalDate, + val weekIndex: Int = 0, + val isOutDate: Boolean = false +) \ No newline at end of file diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/MonthModel.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/MonthModel.kt new file mode 100644 index 00000000..41f5a427 --- /dev/null +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/MonthModel.kt @@ -0,0 +1,54 @@ +package com.terning.feature.calendar.calendar.model + +import androidx.compose.runtime.Immutable +import java.time.YearMonth + +/** + * 달력에서 한 달에 대한 정보를 관리하는 데이터 클래스 + * + * @property [inDays] 현재 달에 표시돼야 할 이전 달의 날 수 + * @property [monthDays] 현재 달의 날 수 + * @property [outDays] 현재 달에 표시돼야 할 다음 달의 날 수 + * @property [totalDays] 달에 포함된 할 전체 날 수 + * @property [calendarMonth] [DayModel]로 이뤄진 달의 날들의 목록 + */ + +@Immutable +data class MonthModel( + val yearMonth: YearMonth +) { + private val firstDayOfWeek = yearMonth.atDay(1).dayOfWeek.value + + val inDays = firstDayOfWeek % 7 + val monthDays = yearMonth.lengthOfMonth() + val outDays = (7 - ((inDays + monthDays) % 7)) % 7 + val totalDays = monthDays + inDays + outDays + + private val rows = (0 until totalDays).chunked(7) + + val calendarMonth: List> = + rows.map { week -> week.map { dayOffset -> getDay(dayOffset) } } + + private fun getDay(dayOffset: Int): DayModel { + val firstDayOnCalendar = yearMonth.atDay(1).minusDays(inDays.toLong()) + val date = firstDayOnCalendar.plusDays(dayOffset.toLong()) + val weekIndex = (dayOffset / 7) + val isOutDate = YearMonth.of(date.year, date.monthValue) != yearMonth + + return DayModel(date, weekIndex, isOutDate) + } + + override fun toString(): String { + val yearString = yearMonth.year.toString() + val monthString = yearMonth.monthValue.toString().padStart(2, '0') + + return STRING_FORMAT.format(yearString, monthString) + } + + companion object { + private const val STRING_FORMAT = "%s년 %s월" + } + +} + + diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/TerningCalendarModel.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/TerningCalendarModel.kt new file mode 100644 index 00000000..891f936c --- /dev/null +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/TerningCalendarModel.kt @@ -0,0 +1,78 @@ +package com.terning.feature.calendar.calendar.model + +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.staticCompositionLocalOf +import java.time.LocalDate +import java.time.YearMonth + +/** + * 터닝의 달력 로직을 관리하는 클래스입니다. + * 달력의 시작과 끝 연도를 설정하여 달력의 크기를 지정합니다. + * + * @param startYear 캘린더의 시작 연도 + * @param endYear 캘린더의 끝 연도 + */ + +@Immutable +class TerningCalendarModel ( + private val startYear: Int = DEFAULT_START_YEAR, + private val endYear: Int = DEFAULT_END_YEAR +) { + private val currentDate = LocalDate.now() + private val startYearDate = LocalDate.of(startYear, 1, 1) + private val endYearDate = LocalDate.of(endYear, 12, 31) + + val pageCount = (endYearDate.year - startYearDate.year) * 12 + val initialPage = (currentDate.year - startYearDate.year) * 12 + currentDate.monthValue - 1 + + /** + * 페이지 값을 사용하여 [MonthModel]을 반환합니다. + */ + fun getMonthModelByPage(page: Int): MonthModel { + val localDate = getLocalDateByPage(page) + return getMonthModelByPage(localDate = localDate) + } + + /** + * [LocalDate]를 사용하여 [MonthModel]을 반환합니다. + */ + fun getMonthModelByPage(localDate: LocalDate): MonthModel { + val yearMonth = YearMonth.of(localDate.year, localDate.monthValue) + return getMonthModelByPage(yearMonth = yearMonth) + } + + /** + * [YearMonth]를 사용하여 [MonthModel]을 반환합니다. + */ + fun getMonthModelByPage(yearMonth: YearMonth): MonthModel { + return MonthModel(yearMonth = yearMonth) + } + + /** + * 현재 페이지의 연도, 월, 1일을 반환합니다. + * @return [LocalDate] + */ + fun getLocalDateByPage(page: Int): LocalDate = LocalDate.of( + startYear + page / 12, + page % 12 + 1, + 1 + ) + + /** + * 현재 페이지의 연도, 월을 반환합니다. + * @return [YearMonth] + */ + fun getYearMonthByPage(page: Int): YearMonth = YearMonth.of( + startYear + page / 12, + page % 12 + 1, + ) + + companion object { + private const val DEFAULT_START_YEAR = 2020 + private const val DEFAULT_END_YEAR = 2030 + + val LocalCalendarModel = staticCompositionLocalOf { + error("No CalendarModel provided") + } + } +} \ No newline at end of file diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt index 8178199e..48fc90ce 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt @@ -38,7 +38,7 @@ import com.terning.core.designsystem.theme.Grey400 import com.terning.core.designsystem.theme.TerningTheme import com.terning.domain.calendar.entity.CalendarScrapDetail import com.terning.feature.calendar.R -import com.terning.feature.calendar.calendar.model.CalendarModel.Companion.getLocalDateByPage +import com.terning.feature.calendar.calendar.model.TerningCalendarModel.Companion.LocalCalendarModel import com.terning.feature.calendar.calendar.model.LocalPagerState import com.terning.feature.calendar.list.component.CalendarScrapList import com.terning.feature.calendar.list.model.CalendarListUiState @@ -55,6 +55,7 @@ fun CalendarListRoute( viewModel: CalendarListViewModel = hiltViewModel(), ) { val pagerState = LocalPagerState.current + val calendarModel = LocalCalendarModel.current val lifecycleOwner = LocalLifecycleOwner.current val uiState by viewModel.uiState.collectAsStateWithLifecycle(lifecycleOwner) val context = LocalContext.current @@ -71,7 +72,7 @@ fun CalendarListRoute( LaunchedEffect(key1 = pagerState) { snapshotFlow { pagerState.settledPage } .collect { settled -> - val date = getLocalDateByPage(settled) + val date = calendarModel.getLocalDateByPage(settled) viewModel.updateCurrentDate(date) viewModel.getScrapMonthList(date) } @@ -133,11 +134,13 @@ private fun CalendarListScreen( onClickScrapButton: (Long) -> Unit, modifier: Modifier = Modifier, ) { + val calendarModel = LocalCalendarModel.current + HorizontalPager( state = pagerState, modifier = modifier ) { page -> - val getDate = getLocalDateByPage(page) + val getDate = calendarModel.getLocalDateByPage(page) LazyColumn( modifier = Modifier diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt index 23a57c2b..57e0d46b 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt @@ -15,13 +15,11 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.flowWithLifecycle import com.terning.core.designsystem.state.UiState import com.terning.core.designsystem.extension.toast -import com.terning.feature.calendar.calendar.model.CalendarModel.Companion.getLocalDateByPage +import com.terning.feature.calendar.calendar.model.TerningCalendarModel.Companion.LocalCalendarModel 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 com.terning.feature.calendar.month.model.MonthModel import java.time.LocalDate -import java.time.YearMonth @Composable fun CalendarMonthRoute( @@ -30,6 +28,7 @@ fun CalendarMonthRoute( modifier: Modifier = Modifier, viewModel: CalendarMonthViewModel = hiltViewModel() ) { + val calendarModel = LocalCalendarModel.current val pagerState = LocalPagerState.current val context = LocalContext.current val lifecycleOwner = LocalLifecycleOwner.current @@ -47,7 +46,8 @@ fun CalendarMonthRoute( LaunchedEffect(key1 = pagerState) { snapshotFlow { pagerState.currentPage } .collect { currentPage-> - viewModel.getScrapMonth(currentPage) + val localDate = calendarModel.getLocalDateByPage(currentPage) + viewModel.getScrapMonth(localDate) } } @@ -68,13 +68,13 @@ private fun CalendarMonthScreen( updateSelectedDate: (LocalDate) -> Unit, modifier: Modifier = Modifier, ) { + val calendarModel = LocalCalendarModel.current HorizontalPager( state = pagerState, modifier = modifier.fillMaxSize() - ) {page -> - val date = getLocalDateByPage(page) - val monthModel = MonthModel(YearMonth.of(date.year, date.month)) + ) { page -> + val monthModel = calendarModel.getMonthModelByPage(page = page) CalendarMonth( modifier = Modifier.fillMaxSize(), diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthViewModel.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthViewModel.kt index 0fd23b2e..a5d1eba0 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthViewModel.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthViewModel.kt @@ -5,7 +5,6 @@ import androidx.lifecycle.viewModelScope import com.terning.core.designsystem.state.UiState import com.terning.domain.calendar.repository.CalendarRepository import com.terning.feature.calendar.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 @@ -15,6 +14,7 @@ import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import java.time.LocalDate import javax.inject.Inject @HiltViewModel @@ -28,9 +28,8 @@ class CalendarMonthViewModel @Inject constructor( val sideEffect = _sideEffect.asSharedFlow() fun getScrapMonth( - currentPage: Int + date: LocalDate ) = viewModelScope.launch(Dispatchers.IO) { - val date = getLocalDateByPage(currentPage) calendarRepository.getScrapMonth(date.year, date.monthValue) .fold( onSuccess = { diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonth.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonth.kt index d69eb981..dbd28710 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonth.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonth.kt @@ -18,7 +18,7 @@ import com.terning.core.designsystem.theme.Grey150 import com.terning.core.designsystem.theme.TerningPointTheme import com.terning.domain.calendar.entity.CalendarScrap import com.terning.feature.calendar.calendar.component.CalendarDay -import com.terning.feature.calendar.month.model.MonthModel +import com.terning.feature.calendar.calendar.model.MonthModel import java.time.LocalDate import java.time.YearMonth @@ -36,7 +36,7 @@ internal fun CalendarMonth( .fillMaxSize() .padding(horizontal = 20.dp), ) { - val month = monthModel.calendarMonth.weekDays + val month = monthModel.calendarMonth for (week in month) { Row( modifier = Modifier.weight(1f), diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/month/model/DayModel.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/month/model/DayModel.kt deleted file mode 100644 index 9f3563f8..00000000 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/month/model/DayModel.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.terning.feature.calendar.month.model - -import androidx.compose.runtime.Immutable -import java.time.LocalDate - -@Immutable -data class DayModel( - val date: LocalDate, - val isOutDate: Boolean = false -) \ No newline at end of file diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/month/model/MonthModel.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/month/model/MonthModel.kt deleted file mode 100644 index f9b940cc..00000000 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/month/model/MonthModel.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.terning.feature.calendar.month.model - -import androidx.compose.runtime.Immutable -import com.terning.feature.calendar.month.model.MonthModel.MonthModel -import java.time.YearMonth - -/** - * [MonthModel] is responsible for managing a month's overall characteristics - * it consists of following properties:- - * - * [inDays] represents the number of days in the previous month that should be shown before the first day of the month. - * [outDays] represents the number of days in the next month that should be shown after the last day of the month.] - * [totalDays] represents the total number of days shown on calendar - * [calendarMonth] represents the list of days of the month, a list of [DayModel] - */ - - -@Immutable -data class MonthModel( - val month: YearMonth -) { - private val firstDayOfWeek = month.atDay(1).dayOfWeek.value - private val previousMonth = month.minusMonths(1) - private val nextMonth = month.plusMonths(1) - - val inDays = firstDayOfWeek % 7 - val monthDays = month.lengthOfMonth() - val outDays = (7 - ((inDays + monthDays) % 7)) % 7 - val totalDays = monthDays + inDays + outDays - - private val rows = (0 until totalDays).chunked(7) - - val calendarMonth = - MonthModel(month, rows.map { week -> week.map { dayOffset -> getDay(dayOffset) } }) - - private fun getDay(dayOffset: Int): DayModel { - val firstDayOnCalendar = month.atDay(1).minusDays(inDays.toLong()) - val date = firstDayOnCalendar.plusDays(dayOffset.toLong()) - val isOutDate = YearMonth.of(date.year, date.monthValue) != month - - return DayModel(date, isOutDate) - } - - @Immutable - data class MonthModel( - val yearMonth: YearMonth, - val weekDays: List> - ) { - override fun toString(): String { - return "${yearMonth.year}년 ${yearMonth.monthValue.toString().padStart(2, '0')}월" - } - } -} - - diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt index 36d5795a..799a918d 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt @@ -14,7 +14,6 @@ import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/week/component/HorizontalCalendarWeek.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/week/component/HorizontalCalendarWeek.kt index bc9b6bf6..efb4515e 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/week/component/HorizontalCalendarWeek.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/week/component/HorizontalCalendarWeek.kt @@ -14,9 +14,8 @@ import androidx.compose.ui.unit.dp import com.terning.core.designsystem.extension.getWeekIndexContainingSelectedDate import com.terning.core.designsystem.extension.isToday import com.terning.feature.calendar.calendar.component.CalendarDay -import com.terning.feature.calendar.month.model.MonthModel +import com.terning.feature.calendar.calendar.model.TerningCalendarModel.Companion.LocalCalendarModel import java.time.LocalDate -import java.time.YearMonth @Composable fun HorizontalCalendarWeek( @@ -24,7 +23,9 @@ fun HorizontalCalendarWeek( onDateSelected: (LocalDate) -> Unit, modifier: Modifier = Modifier ) { - val monthModel = MonthModel(YearMonth.of(selectedDate.year, selectedDate.monthValue)) + val calendarModel = LocalCalendarModel.current + + val monthModel = calendarModel.getMonthModelByPage(selectedDate) val currentWeek = selectedDate.getWeekIndexContainingSelectedDate(monthModel.inDays) val pagerState = rememberPagerState( @@ -46,7 +47,7 @@ fun HorizontalCalendarWeek( .padding(horizontal = 32.dp, vertical = 20.dp), horizontalArrangement = Arrangement.SpaceBetween ) { - items(items = monthModel.calendarMonth.weekDays[page]) { day -> + items(items = monthModel.calendarMonth[page]) { day -> CalendarDay( dayData = day, isSelected = day.date == selectedDate, From 4f25500072289c6b2573955379abc0831010a28a Mon Sep 17 00:00:00 2001 From: boiledegg Date: Thu, 12 Dec 2024 03:09:40 +0900 Subject: [PATCH 03/10] =?UTF-8?q?[UI/#305]=20=EC=BA=98=EB=A6=B0=EB=8D=94?= =?UTF-8?q?=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=84=B8=EB=B6=84?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 월, 주, 일 표시 컴포넌트 재구현 - DayModel 함수 추가 --- .../component/group/CalendarDayGroup.kt | 99 +++++++++++ .../component/group/CalendarMonthGroup.kt | 110 ++++++++++++ .../component/group/CalendarScrapGroup.kt} | 50 +++--- .../component/group/CalendarWeekGroup.kt | 157 ++++++++++++++++++ .../calendar/calendar/model/DayModel.kt | 12 +- 5 files changed, 402 insertions(+), 26 deletions(-) create mode 100644 feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarDayGroup.kt create mode 100644 feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarMonthGroup.kt rename feature/calendar/src/main/java/com/terning/feature/calendar/{month/component/CalendarMonthScrap.kt => calendar/component/group/CalendarScrapGroup.kt} (61%) create mode 100644 feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarWeekGroup.kt diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarDayGroup.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarDayGroup.kt new file mode 100644 index 00000000..ffe34f31 --- /dev/null +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarDayGroup.kt @@ -0,0 +1,99 @@ +package com.terning.feature.calendar.calendar.component.group + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.terning.core.designsystem.theme.Black +import com.terning.core.designsystem.theme.Grey150 +import com.terning.core.designsystem.theme.Grey200 +import com.terning.core.designsystem.theme.TerningMain +import com.terning.core.designsystem.theme.TerningPointTheme +import com.terning.core.designsystem.theme.TerningTheme +import com.terning.core.designsystem.theme.White +import com.terning.feature.calendar.calendar.model.DayModel +import java.time.LocalDate + +/** + * 날짜를 표시하는 컴포넌트 그룹 + * + * @param dayModel 날짜에 대한 정보 + * @param isSelected 해당 날짜가 선택된 날짜인지에 대한 여부 + * @param isToday 해당 날짜가 오늘 날짜인지에 대한 여부 + * @param modifier 수정자 + */ + +@Composable +fun CalendarDayGroup( + dayModel: DayModel, + isSelected: Boolean, + isToday: Boolean, + modifier: Modifier = Modifier, +) { + val backgroundColor = remember(isSelected) { + if (isSelected) TerningMain + else if (isToday) Grey150 + else Color.Transparent + } + + val textColor = remember(isSelected) { + if (dayModel.isOutDate) Grey200 + else if (isSelected) White + else Black + } + + + Box( + modifier = modifier, + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .size(22.dp) + .background( + color = backgroundColor, + shape = CircleShape + ), + contentAlignment = Alignment.Center + ) { + Text( + text = dayModel.date.dayOfMonth.toString(), + color = textColor, + style = TerningTheme.typography.calendar + ) + } + } +} + +@Preview(showBackground = true) +@Composable +fun CalendarDayPreview() { + TerningPointTheme { + Row { + CalendarDayGroup( + dayModel = DayModel(LocalDate.now(), 0, false), + isSelected = true, + isToday = true, + ) + CalendarDayGroup( + dayModel = DayModel(LocalDate.now(), 0, false), + isSelected = false, + isToday = true, + ) + CalendarDayGroup( + dayModel = DayModel(LocalDate.now(), 0, false), + isSelected = false, + isToday = false, + ) + } + } +} \ No newline at end of file diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarMonthGroup.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarMonthGroup.kt new file mode 100644 index 00000000..564a1a56 --- /dev/null +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarMonthGroup.kt @@ -0,0 +1,110 @@ +package com.terning.feature.calendar.calendar.component.group + +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.material3.HorizontalDivider +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.terning.core.designsystem.theme.Grey150 +import com.terning.core.designsystem.theme.TerningPointTheme +import com.terning.core.designsystem.theme.White +import com.terning.domain.calendar.entity.CalendarScrap +import com.terning.feature.calendar.calendar.model.DayModel +import com.terning.feature.calendar.calendar.model.MonthModel +import java.time.LocalDate +import java.time.YearMonth + +/** + * 한 달을 표시하는 컴포넌트 + * + * @param dayModels 한달에 포함된 날들에 대한 데이터 리스트 + * @param isWeekEnabled 주간 달력일 때만 선택된 날에 초록색 마크를 달기 위해 사용하는 부울 변수. + * @param onDateSelected 날이 선택돼었을 때 발생하는 이벤트 + * @param selectedDate 선택된 날 + * @param modifier 수정자 + * @param scrapMap 스크랩 목록과 날짜가 매핑된 목록 + * + */ + +@Composable +internal fun CalendarMonthGroup( + dayModels: List>, + isWeekEnabled: Boolean, + onDateSelected: (DayModel) -> Unit, + selectedDate: DayModel, + modifier: Modifier = Modifier, + scrapMap: Map> = emptyMap() +) { + val scrapCount = remember(dayModels) { + if (dayModels.size == 5) SCRAP_COUNT_WEEK_FIVE + else SCRAP_COUNT_WEEK_SIX + } + + Column( + modifier = modifier + .fillMaxSize() + .background(White) + .padding(horizontal = 20.dp) + + ) { + dayModels.forEach {week -> + CalendarWeekGroup( + dayModels = week, + isWeekEnabled = isWeekEnabled, + onDateSelected = onDateSelected, + selectedDay = selectedDate, + scrapCount = scrapCount, + scrapMap = scrapMap, + modifier = Modifier + .weight(1f) + .padding(top = 16.dp) + ) + + if (dayModels.indexOf(week) != dayModels.lastIndex) { + HorizontalDivider( + thickness = 1.dp, + color = Grey150, + ) + } + } + } +} + + +private const val SCRAP_COUNT_WEEK_SIX = 3 +private const val SCRAP_COUNT_WEEK_FIVE = 4 + +@Preview(showSystemUi = true) +@Composable +private fun CalendarMonthGroupPreview() { + TerningPointTheme { + val monthModel = MonthModel(YearMonth.now()) + + CalendarMonthGroup( + dayModels = monthModel.calendarMonth, + onDateSelected = {}, + selectedDate = DayModel( + date = LocalDate.now(), + weekIndex = 1, + isOutDate = false + ), + scrapMap = mapOf( + "2024-12-11" to listOf( + CalendarScrap( + scrapId = 1, + title = "테스트1", + deadLine = "2024-12-11", + color = "#FF0F0F", + isScrapped = true + ) + ) + ), + isWeekEnabled = false, + ) + } +} \ No newline at end of file diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonthScrap.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarScrapGroup.kt similarity index 61% rename from feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonthScrap.kt rename to feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarScrapGroup.kt index c8771a87..201689b6 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonthScrap.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarScrapGroup.kt @@ -1,10 +1,9 @@ -package com.terning.feature.calendar.month.component +package com.terning.feature.calendar.calendar.component.group import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -19,21 +18,23 @@ import com.terning.core.designsystem.theme.White import com.terning.domain.calendar.entity.CalendarScrap import com.terning.feature.calendar.R -private const val SCRAP_COUNT_WEEK_SIX = 3 -private const val SCRAP_COUNT_WEEK_FIVE = 4 +/** + * 달력 위에 띠지를 표시하는 컴포넌트 + * + * @param scrapCount 한칸에 표시 가능한 최대 스크랩 + * @param scrapLists 스크랩 목록 + */ @Composable -internal fun CalendarMonthScrap( - weekCount: Int, +internal fun CalendarScrapGroup( + scrapCount: Int, + scrapLists: List, modifier: Modifier = Modifier, - scrapLists: List ) { - val scrapCount = if(weekCount == 5) SCRAP_COUNT_WEEK_FIVE else SCRAP_COUNT_WEEK_SIX - - LazyColumn( + Column( modifier = modifier ) { - items(scrapLists.subList(0, scrapCount.coerceAtMost(scrapLists.size))) { scrap -> + scrapLists.subList(0, scrapCount.coerceAtMost(scrapLists.size)).forEach { scrap -> Text( text = scrap.title, style = TerningTheme.typography.button5, @@ -51,17 +52,18 @@ internal fun CalendarMonthScrap( ) ) } - - item { - if (scrapLists.size > scrapCount) { - Text( - text = stringResource(id = R.string.calendar_scrap_overflow, (scrapLists.size - scrapCount)), - style = TerningTheme.typography.detail4, - textAlign = TextAlign.End, - modifier = Modifier.fillMaxWidth() - ) - } + if (scrapLists.size > scrapCount) { + Text( + text = stringResource( + id = R.string.calendar_scrap_overflow, + (scrapLists.size - scrapCount) + ), + style = TerningTheme.typography.detail4, + textAlign = TextAlign.End, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 2.dp) + ) } } -} - +} \ No newline at end of file diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarWeekGroup.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarWeekGroup.kt new file mode 100644 index 00000000..c242f3a8 --- /dev/null +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarWeekGroup.kt @@ -0,0 +1,157 @@ +package com.terning.feature.calendar.calendar.component.group + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import com.terning.core.designsystem.extension.noRippleClickable +import com.terning.core.designsystem.theme.TerningPointTheme +import com.terning.core.designsystem.theme.White +import com.terning.domain.calendar.entity.CalendarScrap +import com.terning.feature.calendar.calendar.model.DayModel +import java.time.LocalDate + +/** + * 일주일을 표시하기 위한 컴포넌트 + * + * @param selectedDay 현재 선택된 날짜 + * @param dayModels 해당 주에 포함된 날짜들에 대한 DayModel 목록 + * @param onDateSelected 날짜를 선택했을 때 호출되는 콜백 + * @param scrapCount 표시 가능한 스크랩 개수 + * @param scrapMap 날짜-스크랩 쌍을 담은 맵 + */ + +@Composable +internal fun CalendarWeekGroup( + dayModels: List, + isWeekEnabled: Boolean, + onDateSelected: (DayModel) -> Unit, + scrapCount: Int, + selectedDay: DayModel, + modifier: Modifier = Modifier, + scrapMap: Map> = emptyMap() +) { + Row( + modifier = modifier + ){ + dayModels.forEach { dayModel -> + Column( + modifier = Modifier + .weight(1f) + .noRippleClickable { + if (!dayModel.isOutDate) { + onDateSelected(dayModel) + } + }, + horizontalAlignment = Alignment.CenterHorizontally + ) { + CalendarDayGroup( + dayModel = dayModel, + isSelected = dayModel == selectedDay && isWeekEnabled, + isToday = dayModel.isToday(), + ) + + if (!dayModel.isOutDate && !isWeekEnabled) { + val scrapMapKey = dayModel.getScrapMapKey() + CalendarScrapGroup( + scrapCount = scrapCount, + scrapLists = scrapMap[scrapMapKey].orEmpty(), + modifier = Modifier.fillMaxWidth() + ) + } + } + } + } +} + +@Preview +@Composable +private fun CalendarWeekGroupNoScrapPreview() { + TerningPointTheme { + var selectedDay by remember { mutableStateOf(DayModel(date = LocalDate.now(), weekIndex = 0, isOutDate = false)) } + + CalendarWeekGroup( + selectedDay = selectedDay, + isWeekEnabled = false, + dayModels = listOf( + DayModel(date = LocalDate.now().minusDays(3), weekIndex = 0, isOutDate = false), + DayModel(date = LocalDate.now().minusDays(2), weekIndex = 0, isOutDate = false), + DayModel(date = LocalDate.now().minusDays(1), weekIndex = 0, isOutDate = false), + DayModel(date = LocalDate.now(), weekIndex = 0, isOutDate = false), + DayModel(date = LocalDate.now().plusDays(1), weekIndex = 0, isOutDate = false), + DayModel(date = LocalDate.now().plusDays(2), weekIndex = 0, isOutDate = false), + DayModel(date = LocalDate.now().plusDays(3), weekIndex = 0, isOutDate = false) + ), + onDateSelected = { + selectedDay = it + }, + scrapCount = 3, + modifier = Modifier.fillMaxWidth().wrapContentHeight().background(White) + ) + } +} + +@Preview +@Composable +private fun CalendarWeekGroupScrapPreview() { + TerningPointTheme { + + CalendarWeekGroup( + selectedDay = DayModel(date = LocalDate.now().minusDays(1), weekIndex = 0, isOutDate = false), + isWeekEnabled = false, + dayModels = listOf( + DayModel(date = LocalDate.now().minusDays(3), weekIndex = 0, isOutDate = false), + DayModel(date = LocalDate.now().minusDays(2), weekIndex = 0, isOutDate = false), + DayModel(date = LocalDate.now().minusDays(1), weekIndex = 0, isOutDate = false), + DayModel(date = LocalDate.now(), weekIndex = 0, isOutDate = false), + DayModel(date = LocalDate.now().plusDays(1), weekIndex = 0, isOutDate = false), + DayModel(date = LocalDate.now().plusDays(2), weekIndex = 0, isOutDate = false), + DayModel(date = LocalDate.now().plusDays(3), weekIndex = 0, isOutDate = false) + ), + onDateSelected = {}, + scrapCount = 3, + modifier = Modifier.fillMaxWidth().wrapContentHeight().background(White), + scrapMap = mapOf( + "2024-12-10" to listOf( + CalendarScrap( + scrapId = 1, + title = "테스트1", + deadLine = "2024-12-10", + color = "#FF0F0F", + isScrapped = true + ), + CalendarScrap( + scrapId = 1, + title = "테스트2", + deadLine = "2024-12-10", + color = "#00FF00", + isScrapped = true + ), + CalendarScrap( + scrapId = 1, + title = "테스트3", + deadLine = "2024-12-10", + color = "#0000FF", + isScrapped = true + ), + CalendarScrap( + scrapId = 1, + title = "테스트4", + deadLine = "2024-12-10", + color = "#FF00FF", + isScrapped = true + ) + ) + ) + ) + } +} \ No newline at end of file diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/DayModel.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/DayModel.kt index 9c1df5ce..858d6efc 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/DayModel.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/DayModel.kt @@ -2,6 +2,7 @@ package com.terning.feature.calendar.calendar.model import androidx.compose.runtime.Immutable import java.time.LocalDate +import java.time.format.DateTimeFormatter /** * 달력의 하루를 나타내는 데이터클래스 모델 @@ -13,7 +14,14 @@ import java.time.LocalDate @Immutable data class DayModel( - val date: LocalDate, + val date: LocalDate = LocalDate.now(), val weekIndex: Int = 0, val isOutDate: Boolean = false -) \ No newline at end of file +) { + fun isToday(): Boolean = date == LocalDate.now() + + fun getScrapMapKey(): String { + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") + return date.format(formatter) + } +} \ No newline at end of file From 3f8d781c020966a5f93bb67779650f049d1bd095 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Thu, 12 Dec 2024 03:39:15 +0900 Subject: [PATCH 04/10] =?UTF-8?q?[UI/#305]=20=EC=BA=98=EB=A6=B0=EB=8D=94?= =?UTF-8?q?=20=ED=8E=98=EC=9D=B4=EC=A0=80=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 페이징 컴포넌트 재구현 - 헤더 컴포넌트 이름 변경 --- ...aysHeader.kt => CalendarWeekDaysHeader.kt} | 4 +- .../month/component/CalendarMonthPager.kt | 82 +++++++++++++++++++ .../week/component/CalendarWeekPager.kt | 74 +++++++++++++++++ 3 files changed, 158 insertions(+), 2 deletions(-) rename feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/{WeekDaysHeader.kt => CalendarWeekDaysHeader.kt} (96%) create mode 100644 feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonthPager.kt create mode 100644 feature/calendar/src/main/java/com/terning/feature/calendar/week/component/CalendarWeekPager.kt diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/WeekDaysHeader.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/CalendarWeekDaysHeader.kt similarity index 96% rename from feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/WeekDaysHeader.kt rename to feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/CalendarWeekDaysHeader.kt index be398b0c..0bb06085 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/WeekDaysHeader.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/CalendarWeekDaysHeader.kt @@ -19,7 +19,7 @@ import com.terning.core.designsystem.theme.TerningTheme import com.terning.feature.calendar.R @Composable -fun WeekDaysHeader( +fun CalendarWeekDaysHeader( modifier: Modifier = Modifier, ) { Row( @@ -56,6 +56,6 @@ fun WeekDaysHeader( @Composable fun WeekDaysHeaderPreview() { TerningPointTheme { - WeekDaysHeader() + CalendarWeekDaysHeader() } } \ No newline at end of file diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonthPager.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonthPager.kt new file mode 100644 index 00000000..0ed528ea --- /dev/null +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonthPager.kt @@ -0,0 +1,82 @@ +package com.terning.feature.calendar.month.component + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.PagerState +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import com.terning.core.designsystem.theme.TerningPointTheme +import com.terning.domain.calendar.entity.CalendarScrap +import com.terning.feature.calendar.calendar.component.group.CalendarMonthGroup +import com.terning.feature.calendar.calendar.model.DayModel +import com.terning.feature.calendar.calendar.model.TerningCalendarModel +import java.time.LocalDate + + +@Composable +internal fun CalendarMonthPager( + pagerState: PagerState, + calendarModel: TerningCalendarModel, + onDateSelect: (DayModel) -> Unit, + selectedDate: DayModel, + modifier: Modifier = Modifier, + scrapMap: Map>, + isWeekEnabled: Boolean = false, +) { + HorizontalPager( + state = pagerState, + modifier = modifier.fillMaxSize() + ) { page -> + val monthModel = calendarModel.getMonthModelByPage(page = page) + + CalendarMonthGroup( + isWeekEnabled = isWeekEnabled, + dayModels = monthModel.calendarMonth, + modifier = Modifier.fillMaxSize(), + onDateSelected = onDateSelect, + selectedDate = selectedDate, + scrapMap = scrapMap + ) + } +} + +@Preview +@Composable +private fun CalendarMonthScreenPreview() { + TerningPointTheme { + val calendarModel = TerningCalendarModel() + val selectedDay = DayModel(LocalDate.now()) + val pagerState = rememberPagerState( + initialPage = calendarModel.initialPage, + pageCount = { calendarModel.pageCount } + ) + + HorizontalPager( + state = pagerState, + modifier = Modifier.fillMaxSize() + ) { page -> + val monthModel = calendarModel.getMonthModelByPage(page = page) + + CalendarMonthGroup( + isWeekEnabled = false, + dayModels = monthModel.calendarMonth, + modifier = Modifier.fillMaxSize(), + onDateSelected = { }, + selectedDate = selectedDay, + scrapMap = mapOf( + "2024-12-11" to listOf( + CalendarScrap( + scrapId = 1, + title = "테스트1", + deadLine = "2024-12-11", + isScrapped = true, + color = "#a3d711" + ) + ) + ) + ) + } + } +} \ No newline at end of file diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/week/component/CalendarWeekPager.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/week/component/CalendarWeekPager.kt new file mode 100644 index 00000000..51891d3f --- /dev/null +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/week/component/CalendarWeekPager.kt @@ -0,0 +1,74 @@ +package com.terning.feature.calendar.week.component + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +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.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.terning.core.designsystem.theme.TerningPointTheme +import com.terning.core.designsystem.theme.White +import com.terning.feature.calendar.calendar.component.group.CalendarWeekGroup +import com.terning.feature.calendar.calendar.model.DayModel +import com.terning.feature.calendar.calendar.model.MonthModel +import com.terning.feature.calendar.calendar.model.TerningCalendarModel +import java.time.LocalDate + +@Composable +internal fun CalendarWeekPager( + monthModel: MonthModel, + onDateSelect: (DayModel) -> Unit, + selectedDate: DayModel, + modifier: Modifier = Modifier, +) { + val pagerState = rememberPagerState( + initialPage = selectedDate.weekIndex, + pageCount = { monthModel.calendarMonth.size } + ) + + LaunchedEffect(selectedDate) { + val page = selectedDate.weekIndex + pagerState.animateScrollToPage(page) + } + + HorizontalPager( + modifier = modifier + .fillMaxWidth() + .background(color = White) + .padding(vertical = 16.dp), + contentPadding = PaddingValues(horizontal = 20.dp), + pageSpacing = 32.dp, + state = pagerState, + ) { page -> + + CalendarWeekGroup( + isWeekEnabled = true, + dayModels = monthModel.calendarMonth[page], + onDateSelected = { dayModel -> + onDateSelect(dayModel) + }, + selectedDay = selectedDate, + scrapCount = 0, + ) + } + +} + + +@Preview +@Composable +private fun CalendarWeekPagerPreview() { + TerningPointTheme { + CalendarWeekPager( + monthModel = TerningCalendarModel().getMonthModelByPage(LocalDate.now()), + onDateSelect = { }, + selectedDate = DayModel(LocalDate.now()) + ) + } +} + From 15744ddb82a1399b385fcbe4835f2c16dec09093 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Thu, 12 Dec 2024 04:11:31 +0900 Subject: [PATCH 05/10] =?UTF-8?q?[REFACTOR/#305]=20DayModel=20=EB=A7=88?= =?UTF-8?q?=EC=9D=B4=EA=B7=B8=EB=A0=88=EC=9D=B4=EC=85=98=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../calendar/calendar/CalendarRoute.kt | 29 +++-- .../calendar/calendar/CalendarViewModel.kt | 36 +++---- .../calendar/component/CalendarDay.kt | 101 ------------------ ...darWeekDaysHeader.kt => WeekDaysHeader.kt} | 4 +- .../{model => state}/CalendarUiState.kt | 9 +- .../calendar/list/CalendarListScreen.kt | 2 +- .../calendar/month/CalendarMonthScreen.kt | 68 ++++-------- .../calendar/month/component/CalendarMonth.kt | 95 ---------------- .../calendar/week/CalendarWeekScreen.kt | 33 +++--- .../week/component/HorizontalCalendarWeek.kt | 60 ----------- 10 files changed, 80 insertions(+), 357 deletions(-) delete mode 100644 feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/CalendarDay.kt rename feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/{CalendarWeekDaysHeader.kt => WeekDaysHeader.kt} (96%) rename feature/calendar/src/main/java/com/terning/feature/calendar/calendar/{model => state}/CalendarUiState.kt (55%) delete mode 100644 feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonth.kt delete mode 100644 feature/calendar/src/main/java/com/terning/feature/calendar/week/component/HorizontalCalendarWeek.kt diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt index de9bc1c0..fc0108ed 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt @@ -1,5 +1,6 @@ package com.terning.feature.calendar.calendar +import androidx.activity.compose.BackHandler import androidx.compose.animation.core.tween import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideInVertically @@ -25,17 +26,20 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.terning.core.analytics.EventType import com.terning.core.analytics.LocalTracker import com.terning.core.designsystem.component.topappbar.CalendarTopAppBar +import com.terning.core.designsystem.extension.getWeekIndexContainingSelectedDate 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.state.CalendarUiState +import com.terning.feature.calendar.calendar.model.DayModel +import com.terning.feature.calendar.calendar.state.LocalPagerState import com.terning.feature.calendar.calendar.model.TerningCalendarModel.Companion.LocalCalendarModel -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.launch +import timber.log.Timber import java.time.LocalDate @Composable @@ -72,8 +76,8 @@ fun CalendarRoute( private fun CalendarScreen( uiState: CalendarUiState, navigateToAnnouncement: (Long) -> Unit, - onClickNewDate: (LocalDate) -> Unit, - updateSelectedDate: (LocalDate) -> Unit, + onClickNewDate: (DayModel) -> Unit, + updateSelectedDate: (DayModel) -> Unit, disableListVisibility: () -> Unit, disableWeekVisibility: () -> Unit, onClickListButton: () -> Unit, @@ -86,19 +90,26 @@ private fun CalendarScreen( pageCount = { uiState.calendarModel.pageCount } ) + BackHandler(enabled = uiState.isWeekEnabled) { + disableWeekVisibility() + } + LaunchedEffect(key1 = pagerState, key2 = uiState.selectedDate) { snapshotFlow { pagerState.currentPage } .collect { current -> - //val date = getLocalDateByPage(current) val date = uiState.calendarModel.getLocalDateByPage(current) + val month = uiState.calendarModel.getMonthModelByPage(current) val newDate = LocalDate.of( date.year, date.month, - uiState.selectedDate.dayOfMonth.coerceAtMost(date.month.minLength()) + uiState.selectedDate.date.dayOfMonth.coerceAtMost(date.month.minLength()) ) - updateSelectedDate(newDate) + + val currentWeek = newDate.getWeekIndexContainingSelectedDate(month.inDays) + Timber.tag("WeekIndex").d("In CalendarRoute: ${currentWeek.toString()}") + updateSelectedDate(DayModel(newDate, currentWeek)) } } @@ -165,7 +176,9 @@ private fun CalendarScreen( .fillMaxSize(), navigateUp = disableWeekVisibility, navigateToAnnouncement = navigateToAnnouncement, - updateSelectedDate = onClickNewDate + updateSelectedDate = { + onClickNewDate(it) + } ) } ) diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt index 5280ae0a..f242a954 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt @@ -1,14 +1,12 @@ package com.terning.feature.calendar.calendar import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.terning.feature.calendar.calendar.model.CalendarUiState +import com.terning.feature.calendar.calendar.model.DayModel +import com.terning.feature.calendar.calendar.state.CalendarUiState import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import java.time.LocalDate import javax.inject.Inject @HiltViewModel @@ -16,13 +14,9 @@ class CalendarViewModel @Inject constructor() : ViewModel() { private var _uiState: MutableStateFlow = MutableStateFlow(CalendarUiState()) val uiState get() = _uiState.asStateFlow() - fun onSelectNewDate(selectedDate: LocalDate) = viewModelScope.launch { - if (_uiState.value.selectedDate == selectedDate) { - _uiState.update { currentState -> - currentState.copy( - isWeekEnabled = !_uiState.value.isWeekEnabled - ) - } + fun onSelectNewDate(selectedDate: DayModel) { + if (_uiState.value.selectedDate.date == selectedDate.date) { + updateWeekVisibility(!_uiState.value.isWeekEnabled) } else { _uiState.update { currentState -> currentState.copy( @@ -33,27 +27,23 @@ class CalendarViewModel @Inject constructor() : ViewModel() { } } - fun updateSelectedDate(date: LocalDate) = viewModelScope.launch { - _uiState.update { currentState -> + fun updateSelectedDate(value: DayModel) = _uiState.update { currentState -> currentState.copy( - selectedDate = date + selectedDate = value ) } - } - fun updateListVisibility(visibility: Boolean) = viewModelScope.launch { - _uiState.update { currentState -> + + fun updateListVisibility(value: Boolean) = _uiState.update { currentState -> currentState.copy( - isListEnabled = visibility + isListEnabled = value ) } - } - fun updateWeekVisibility(visibility: Boolean) = viewModelScope.launch { - _uiState.update { currentState -> + + fun updateWeekVisibility(value: Boolean) = _uiState.update { currentState -> currentState.copy( - isWeekEnabled = visibility + isWeekEnabled = value ) } - } } \ No newline at end of file diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/CalendarDay.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/CalendarDay.kt deleted file mode 100644 index c54a3b53..00000000 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/CalendarDay.kt +++ /dev/null @@ -1,101 +0,0 @@ -package com.terning.feature.calendar.calendar.component - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.terning.core.designsystem.extension.noRippleClickable -import com.terning.core.designsystem.theme.Black -import com.terning.core.designsystem.theme.Grey150 -import com.terning.core.designsystem.theme.Grey200 -import com.terning.core.designsystem.theme.TerningMain -import com.terning.core.designsystem.theme.TerningPointTheme -import com.terning.core.designsystem.theme.TerningTheme -import com.terning.core.designsystem.theme.White -import com.terning.feature.calendar.calendar.model.DayModel -import java.time.LocalDate - -@Composable -fun CalendarDay( - modifier: Modifier = Modifier, - dayData: DayModel, - isSelected: Boolean, - isToday: Boolean, - onDateSelected: (LocalDate) -> Unit = {} -) { - val backgroundColor = - if (isSelected) - TerningMain - else if (isToday) Grey150 - else Color.Transparent - - val textColor = - if (dayData.isOutDate) - Grey200 - else if (isSelected) - White - else - Black - - - Box( - modifier = modifier, - contentAlignment = Alignment.Center - ) { - Box( - modifier = Modifier - .size(22.dp) - .noRippleClickable { - if (!dayData.isOutDate) { - onDateSelected(dayData.date) - } - } - .background( - color = backgroundColor, - shape = CircleShape - ), - contentAlignment = Alignment.Center - ) { - Text( - text = dayData.date.dayOfMonth.toString(), - color = textColor, - style = TerningTheme.typography.calendar - ) - } - } -} - -@Preview(showBackground = true) -@Composable -fun CalendarDayPreview() { - TerningPointTheme { - Row { - CalendarDay( - dayData = DayModel(LocalDate.now(), 0, false), - isSelected = true, - isToday = true, - onDateSelected = {} - ) - CalendarDay( - dayData = DayModel(LocalDate.now(), 0, false), - isSelected = false, - isToday = true, - onDateSelected = {} - ) - CalendarDay( - dayData = DayModel(LocalDate.now(), 0, false), - isSelected = false, - isToday = false, - onDateSelected = {} - ) - } - } -} \ No newline at end of file diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/CalendarWeekDaysHeader.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/WeekDaysHeader.kt similarity index 96% rename from feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/CalendarWeekDaysHeader.kt rename to feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/WeekDaysHeader.kt index 0bb06085..be398b0c 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/CalendarWeekDaysHeader.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/WeekDaysHeader.kt @@ -19,7 +19,7 @@ import com.terning.core.designsystem.theme.TerningTheme import com.terning.feature.calendar.R @Composable -fun CalendarWeekDaysHeader( +fun WeekDaysHeader( modifier: Modifier = Modifier, ) { Row( @@ -56,6 +56,6 @@ fun CalendarWeekDaysHeader( @Composable fun WeekDaysHeaderPreview() { TerningPointTheme { - CalendarWeekDaysHeader() + WeekDaysHeader() } } \ No newline at end of file diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/state/CalendarUiState.kt similarity index 55% rename from feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt rename to feature/calendar/src/main/java/com/terning/feature/calendar/calendar/state/CalendarUiState.kt index 5aa07853..065c1b3c 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/state/CalendarUiState.kt @@ -1,14 +1,15 @@ -package com.terning.feature.calendar.calendar.model +package com.terning.feature.calendar.calendar.state import androidx.compose.foundation.pager.PagerState import androidx.compose.runtime.compositionLocalOf -import java.time.LocalDate +import com.terning.feature.calendar.calendar.model.DayModel +import com.terning.feature.calendar.calendar.model.TerningCalendarModel data class CalendarUiState( - val selectedDate: LocalDate = LocalDate.now(), + val selectedDate: DayModel = DayModel(), val calendarModel: TerningCalendarModel = TerningCalendarModel(), val isListEnabled: Boolean = false, - val isWeekEnabled: Boolean = false + val isWeekEnabled: Boolean = false, ) val LocalPagerState = compositionLocalOf { diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt index 48fc90ce..9d3028e5 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt @@ -39,7 +39,7 @@ import com.terning.core.designsystem.theme.TerningTheme import com.terning.domain.calendar.entity.CalendarScrapDetail import com.terning.feature.calendar.R import com.terning.feature.calendar.calendar.model.TerningCalendarModel.Companion.LocalCalendarModel -import com.terning.feature.calendar.calendar.model.LocalPagerState +import com.terning.feature.calendar.calendar.state.LocalPagerState import com.terning.feature.calendar.list.component.CalendarScrapList import com.terning.feature.calendar.list.model.CalendarListUiState import com.terning.feature.dialog.cancel.ScrapCancelDialog diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt index 57e0d46b..bc81132c 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt @@ -1,8 +1,5 @@ package com.terning.feature.calendar.month -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 @@ -13,18 +10,18 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.flowWithLifecycle -import com.terning.core.designsystem.state.UiState import com.terning.core.designsystem.extension.toast +import com.terning.core.designsystem.state.UiState +import com.terning.domain.calendar.entity.CalendarScrap +import com.terning.feature.calendar.calendar.model.DayModel +import com.terning.feature.calendar.calendar.state.LocalPagerState import com.terning.feature.calendar.calendar.model.TerningCalendarModel.Companion.LocalCalendarModel -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 java.time.LocalDate +import com.terning.feature.calendar.month.component.CalendarMonthPager @Composable fun CalendarMonthRoute( - selectedDate: LocalDate, - updateSelectedDate: (LocalDate) -> Unit, + selectedDate: DayModel, + updateSelectedDate: (DayModel) -> Unit, modifier: Modifier = Modifier, viewModel: CalendarMonthViewModel = hiltViewModel() ) { @@ -32,7 +29,7 @@ fun CalendarMonthRoute( val pagerState = LocalPagerState.current val context = LocalContext.current val lifecycleOwner = LocalLifecycleOwner.current - val monthUiState by viewModel.uiState.collectAsStateWithLifecycle(lifecycleOwner) + val uiState by viewModel.uiState.collectAsStateWithLifecycle(lifecycleOwner) LaunchedEffect(viewModel.sideEffect, lifecycleOwner) { viewModel.sideEffect.flowWithLifecycle(lifecycle = lifecycleOwner.lifecycle) @@ -45,51 +42,26 @@ fun CalendarMonthRoute( LaunchedEffect(key1 = pagerState) { snapshotFlow { pagerState.currentPage } - .collect { currentPage-> + .collect { currentPage -> val localDate = calendarModel.getLocalDateByPage(currentPage) viewModel.getScrapMonth(localDate) } } - CalendarMonthScreen( + CalendarMonthPager( + modifier = modifier, pagerState = pagerState, + calendarModel = calendarModel, selectedDate = selectedDate, - uiState = monthUiState, - updateSelectedDate = updateSelectedDate, - modifier = modifier + onDateSelect = updateSelectedDate, + isWeekEnabled = false, + scrapMap = when (uiState.loadState) { + UiState.Loading -> emptyMap() + UiState.Empty -> emptyMap() + is UiState.Failure -> emptyMap() + is UiState.Success -> (uiState.loadState as UiState.Success>>).data + }, ) } -@Composable -private fun CalendarMonthScreen( - pagerState: PagerState, - selectedDate: LocalDate, - uiState: CalendarMonthUiState, - updateSelectedDate: (LocalDate) -> Unit, - modifier: Modifier = Modifier, -) { - val calendarModel = LocalCalendarModel.current - - HorizontalPager( - state = pagerState, - modifier = modifier.fillMaxSize() - ) { page -> - val monthModel = calendarModel.getMonthModelByPage(page = page) - - 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 - }, - ) - } -} - diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonth.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonth.kt deleted file mode 100644 index dbd28710..00000000 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonth.kt +++ /dev/null @@ -1,95 +0,0 @@ -package com.terning.feature.calendar.month.component - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.HorizontalDivider -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.terning.core.designsystem.extension.getDateAsMapString -import com.terning.core.designsystem.extension.isToday -import com.terning.core.designsystem.extension.noRippleClickable -import com.terning.core.designsystem.theme.Grey150 -import com.terning.core.designsystem.theme.TerningPointTheme -import com.terning.domain.calendar.entity.CalendarScrap -import com.terning.feature.calendar.calendar.component.CalendarDay -import com.terning.feature.calendar.calendar.model.MonthModel -import java.time.LocalDate -import java.time.YearMonth - -@Composable -internal fun CalendarMonth( - isWeekEnabled: Boolean, - monthModel: MonthModel, - onDateSelected: (LocalDate) -> Unit, - selectedDate: LocalDate, - modifier: Modifier = Modifier, - scrapMap: Map> = mapOf() -) { - Column( - modifier = modifier - .fillMaxSize() - .padding(horizontal = 20.dp), - ) { - val month = monthModel.calendarMonth - for (week in month) { - Row( - modifier = Modifier.weight(1f), - ) { - for (day in week) { - Column( - modifier = Modifier - .weight(1f) - .fillMaxSize() - .noRippleClickable { - if(!day.isOutDate) { - onDateSelected(day.date) - } - } - .padding(top = 15.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - CalendarDay( - dayData = day, - isSelected = selectedDate == day.date && isWeekEnabled, - isToday = day.date.isToday(), - onDateSelected = onDateSelected - ) - if (!day.isOutDate) { - val index = day.date.getDateAsMapString() - CalendarMonthScrap( - weekCount = month.size, - scrapLists = scrapMap[index].orEmpty(), - modifier = Modifier.fillMaxWidth() - ) - } - } - } - } - if (month.indexOf(week) != month.lastIndex) { - HorizontalDivider( - thickness = 1.dp, - color = Grey150 - ) - } - } - } -} - -@Preview(showBackground = true) -@Composable -private fun CalendarMonthPreview() { - TerningPointTheme { - CalendarMonth( - monthModel = MonthModel(YearMonth.now()), - onDateSelected = {}, - selectedDate = LocalDate.now(), - isWeekEnabled = true - ) - } -} \ No newline at end of file diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt index 799a918d..ac689e2f 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt @@ -47,10 +47,12 @@ import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.designsystem.theme.White import com.terning.domain.calendar.entity.CalendarScrapDetail import com.terning.feature.calendar.R -import com.terning.feature.calendar.calendar.model.CalendarUiState -import com.terning.feature.calendar.calendar.model.LocalPagerState +import com.terning.feature.calendar.calendar.state.CalendarUiState +import com.terning.feature.calendar.calendar.model.DayModel +import com.terning.feature.calendar.calendar.state.LocalPagerState +import com.terning.feature.calendar.calendar.model.TerningCalendarModel import com.terning.feature.calendar.list.component.CalendarScrapList -import com.terning.feature.calendar.week.component.HorizontalCalendarWeek +import com.terning.feature.calendar.week.component.CalendarWeekPager import com.terning.feature.calendar.week.model.CalendarWeekUiState import com.terning.feature.dialog.cancel.ScrapCancelDialog import com.terning.feature.dialog.detail.ScrapDialog @@ -61,7 +63,7 @@ import java.time.LocalDate fun CalendarWeekRoute( calendarUiState: CalendarUiState, navigateToAnnouncement: (Long) -> Unit, - updateSelectedDate: (LocalDate) -> Unit, + updateSelectedDate: (DayModel) -> Unit, navigateUp: () -> Unit, modifier: Modifier = Modifier, viewModel: CalendarWeekViewModel = hiltViewModel(), @@ -81,7 +83,7 @@ fun CalendarWeekRoute( } LaunchedEffect(key1 = calendarUiState.selectedDate) { - viewModel.getScrapWeekList(selectedDate = calendarUiState.selectedDate) + viewModel.getScrapWeekList(selectedDate = calendarUiState.selectedDate.date) } BackHandler { @@ -91,6 +93,7 @@ fun CalendarWeekRoute( CalendarWeekScreen( modifier = modifier, pagerState = pagerState, + calendarModel = calendarUiState.calendarModel, uiState = uiState, selectedDate = calendarUiState.selectedDate, updateSelectedDate = updateSelectedDate, @@ -109,7 +112,7 @@ fun CalendarWeekRoute( ) CalendarWeekScrapPatchDialog( - currentDate = calendarUiState.selectedDate, + currentDate = calendarUiState.selectedDate.date, dialogVisibility = uiState.scrapDetailDialogVisibility, internshipModel = uiState.internshipModel, navigateToAnnouncement = { announcementId -> @@ -118,7 +121,7 @@ fun CalendarWeekRoute( }, onDismissInternDialog = { viewModel.updateScrapDetailDialogVisibility(false) }, onClickChangeColor = { - viewModel.getScrapWeekList(calendarUiState.selectedDate) + viewModel.getScrapWeekList(calendarUiState.selectedDate.date) }, ) @@ -128,7 +131,7 @@ fun CalendarWeekRoute( onDismissCancelDialog = { isCancelled -> viewModel.updateScrapCancelDialogVisibility(false) if (isCancelled) { - viewModel.getScrapWeekList(calendarUiState.selectedDate) + viewModel.getScrapWeekList(calendarUiState.selectedDate.date) } } ) @@ -137,9 +140,10 @@ fun CalendarWeekRoute( @Composable private fun CalendarWeekScreen( uiState: CalendarWeekUiState, + calendarModel: TerningCalendarModel, pagerState: PagerState, - selectedDate: LocalDate, - updateSelectedDate: (LocalDate) -> Unit, + selectedDate: DayModel, + updateSelectedDate: (DayModel) -> Unit, onClickInternship: (CalendarScrapDetail) -> Unit, onClickScrapButton: (Long) -> Unit, modifier: Modifier = Modifier, @@ -169,11 +173,10 @@ private fun CalendarWeekScreen( ), shape = RoundedCornerShape(bottomStart = 20.dp, bottomEnd = 20.dp), ) { - HorizontalCalendarWeek( + CalendarWeekPager( + monthModel = calendarModel.getMonthModelByPage(selectedDate.date), selectedDate = selectedDate, - onDateSelected = updateSelectedDate, - modifier = Modifier - .fillMaxWidth() + onDateSelect = updateSelectedDate, ) Spacer( @@ -195,7 +198,7 @@ private fun CalendarWeekScreen( horizontalAlignment = Alignment.CenterHorizontally ) { Text( - text = selectedDate.getDateStringInKorean(), + text = selectedDate.date.getDateStringInKorean(), style = TerningTheme.typography.title5, color = Black, modifier = Modifier diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/week/component/HorizontalCalendarWeek.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/week/component/HorizontalCalendarWeek.kt deleted file mode 100644 index efb4515e..00000000 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/week/component/HorizontalCalendarWeek.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.terning.feature.calendar.week.component - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyRow -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.designsystem.extension.getWeekIndexContainingSelectedDate -import com.terning.core.designsystem.extension.isToday -import com.terning.feature.calendar.calendar.component.CalendarDay -import com.terning.feature.calendar.calendar.model.TerningCalendarModel.Companion.LocalCalendarModel -import java.time.LocalDate - -@Composable -fun HorizontalCalendarWeek( - selectedDate: LocalDate, - onDateSelected: (LocalDate) -> Unit, - modifier: Modifier = Modifier -) { - val calendarModel = LocalCalendarModel.current - - val monthModel = calendarModel.getMonthModelByPage(selectedDate) - val currentWeek = selectedDate.getWeekIndexContainingSelectedDate(monthModel.inDays) - - val pagerState = rememberPagerState( - initialPage = currentWeek, - pageCount = { monthModel.totalDays / 7 } - ) - - LaunchedEffect(selectedDate) { - pagerState.animateScrollToPage(selectedDate.getWeekIndexContainingSelectedDate(monthModel.inDays)) - } - - HorizontalPager( - modifier = modifier, - state = pagerState - ) { page -> - LazyRow( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 32.dp, vertical = 20.dp), - horizontalArrangement = Arrangement.SpaceBetween - ) { - items(items = monthModel.calendarMonth[page]) { day -> - CalendarDay( - dayData = day, - isSelected = day.date == selectedDate, - isToday = day.date.isToday(), - onDateSelected = onDateSelected - ) - } - } - } -} \ No newline at end of file From fb39552e935e3bed42a26443f50f27b4a36d501a Mon Sep 17 00:00:00 2001 From: boiledegg Date: Thu, 12 Dec 2024 04:26:21 +0900 Subject: [PATCH 06/10] =?UTF-8?q?[MOVE/#305]=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EC=9C=84=EC=B9=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../calendar/calendar/CalendarRoute.kt | 22 +++++-------------- .../calendar/calendar/CalendarViewModel.kt | 2 +- .../group/CalendarScrapListGroup.kt} | 6 ++--- .../group/CalendarScrapListItemGroup.kt} | 4 ++-- .../component/pager}/CalendarMonthPager.kt | 2 +- .../component/pager}/CalendarWeekPager.kt | 2 +- .../{state => model}/CalendarUiState.kt | 4 +--- .../calendar/list/CalendarListScreen.kt | 6 ++--- .../calendar/month/CalendarMonthScreen.kt | 11 +++++++--- .../calendar/week/CalendarWeekScreen.kt | 10 ++++----- 10 files changed, 31 insertions(+), 38 deletions(-) rename feature/calendar/src/main/java/com/terning/feature/calendar/{list/component/CalendarScrapList.kt => calendar/component/group/CalendarScrapListGroup.kt} (90%) rename feature/calendar/src/main/java/com/terning/feature/calendar/{list/component/CalendarScrap.kt => calendar/component/group/CalendarScrapListItemGroup.kt} (93%) rename feature/calendar/src/main/java/com/terning/feature/calendar/{month/component => calendar/component/pager}/CalendarMonthPager.kt (97%) rename feature/calendar/src/main/java/com/terning/feature/calendar/{week/component => calendar/component/pager}/CalendarWeekPager.kt (97%) rename feature/calendar/src/main/java/com/terning/feature/calendar/calendar/{state => model}/CalendarUiState.kt (69%) diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt index fc0108ed..c3d8ccdf 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt @@ -7,7 +7,6 @@ import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutHorizontally import androidx.compose.animation.slideOutVertically 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.pager.rememberPagerState @@ -21,25 +20,22 @@ import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.terning.core.analytics.EventType import com.terning.core.analytics.LocalTracker import com.terning.core.designsystem.component.topappbar.CalendarTopAppBar import com.terning.core.designsystem.extension.getWeekIndexContainingSelectedDate 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.state.CalendarUiState import com.terning.feature.calendar.calendar.model.DayModel -import com.terning.feature.calendar.calendar.state.LocalPagerState import com.terning.feature.calendar.calendar.model.TerningCalendarModel.Companion.LocalCalendarModel +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.launch -import timber.log.Timber import java.time.LocalDate @Composable @@ -48,8 +44,7 @@ fun CalendarRoute( modifier: Modifier = Modifier, viewModel: CalendarViewModel = hiltViewModel() ) { - val lifecycleOwner = LocalLifecycleOwner.current - val uiState by viewModel.uiState.collectAsStateWithLifecycle(lifecycleOwner = lifecycleOwner) + val uiState by viewModel.uiState.collectAsStateWithLifecycle() val amplitudeTracker = LocalTracker.current CalendarScreen( @@ -108,7 +103,6 @@ private fun CalendarScreen( ) val currentWeek = newDate.getWeekIndexContainingSelectedDate(month.inDays) - Timber.tag("WeekIndex").d("In CalendarRoute: ${currentWeek.toString()}") updateSelectedDate(DayModel(newDate, currentWeek)) } } @@ -163,10 +157,7 @@ private fun CalendarScreen( updateSelectedDate = { newDate -> if (!pagerState.isScrollInProgress) onClickNewDate(newDate) - }, - modifier = Modifier - .fillMaxSize() - .background(White), + } ) }, contentTwo = { @@ -176,9 +167,8 @@ private fun CalendarScreen( .fillMaxSize(), navigateUp = disableWeekVisibility, navigateToAnnouncement = navigateToAnnouncement, - updateSelectedDate = { - onClickNewDate(it) - } + updateSelectedDate = onClickNewDate + ) } ) diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt index f242a954..d1fed7a8 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt @@ -2,7 +2,7 @@ package com.terning.feature.calendar.calendar import androidx.lifecycle.ViewModel import com.terning.feature.calendar.calendar.model.DayModel -import com.terning.feature.calendar.calendar.state.CalendarUiState +import com.terning.feature.calendar.calendar.model.CalendarUiState import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/list/component/CalendarScrapList.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarScrapListGroup.kt similarity index 90% rename from feature/calendar/src/main/java/com/terning/feature/calendar/list/component/CalendarScrapList.kt rename to feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarScrapListGroup.kt index bb59e265..61695b27 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/list/component/CalendarScrapList.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarScrapListGroup.kt @@ -1,4 +1,4 @@ -package com.terning.feature.calendar.list.component +package com.terning.feature.calendar.calendar.component.group import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -12,7 +12,7 @@ import androidx.compose.ui.unit.dp import com.terning.domain.calendar.entity.CalendarScrapDetail @Composable -internal fun CalendarScrapList( +internal fun CalendarScrapListGroup( scrapList: List, onScrapButtonClicked: (Long) -> Unit, onInternshipClicked: (CalendarScrapDetail) -> Unit, @@ -32,7 +32,7 @@ internal fun CalendarScrapList( modifier = topModifier ) { for (scrap in scrapList) { - CalendarScrap( + CalendarScrapListItemGroup( scrap = scrap, onScrapButtonClicked = onScrapButtonClicked, onInternshipClicked = onInternshipClicked diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/list/component/CalendarScrap.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarScrapListItemGroup.kt similarity index 93% rename from feature/calendar/src/main/java/com/terning/feature/calendar/list/component/CalendarScrap.kt rename to feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarScrapListItemGroup.kt index 9c2c042e..df0cce3d 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/list/component/CalendarScrap.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarScrapListItemGroup.kt @@ -1,4 +1,4 @@ -package com.terning.feature.calendar.list.component +package com.terning.feature.calendar.calendar.component.group import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -12,7 +12,7 @@ import com.terning.core.designsystem.theme.Grey200 import com.terning.domain.calendar.entity.CalendarScrapDetail @Composable -fun CalendarScrap( +fun CalendarScrapListItemGroup( scrap: CalendarScrapDetail, onScrapButtonClicked: (Long) -> Unit, onInternshipClicked: (CalendarScrapDetail) -> Unit, diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonthPager.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/pager/CalendarMonthPager.kt similarity index 97% rename from feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonthPager.kt rename to feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/pager/CalendarMonthPager.kt index 0ed528ea..21a8debd 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/month/component/CalendarMonthPager.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/pager/CalendarMonthPager.kt @@ -1,4 +1,4 @@ -package com.terning.feature.calendar.month.component +package com.terning.feature.calendar.calendar.component.pager import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.pager.HorizontalPager diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/week/component/CalendarWeekPager.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/pager/CalendarWeekPager.kt similarity index 97% rename from feature/calendar/src/main/java/com/terning/feature/calendar/week/component/CalendarWeekPager.kt rename to feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/pager/CalendarWeekPager.kt index 51891d3f..a43000d8 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/week/component/CalendarWeekPager.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/pager/CalendarWeekPager.kt @@ -1,4 +1,4 @@ -package com.terning.feature.calendar.week.component +package com.terning.feature.calendar.calendar.component.pager import androidx.compose.foundation.background import androidx.compose.foundation.layout.PaddingValues diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/state/CalendarUiState.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt similarity index 69% rename from feature/calendar/src/main/java/com/terning/feature/calendar/calendar/state/CalendarUiState.kt rename to feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt index 065c1b3c..c2c097d6 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/state/CalendarUiState.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt @@ -1,9 +1,7 @@ -package com.terning.feature.calendar.calendar.state +package com.terning.feature.calendar.calendar.model import androidx.compose.foundation.pager.PagerState import androidx.compose.runtime.compositionLocalOf -import com.terning.feature.calendar.calendar.model.DayModel -import com.terning.feature.calendar.calendar.model.TerningCalendarModel data class CalendarUiState( val selectedDate: DayModel = DayModel(), diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt index 9d3028e5..f3238468 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt @@ -39,8 +39,8 @@ import com.terning.core.designsystem.theme.TerningTheme import com.terning.domain.calendar.entity.CalendarScrapDetail import com.terning.feature.calendar.R import com.terning.feature.calendar.calendar.model.TerningCalendarModel.Companion.LocalCalendarModel -import com.terning.feature.calendar.calendar.state.LocalPagerState -import com.terning.feature.calendar.list.component.CalendarScrapList +import com.terning.feature.calendar.calendar.model.LocalPagerState +import com.terning.feature.calendar.calendar.component.group.CalendarScrapListGroup import com.terning.feature.calendar.list.model.CalendarListUiState import com.terning.feature.dialog.cancel.ScrapCancelDialog import com.terning.feature.dialog.detail.ScrapDialog @@ -178,7 +178,7 @@ private fun CalendarListScreen( .padding(start = 24.dp, top = 16.dp, bottom = 15.dp) ) - CalendarScrapList( + CalendarScrapListGroup( scrapList = scrapMap[dateInKorean].orEmpty().toImmutableList(), onScrapButtonClicked = onClickScrapButton, onInternshipClicked = onClickInternship, diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt index bc81132c..efeb13c9 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt @@ -1,5 +1,7 @@ package com.terning.feature.calendar.month +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -12,11 +14,12 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.flowWithLifecycle import com.terning.core.designsystem.extension.toast import com.terning.core.designsystem.state.UiState +import com.terning.core.designsystem.theme.White import com.terning.domain.calendar.entity.CalendarScrap import com.terning.feature.calendar.calendar.model.DayModel -import com.terning.feature.calendar.calendar.state.LocalPagerState +import com.terning.feature.calendar.calendar.model.LocalPagerState import com.terning.feature.calendar.calendar.model.TerningCalendarModel.Companion.LocalCalendarModel -import com.terning.feature.calendar.month.component.CalendarMonthPager +import com.terning.feature.calendar.calendar.component.pager.CalendarMonthPager @Composable fun CalendarMonthRoute( @@ -49,7 +52,9 @@ fun CalendarMonthRoute( } CalendarMonthPager( - modifier = modifier, + modifier = modifier + .fillMaxSize() + .background(White), pagerState = pagerState, calendarModel = calendarModel, selectedDate = selectedDate, diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt index ac689e2f..8a8e488e 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt @@ -47,12 +47,12 @@ import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.designsystem.theme.White import com.terning.domain.calendar.entity.CalendarScrapDetail import com.terning.feature.calendar.R -import com.terning.feature.calendar.calendar.state.CalendarUiState +import com.terning.feature.calendar.calendar.model.CalendarUiState import com.terning.feature.calendar.calendar.model.DayModel -import com.terning.feature.calendar.calendar.state.LocalPagerState +import com.terning.feature.calendar.calendar.model.LocalPagerState import com.terning.feature.calendar.calendar.model.TerningCalendarModel -import com.terning.feature.calendar.list.component.CalendarScrapList -import com.terning.feature.calendar.week.component.CalendarWeekPager +import com.terning.feature.calendar.calendar.component.group.CalendarScrapListGroup +import com.terning.feature.calendar.calendar.component.pager.CalendarWeekPager import com.terning.feature.calendar.week.model.CalendarWeekUiState import com.terning.feature.dialog.cancel.ScrapCancelDialog import com.terning.feature.dialog.detail.ScrapDialog @@ -257,7 +257,7 @@ private fun CalendarWeekSuccess( onScrapButtonClicked: (Long) -> Unit, onInternshipClicked: (CalendarScrapDetail) -> Unit, ) { - CalendarScrapList( + CalendarScrapListGroup( scrapList = scrapList, onScrapButtonClicked = onScrapButtonClicked, onInternshipClicked = onInternshipClicked, From 64a115254fab078547e6c5669f13149d0c53a34d Mon Sep 17 00:00:00 2001 From: boiledegg Date: Thu, 12 Dec 2024 04:57:01 +0900 Subject: [PATCH 07/10] =?UTF-8?q?[REFACTOR/#305]=20CalendarRoute=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../calendar/calendar/CalendarRoute.kt | 209 +++++++++++------- .../calendar/model/CalendarUiState.kt | 6 +- .../calendar/model/TerningCalendarModel.kt | 4 - .../calendar/list/CalendarListScreen.kt | 12 +- .../calendar/month/CalendarMonthScreen.kt | 12 +- .../calendar/week/CalendarWeekScreen.kt | 27 ++- 6 files changed, 151 insertions(+), 119 deletions(-) diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt index c3d8ccdf..c0b19646 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt @@ -1,6 +1,5 @@ package com.terning.feature.calendar.calendar -import androidx.activity.compose.BackHandler import androidx.compose.animation.core.tween import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideInVertically @@ -9,10 +8,10 @@ import androidx.compose.animation.slideOutVertically import androidx.compose.animation.togetherWith import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.material3.HorizontalDivider 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 @@ -28,10 +27,9 @@ import com.terning.core.designsystem.extension.getWeekIndexContainingSelectedDat import com.terning.core.designsystem.theme.Grey200 import com.terning.feature.calendar.calendar.component.ScreenTransition import com.terning.feature.calendar.calendar.component.WeekDaysHeader -import com.terning.feature.calendar.calendar.model.DayModel -import com.terning.feature.calendar.calendar.model.TerningCalendarModel.Companion.LocalCalendarModel import com.terning.feature.calendar.calendar.model.CalendarUiState -import com.terning.feature.calendar.calendar.model.LocalPagerState +import com.terning.feature.calendar.calendar.model.DayModel +import com.terning.feature.calendar.calendar.model.TerningCalendarModel import com.terning.feature.calendar.list.CalendarListRoute import com.terning.feature.calendar.month.CalendarMonthRoute import com.terning.feature.calendar.week.CalendarWeekRoute @@ -48,7 +46,6 @@ fun CalendarRoute( val amplitudeTracker = LocalTracker.current CalendarScreen( - modifier = modifier, uiState = uiState, navigateToAnnouncement = navigateToAnnouncement, onClickNewDate = viewModel::onSelectNewDate, @@ -63,7 +60,8 @@ fun CalendarRoute( ) } viewModel.updateListVisibility(!uiState.isListEnabled) - } + }, + modifier = modifier, ) } @@ -85,17 +83,12 @@ private fun CalendarScreen( pageCount = { uiState.calendarModel.pageCount } ) - BackHandler(enabled = uiState.isWeekEnabled) { - disableWeekVisibility() - } - LaunchedEffect(key1 = pagerState, key2 = uiState.selectedDate) { snapshotFlow { pagerState.currentPage } .collect { current -> val date = uiState.calendarModel.getLocalDateByPage(current) val month = uiState.calendarModel.getMonthModelByPage(current) - val newDate = LocalDate.of( date.year, date.month, @@ -107,83 +100,131 @@ private fun CalendarScreen( } } - CompositionLocalProvider( - LocalPagerState provides pagerState, - LocalCalendarModel provides uiState.calendarModel + + Column( + modifier = modifier, ) { - Column( - modifier = modifier, - ) { - CalendarTopAppBar( - date = uiState.calendarModel.getYearMonthByPage(pagerState.settledPage), - isListExpanded = uiState.isListEnabled, - onListButtonClicked = onClickListButton, - onMonthNavigationButtonClicked = { direction -> - coroutineScope.launch { - pagerState.animateScrollToPage( - page = pagerState.settledPage + direction, - animationSpec = tween(500) - ) - } + CalendarTopAppBar( + date = uiState.calendarModel.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() - - 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( - selectedDate = uiState.selectedDate, - updateSelectedDate = { newDate -> - if (!pagerState.isScrollInProgress) - onClickNewDate(newDate) - } - ) - }, - contentTwo = { - CalendarWeekRoute( - calendarUiState = uiState, - modifier = Modifier - .fillMaxSize(), - navigateUp = disableWeekVisibility, - navigateToAnnouncement = navigateToAnnouncement, - updateSelectedDate = onClickNewDate - - ) - } - ) - } - }, - contentTwo = { - CalendarListRoute( - navigateToAnnouncement = navigateToAnnouncement, - navigateUp = disableListVisibility, - modifier = Modifier - .fillMaxSize() + } + ) + + CalendarListTransition( + isCalendarEnabled = !uiState.isListEnabled, + calendarModel = uiState.calendarModel, + pagerState = pagerState, + onNavigateToAnnouncement = navigateToAnnouncement, + onNavigateUpToCalendar = disableListVisibility, + calendarContent = { + Column( + modifier = Modifier + .fillMaxSize() + ) { + WeekDaysHeader() + + HorizontalDivider( + thickness = 1.dp, + color = Grey200 + ) + + MonthWeekTransition( + isMonthEnabled = !uiState.isWeekEnabled, + selectedDate = uiState.selectedDate, + calendarModel = uiState.calendarModel, + pagerState = pagerState, + onSelectDate = { newDate -> onClickNewDate(newDate) }, + onNavigateToAnnouncement = navigateToAnnouncement, + onNavigateUpToMonth = disableWeekVisibility ) + } + } + ) + } +} + + +/** 달력 <-> 목록 전환 컴포저블 */ +@Composable +private fun CalendarListTransition( + isCalendarEnabled: Boolean, + calendarModel: TerningCalendarModel, + pagerState: PagerState, + onNavigateToAnnouncement: (Long) -> Unit, + onNavigateUpToCalendar: () -> Unit, + calendarContent: @Composable () -> Unit, +) { + ScreenTransition( + targetState = isCalendarEnabled, + transitionOne = slideInHorizontally { fullWidth -> -fullWidth } togetherWith + slideOutHorizontally { fullWidth -> fullWidth }, + transitionTwo = slideInHorizontally { fullWidth -> fullWidth } togetherWith + slideOutHorizontally { fullWidth -> -fullWidth }, + contentOne = { + calendarContent() + }, + contentTwo = { + CalendarListRoute( + calendarModel = calendarModel, + navigateToAnnouncement = onNavigateToAnnouncement, + navigateUp = onNavigateUpToCalendar, + pagerState = pagerState, + modifier = Modifier + .fillMaxSize() + ) + }, + ) +} + +/**월간 <-> 주간 전환 컴포저블*/ +@Composable +private fun MonthWeekTransition( + isMonthEnabled: Boolean, + selectedDate: DayModel, + calendarModel: TerningCalendarModel, + pagerState: PagerState, + onSelectDate: (DayModel) -> Unit, + onNavigateToAnnouncement: (Long) -> Unit, + onNavigateUpToMonth: () -> Unit, +) { + ScreenTransition( + targetState = isMonthEnabled, + transitionOne = slideInVertically { fullHeight -> -fullHeight } togetherWith + slideOutVertically { fullHeight -> fullHeight }, + transitionTwo = slideInVertically { fullHeight -> fullHeight } togetherWith + slideOutVertically { fullHeight -> -fullHeight }, + contentOne = { + CalendarMonthRoute( + selectedDate = selectedDate, + updateSelectedDate = { newDate -> + if (!pagerState.isScrollInProgress) + onSelectDate(newDate) }, + pagerState = pagerState, + calendarModel = calendarModel + ) + }, + contentTwo = { + CalendarWeekRoute( + modifier = Modifier + .fillMaxSize(), + navigateUp = onNavigateUpToMonth, + navigateToAnnouncement = onNavigateToAnnouncement, + updateSelectedDate = onSelectDate, + selectedDate = selectedDate, + calendarModel = calendarModel, + pagerState = pagerState, ) } - } + ) } + diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt index c2c097d6..7273a807 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt @@ -8,8 +8,4 @@ data class CalendarUiState( val calendarModel: TerningCalendarModel = TerningCalendarModel(), val isListEnabled: Boolean = false, val isWeekEnabled: Boolean = false, -) - -val LocalPagerState = compositionLocalOf { - error("No PagerState provided") -} +) \ No newline at end of file diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/TerningCalendarModel.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/TerningCalendarModel.kt index 891f936c..3f7b5a56 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/TerningCalendarModel.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/TerningCalendarModel.kt @@ -70,9 +70,5 @@ class TerningCalendarModel ( companion object { private const val DEFAULT_START_YEAR = 2020 private const val DEFAULT_END_YEAR = 2030 - - val LocalCalendarModel = staticCompositionLocalOf { - error("No CalendarModel provided") - } } } \ No newline at end of file diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt index f3238468..be99dfde 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt @@ -28,19 +28,18 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.flowWithLifecycle -import com.terning.core.designsystem.state.UiState import com.terning.core.designsystem.extension.getFullDateStringInKorean import com.terning.core.designsystem.extension.isListNotEmpty import com.terning.core.designsystem.extension.toast +import com.terning.core.designsystem.state.UiState 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.domain.calendar.entity.CalendarScrapDetail import com.terning.feature.calendar.R -import com.terning.feature.calendar.calendar.model.TerningCalendarModel.Companion.LocalCalendarModel -import com.terning.feature.calendar.calendar.model.LocalPagerState import com.terning.feature.calendar.calendar.component.group.CalendarScrapListGroup +import com.terning.feature.calendar.calendar.model.TerningCalendarModel import com.terning.feature.calendar.list.model.CalendarListUiState import com.terning.feature.dialog.cancel.ScrapCancelDialog import com.terning.feature.dialog.detail.ScrapDialog @@ -50,12 +49,12 @@ import java.time.LocalDate @Composable fun CalendarListRoute( modifier: Modifier = Modifier, + calendarModel: TerningCalendarModel, + pagerState: PagerState, navigateUp: () -> Unit, navigateToAnnouncement: (Long) -> Unit, viewModel: CalendarListViewModel = hiltViewModel(), ) { - val pagerState = LocalPagerState.current - val calendarModel = LocalCalendarModel.current val lifecycleOwner = LocalLifecycleOwner.current val uiState by viewModel.uiState.collectAsStateWithLifecycle(lifecycleOwner) val context = LocalContext.current @@ -85,6 +84,7 @@ fun CalendarListRoute( CalendarListScreen( pagerState = pagerState, uiState = uiState, + calendarModel = calendarModel, modifier = modifier, onClickScrapButton = { scrapId -> with(viewModel) { @@ -129,12 +129,12 @@ fun CalendarListRoute( @Composable private fun CalendarListScreen( pagerState: PagerState, + calendarModel: TerningCalendarModel, uiState: CalendarListUiState, onClickInternship: (CalendarScrapDetail) -> Unit, onClickScrapButton: (Long) -> Unit, modifier: Modifier = Modifier, ) { - val calendarModel = LocalCalendarModel.current HorizontalPager( state = pagerState, diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt index efeb13c9..b128f044 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/month/CalendarMonthScreen.kt @@ -2,6 +2,7 @@ package com.terning.feature.calendar.month import androidx.compose.foundation.background import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.pager.PagerState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -16,23 +17,22 @@ import com.terning.core.designsystem.extension.toast import com.terning.core.designsystem.state.UiState import com.terning.core.designsystem.theme.White import com.terning.domain.calendar.entity.CalendarScrap -import com.terning.feature.calendar.calendar.model.DayModel -import com.terning.feature.calendar.calendar.model.LocalPagerState -import com.terning.feature.calendar.calendar.model.TerningCalendarModel.Companion.LocalCalendarModel import com.terning.feature.calendar.calendar.component.pager.CalendarMonthPager +import com.terning.feature.calendar.calendar.model.DayModel +import com.terning.feature.calendar.calendar.model.TerningCalendarModel @Composable fun CalendarMonthRoute( selectedDate: DayModel, + calendarModel: TerningCalendarModel, + pagerState: PagerState, updateSelectedDate: (DayModel) -> Unit, modifier: Modifier = Modifier, viewModel: CalendarMonthViewModel = hiltViewModel() ) { - val calendarModel = LocalCalendarModel.current - val pagerState = LocalPagerState.current val context = LocalContext.current val lifecycleOwner = LocalLifecycleOwner.current - val uiState by viewModel.uiState.collectAsStateWithLifecycle(lifecycleOwner) + val uiState by viewModel.uiState.collectAsStateWithLifecycle() LaunchedEffect(viewModel.sideEffect, lifecycleOwner) { viewModel.sideEffect.flowWithLifecycle(lifecycle = lifecycleOwner.lifecycle) diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt index 8a8e488e..5d0da8b0 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt @@ -47,12 +47,10 @@ import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.designsystem.theme.White import com.terning.domain.calendar.entity.CalendarScrapDetail import com.terning.feature.calendar.R -import com.terning.feature.calendar.calendar.model.CalendarUiState -import com.terning.feature.calendar.calendar.model.DayModel -import com.terning.feature.calendar.calendar.model.LocalPagerState -import com.terning.feature.calendar.calendar.model.TerningCalendarModel import com.terning.feature.calendar.calendar.component.group.CalendarScrapListGroup import com.terning.feature.calendar.calendar.component.pager.CalendarWeekPager +import com.terning.feature.calendar.calendar.model.DayModel +import com.terning.feature.calendar.calendar.model.TerningCalendarModel import com.terning.feature.calendar.week.model.CalendarWeekUiState import com.terning.feature.dialog.cancel.ScrapCancelDialog import com.terning.feature.dialog.detail.ScrapDialog @@ -61,14 +59,15 @@ import java.time.LocalDate @Composable fun CalendarWeekRoute( - calendarUiState: CalendarUiState, + selectedDate: DayModel, + calendarModel: TerningCalendarModel, + pagerState: PagerState, navigateToAnnouncement: (Long) -> Unit, updateSelectedDate: (DayModel) -> Unit, navigateUp: () -> Unit, modifier: Modifier = Modifier, viewModel: CalendarWeekViewModel = hiltViewModel(), ) { - val pagerState = LocalPagerState.current val lifecycleOwner = LocalLifecycleOwner.current val uiState by viewModel.uiState.collectAsStateWithLifecycle(lifecycleOwner) @@ -82,8 +81,8 @@ fun CalendarWeekRoute( } } - LaunchedEffect(key1 = calendarUiState.selectedDate) { - viewModel.getScrapWeekList(selectedDate = calendarUiState.selectedDate.date) + LaunchedEffect(key1 = selectedDate) { + viewModel.getScrapWeekList(selectedDate = selectedDate.date) } BackHandler { @@ -91,11 +90,11 @@ fun CalendarWeekRoute( } CalendarWeekScreen( - modifier = modifier, + modifier = modifier.fillMaxSize(), pagerState = pagerState, - calendarModel = calendarUiState.calendarModel, + calendarModel = calendarModel, uiState = uiState, - selectedDate = calendarUiState.selectedDate, + selectedDate = selectedDate, updateSelectedDate = updateSelectedDate, onClickScrapButton = { scrapId -> with(viewModel) { @@ -112,7 +111,7 @@ fun CalendarWeekRoute( ) CalendarWeekScrapPatchDialog( - currentDate = calendarUiState.selectedDate.date, + currentDate = selectedDate.date, dialogVisibility = uiState.scrapDetailDialogVisibility, internshipModel = uiState.internshipModel, navigateToAnnouncement = { announcementId -> @@ -121,7 +120,7 @@ fun CalendarWeekRoute( }, onDismissInternDialog = { viewModel.updateScrapDetailDialogVisibility(false) }, onClickChangeColor = { - viewModel.getScrapWeekList(calendarUiState.selectedDate.date) + viewModel.getScrapWeekList(selectedDate.date) }, ) @@ -131,7 +130,7 @@ fun CalendarWeekRoute( onDismissCancelDialog = { isCancelled -> viewModel.updateScrapCancelDialogVisibility(false) if (isCancelled) { - viewModel.getScrapWeekList(calendarUiState.selectedDate.date) + viewModel.getScrapWeekList(selectedDate.date) } } ) From ee68943f6aa61b2ab97734fe25ef8c27c85c971d Mon Sep 17 00:00:00 2001 From: boiledegg Date: Thu, 12 Dec 2024 16:27:09 +0900 Subject: [PATCH 08/10] =?UTF-8?q?[REFACTOR/#305]=20Calendar=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 요일 enum 추가 - 컴포넌트 주석 추가 - 미사용 라이브러리 제거 --- .../calendar/calendar/CalendarViewModel.kt | 2 +- .../calendar/component/ScreenTransition.kt | 10 ++ .../calendar/component/WeekDaysHeader.kt | 18 +-- .../dialog/CalendarScrapCancelDialog.kt | 28 +++++ .../dialog/CalendarScrapPatchDialog.kt | 50 ++++++++ .../calendar/model/CalendarUiState.kt | 3 - .../calendar/model/TerningCalendarModel.kt | 1 - .../feature/calendar/calendar/type/WeekDay.kt | 19 +++ .../calendar/list/CalendarListScreen.kt | 119 +++++++----------- .../calendar/week/CalendarWeekScreen.kt | 62 +-------- 10 files changed, 159 insertions(+), 153 deletions(-) create mode 100644 feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/dialog/CalendarScrapCancelDialog.kt create mode 100644 feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/dialog/CalendarScrapPatchDialog.kt create mode 100644 feature/calendar/src/main/java/com/terning/feature/calendar/calendar/type/WeekDay.kt diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt index d1fed7a8..b8787976 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarViewModel.kt @@ -1,8 +1,8 @@ package com.terning.feature.calendar.calendar import androidx.lifecycle.ViewModel -import com.terning.feature.calendar.calendar.model.DayModel import com.terning.feature.calendar.calendar.model.CalendarUiState +import com.terning.feature.calendar.calendar.model.DayModel import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/ScreenTransition.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/ScreenTransition.kt index 21d8acdd..8d6e9bea 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/ScreenTransition.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/ScreenTransition.kt @@ -7,6 +7,16 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import com.terning.feature.calendar.R +/** + * 두 화면 간 전환을 담당하는 컴포넌트 + * + * @param targetState 전환할 상태 + * @param transitionOne 첫번째 화면에서 두번쨰 화면으로 이동할 때 발생할 전환 모션 + * @param transitionTwo 두번째 화면에서 첫번째 화면으로 이동할 때 발생할 전환 모션 + * @param contentOne 첫번째 화면 + * @param contentTwo 두번째 화면 + */ + @Composable fun ScreenTransition( targetState: Boolean, diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/WeekDaysHeader.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/WeekDaysHeader.kt index be398b0c..0e7d08fa 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/WeekDaysHeader.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/WeekDaysHeader.kt @@ -8,7 +8,6 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -16,7 +15,7 @@ import com.terning.core.designsystem.theme.Black import com.terning.core.designsystem.theme.SundayRed import com.terning.core.designsystem.theme.TerningPointTheme import com.terning.core.designsystem.theme.TerningTheme -import com.terning.feature.calendar.R +import com.terning.feature.calendar.calendar.type.WeekDay @Composable fun WeekDaysHeader( @@ -31,21 +30,12 @@ fun WeekDaysHeader( vertical = 18.dp ), ) { - val dayOfWeek = listOf( - R.string.calendar_text_sunday, - R.string.calendar_text_monday, - R.string.calendar_text_tuesday, - R.string.calendar_text_wednesday, - R.string.calendar_text_thursday, - R.string.calendar_text_friday, - R.string.calendar_text_saturday, - ) - dayOfWeek.forEach { day -> + WeekDay.entries.forEach { day -> Text( modifier = Modifier.weight(1f), - text = stringResource(id = day), + text = day.nameInKorean, style = TerningTheme.typography.body7, - color = if (day == R.string.calendar_text_sunday) SundayRed else Black, + color = if (WeekDay.isSunday(day)) SundayRed else Black, textAlign = TextAlign.Center ) } diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/dialog/CalendarScrapCancelDialog.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/dialog/CalendarScrapCancelDialog.kt new file mode 100644 index 00000000..60c62d54 --- /dev/null +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/dialog/CalendarScrapCancelDialog.kt @@ -0,0 +1,28 @@ +package com.terning.feature.calendar.calendar.component.dialog + +import androidx.compose.runtime.Composable +import com.terning.feature.dialog.cancel.ScrapCancelDialog + +/** + * 달력 스크랩 취소 다이얼로그 + * + * @param scrapVisibility 스크랩 취소 다이얼로그 가시 여부 + * @param internshipAnnouncementId 스크랩 취소를 진행할 공고 ID + * @param onDismissCancelDialog 스크랩 취소 다이얼로그 끄기 + */ + +@Composable +internal fun CalendarScrapCancelDialog( + scrapVisibility: Boolean, + internshipAnnouncementId: Long?, + onDismissCancelDialog: (Boolean) -> Unit, +) { + if (scrapVisibility) { + internshipAnnouncementId?.run { + ScrapCancelDialog( + internshipAnnouncementId = this, + onDismissRequest = onDismissCancelDialog + ) + } + } +} diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/dialog/CalendarScrapPatchDialog.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/dialog/CalendarScrapPatchDialog.kt new file mode 100644 index 00000000..9861c357 --- /dev/null +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/dialog/CalendarScrapPatchDialog.kt @@ -0,0 +1,50 @@ +package com.terning.feature.calendar.calendar.component.dialog + +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import com.terning.core.designsystem.extension.getFullDateStringInKorean +import com.terning.domain.calendar.entity.CalendarScrapDetail +import com.terning.feature.dialog.detail.ScrapDialog +import java.time.LocalDate + +/** + * 달력 스크랩 디테일 다이얼로그 + * + * @param date 선택된 날짜 + * @param dialogVisibility 스크랩 디테일 다이얼로그 가시 여부 + * @param internshipModel 스크랩 디테일 + * @param navigateToAnnouncement 공고 상세로 이동하는 이동 + * @param onDismissInternDialog 스크랩 디테일 다이얼로그 끄기 + * @param onClickChangeColor 스크랩 색상 변경 시 발생하는 이벤트 + */ + +@Composable +internal fun CalendarScrapPatchDialog( + date: LocalDate, + dialogVisibility: Boolean, + internshipModel: CalendarScrapDetail?, + navigateToAnnouncement: (Long) -> Unit, + onDismissInternDialog: (Boolean) -> Unit, + onClickChangeColor: () -> Unit, +) { + if (dialogVisibility && internshipModel != null) { + val scrapColor = Color( + android.graphics.Color.parseColor( + internshipModel.color + ) + ) + ScrapDialog( + title = internshipModel.title, + scrapColor = scrapColor, + deadline = date.getFullDateStringInKorean(), + startYearMonth = internshipModel.startYearMonth, + workingPeriod = internshipModel.workingPeriod, + internshipAnnouncementId = internshipModel.internshipAnnouncementId, + companyImage = internshipModel.companyImage, + isScrapped = true, + onDismissRequest = onDismissInternDialog, + onClickChangeColor = onClickChangeColor, + onClickNavigateButton = navigateToAnnouncement + ) + } +} diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt index 7273a807..1373729b 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/CalendarUiState.kt @@ -1,8 +1,5 @@ package com.terning.feature.calendar.calendar.model -import androidx.compose.foundation.pager.PagerState -import androidx.compose.runtime.compositionLocalOf - data class CalendarUiState( val selectedDate: DayModel = DayModel(), val calendarModel: TerningCalendarModel = TerningCalendarModel(), diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/TerningCalendarModel.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/TerningCalendarModel.kt index 3f7b5a56..6733555f 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/TerningCalendarModel.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/model/TerningCalendarModel.kt @@ -1,7 +1,6 @@ package com.terning.feature.calendar.calendar.model import androidx.compose.runtime.Immutable -import androidx.compose.runtime.staticCompositionLocalOf import java.time.LocalDate import java.time.YearMonth diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/type/WeekDay.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/type/WeekDay.kt new file mode 100644 index 00000000..ce5de1cb --- /dev/null +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/type/WeekDay.kt @@ -0,0 +1,19 @@ +package com.terning.feature.calendar.calendar.type + +enum class WeekDay( + val nameInKorean: String, +) { + SUNDAY(nameInKorean = "일"), + MONDAY(nameInKorean = "월"), + TUESDAY(nameInKorean = "화"), + WEDNESDAY(nameInKorean = "수"), + THURSDAY(nameInKorean = "목"), + FRIDAY(nameInKorean = "금"), + SATURDAY(nameInKorean = "토"); + + companion object { + fun isSunday(weekDay: WeekDay): Boolean { + return weekDay == SUNDAY + } + } +} diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt index be99dfde..e8cf6898 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/list/CalendarListScreen.kt @@ -18,7 +18,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -38,11 +37,11 @@ import com.terning.core.designsystem.theme.Grey400 import com.terning.core.designsystem.theme.TerningTheme import com.terning.domain.calendar.entity.CalendarScrapDetail import com.terning.feature.calendar.R +import com.terning.feature.calendar.calendar.component.dialog.CalendarScrapCancelDialog +import com.terning.feature.calendar.calendar.component.dialog.CalendarScrapPatchDialog import com.terning.feature.calendar.calendar.component.group.CalendarScrapListGroup import com.terning.feature.calendar.calendar.model.TerningCalendarModel import com.terning.feature.calendar.list.model.CalendarListUiState -import com.terning.feature.dialog.cancel.ScrapCancelDialog -import com.terning.feature.dialog.detail.ScrapDialog import okhttp3.internal.toImmutableList import java.time.LocalDate @@ -56,9 +55,10 @@ fun CalendarListRoute( viewModel: CalendarListViewModel = hiltViewModel(), ) { val lifecycleOwner = LocalLifecycleOwner.current - val uiState by viewModel.uiState.collectAsStateWithLifecycle(lifecycleOwner) val context = LocalContext.current + val uiState by viewModel.uiState.collectAsStateWithLifecycle() + LaunchedEffect(viewModel.sideEffect, lifecycleOwner) { viewModel.sideEffect.flowWithLifecycle(lifecycle = lifecycleOwner.lifecycle) .collect { sideEffect -> @@ -100,8 +100,8 @@ fun CalendarListRoute( } ) - CalendarListScrapPatchDialog( - currentDate = uiState.currentDate, + CalendarScrapPatchDialog( + date = uiState.currentDate, dialogVisibility = uiState.scrapDetailDialogVisibility, internshipModel = uiState.internshipModel, navigateToAnnouncement = { announcementId -> @@ -114,7 +114,7 @@ fun CalendarListRoute( }, ) - CalendarListScrapCancelDialog( + CalendarScrapCancelDialog( scrapVisibility = uiState.scrapCancelDialogVisibility, internshipAnnouncementId = uiState.internshipAnnouncementId, onDismissCancelDialog = { isCancelled -> @@ -140,7 +140,6 @@ private fun CalendarListScreen( state = pagerState, modifier = modifier ) { page -> - val getDate = calendarModel.getLocalDateByPage(page) LazyColumn( modifier = Modifier @@ -163,31 +162,15 @@ private fun CalendarListScreen( 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) - ) - - CalendarScrapListGroup( - scrapList = scrapMap[dateInKorean].orEmpty().toImmutableList(), - onScrapButtonClicked = onClickScrapButton, - onInternshipClicked = onClickInternship, - isFromList = true, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 24.dp) - ) - } + val date = calendarModel.getLocalDateByPage(page) + + items(date.lengthOfMonth()) { day -> + CalendarListSuccess( + date = LocalDate.of(date.year, date.monthValue, day + 1), + scrapMap = uiState.loadState.data, + onClickScrapButton = onClickScrapButton, + onClickInternship = onClickInternship, + ) } } } @@ -218,50 +201,32 @@ 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: (Boolean) -> Unit, - onClickChangeColor: () -> Unit, +private fun CalendarListSuccess( + date: LocalDate, + scrapMap: Map>, + onClickScrapButton: (Long) -> Unit, + onClickInternship: (CalendarScrapDetail) -> Unit, + modifier: Modifier = Modifier, ) { - 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 - ) - } + val dateInKorean = date.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) + ) + + CalendarScrapListGroup( + scrapList = scrapMap[dateInKorean].orEmpty().toImmutableList(), + onScrapButtonClicked = onClickScrapButton, + onInternshipClicked = onClickInternship, + isFromList = true, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 24.dp) + ) } } diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt index 5d0da8b0..ab22b7fe 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/week/CalendarWeekScreen.kt @@ -24,7 +24,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.shadow -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -35,7 +34,6 @@ import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.flowWithLifecycle import com.terning.core.designsystem.extension.getDateStringInKorean -import com.terning.core.designsystem.extension.getFullDateStringInKorean import com.terning.core.designsystem.extension.swipableVertically import com.terning.core.designsystem.extension.toast import com.terning.core.designsystem.state.UiState @@ -47,15 +45,14 @@ import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.designsystem.theme.White import com.terning.domain.calendar.entity.CalendarScrapDetail import com.terning.feature.calendar.R +import com.terning.feature.calendar.calendar.component.dialog.CalendarScrapCancelDialog +import com.terning.feature.calendar.calendar.component.dialog.CalendarScrapPatchDialog import com.terning.feature.calendar.calendar.component.group.CalendarScrapListGroup import com.terning.feature.calendar.calendar.component.pager.CalendarWeekPager import com.terning.feature.calendar.calendar.model.DayModel import com.terning.feature.calendar.calendar.model.TerningCalendarModel import com.terning.feature.calendar.week.model.CalendarWeekUiState -import com.terning.feature.dialog.cancel.ScrapCancelDialog -import com.terning.feature.dialog.detail.ScrapDialog import okhttp3.internal.toImmutableList -import java.time.LocalDate @Composable fun CalendarWeekRoute( @@ -110,8 +107,8 @@ fun CalendarWeekRoute( }, ) - CalendarWeekScrapPatchDialog( - currentDate = selectedDate.date, + CalendarScrapPatchDialog( + date = selectedDate.date, dialogVisibility = uiState.scrapDetailDialogVisibility, internshipModel = uiState.internshipModel, navigateToAnnouncement = { announcementId -> @@ -124,7 +121,7 @@ fun CalendarWeekRoute( }, ) - CalendarWeekScrapCancelDialog( + CalendarScrapCancelDialog( scrapVisibility = uiState.scrapCancelDialogVisibility, internshipAnnouncementId = uiState.internshipAnnouncementId, onDismissCancelDialog = { isCancelled -> @@ -265,55 +262,6 @@ 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: (Boolean) -> 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 - ) - } - } -} - From 3dbc4a63f093a4573469a31dd87f1e2d39f2fa18 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Thu, 12 Dec 2024 16:58:44 +0900 Subject: [PATCH 09/10] =?UTF-8?q?[FIX/#305]=20=EC=A0=84=ED=99=98=20?= =?UTF-8?q?=EB=AA=A8=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../calendar/calendar/CalendarRoute.kt | 24 +++++++++++++------ .../calendar/component/ScreenTransition.kt | 11 ++++----- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt index c0b19646..fe3db7cb 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/CalendarRoute.kt @@ -1,6 +1,8 @@ package com.terning.feature.calendar.calendar +import androidx.compose.animation.core.Transition import androidx.compose.animation.core.tween +import androidx.compose.animation.core.updateTransition import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutHorizontally @@ -78,6 +80,11 @@ private fun CalendarScreen( ) { val coroutineScope = rememberCoroutineScope() + val calendarListTransition = + updateTransition(!uiState.isListEnabled, label = "calendarListTransition") + val monthWeekTransition = + updateTransition(!uiState.isWeekEnabled, label = "monthWeekTransition") + val pagerState = rememberPagerState( initialPage = uiState.calendarModel.initialPage, pageCount = { uiState.calendarModel.pageCount } @@ -107,7 +114,10 @@ private fun CalendarScreen( CalendarTopAppBar( date = uiState.calendarModel.getYearMonthByPage(pagerState.settledPage), isListExpanded = uiState.isListEnabled, - onListButtonClicked = onClickListButton, + onListButtonClicked = { + if(!calendarListTransition.isRunning) + onClickListButton() + }, onMonthNavigationButtonClicked = { direction -> coroutineScope.launch { pagerState.animateScrollToPage( @@ -119,7 +129,7 @@ private fun CalendarScreen( ) CalendarListTransition( - isCalendarEnabled = !uiState.isListEnabled, + transition = calendarListTransition, calendarModel = uiState.calendarModel, pagerState = pagerState, onNavigateToAnnouncement = navigateToAnnouncement, @@ -137,7 +147,7 @@ private fun CalendarScreen( ) MonthWeekTransition( - isMonthEnabled = !uiState.isWeekEnabled, + transition = monthWeekTransition, selectedDate = uiState.selectedDate, calendarModel = uiState.calendarModel, pagerState = pagerState, @@ -155,7 +165,7 @@ private fun CalendarScreen( /** 달력 <-> 목록 전환 컴포저블 */ @Composable private fun CalendarListTransition( - isCalendarEnabled: Boolean, + transition: Transition, calendarModel: TerningCalendarModel, pagerState: PagerState, onNavigateToAnnouncement: (Long) -> Unit, @@ -163,7 +173,7 @@ private fun CalendarListTransition( calendarContent: @Composable () -> Unit, ) { ScreenTransition( - targetState = isCalendarEnabled, + transition = transition, transitionOne = slideInHorizontally { fullWidth -> -fullWidth } togetherWith slideOutHorizontally { fullWidth -> fullWidth }, transitionTwo = slideInHorizontally { fullWidth -> fullWidth } togetherWith @@ -187,7 +197,7 @@ private fun CalendarListTransition( /**월간 <-> 주간 전환 컴포저블*/ @Composable private fun MonthWeekTransition( - isMonthEnabled: Boolean, + transition: Transition, selectedDate: DayModel, calendarModel: TerningCalendarModel, pagerState: PagerState, @@ -196,7 +206,7 @@ private fun MonthWeekTransition( onNavigateUpToMonth: () -> Unit, ) { ScreenTransition( - targetState = isMonthEnabled, + transition = transition, transitionOne = slideInVertically { fullHeight -> -fullHeight } togetherWith slideOutVertically { fullHeight -> fullHeight }, transitionTwo = slideInVertically { fullHeight -> fullHeight } togetherWith diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/ScreenTransition.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/ScreenTransition.kt index 8d6e9bea..aeebc955 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/ScreenTransition.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/ScreenTransition.kt @@ -3,14 +3,13 @@ package com.terning.feature.calendar.calendar.component import androidx.compose.animation.AnimatedContent import androidx.compose.animation.ContentTransform import androidx.compose.animation.SizeTransform +import androidx.compose.animation.core.Transition import androidx.compose.runtime.Composable -import androidx.compose.ui.res.stringResource -import com.terning.feature.calendar.R /** * 두 화면 간 전환을 담당하는 컴포넌트 * - * @param targetState 전환할 상태 + * @param transition [Transition] * @param transitionOne 첫번째 화면에서 두번쨰 화면으로 이동할 때 발생할 전환 모션 * @param transitionTwo 두번째 화면에서 첫번째 화면으로 이동할 때 발생할 전환 모션 * @param contentOne 첫번째 화면 @@ -19,14 +18,13 @@ import com.terning.feature.calendar.R @Composable fun ScreenTransition( - targetState: Boolean, + transition: Transition, transitionOne: ContentTransform, transitionTwo: ContentTransform, contentOne: @Composable () -> Unit, contentTwo: @Composable () -> Unit ) { - AnimatedContent( - targetState = targetState, + transition.AnimatedContent( transitionSpec = { if (targetState) { transitionOne @@ -36,7 +34,6 @@ fun ScreenTransition( sizeTransform = SizeTransform(clip = true) ) }, - label = stringResource(id = R.string.calendar_animation_label) ) { state -> if (state) { contentOne.invoke() From 2743ab1ab60115e09591f1310ac8579ab5cde025 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Wed, 18 Dec 2024 19:14:51 +0900 Subject: [PATCH 10/10] =?UTF-8?q?[REFACTOR/#305]=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EA=B8=B0=EB=B0=98=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../calendar/calendar/component/group/CalendarMonthGroup.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarMonthGroup.kt b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarMonthGroup.kt index 564a1a56..3115c691 100644 --- a/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarMonthGroup.kt +++ b/feature/calendar/src/main/java/com/terning/feature/calendar/calendar/component/group/CalendarMonthGroup.kt @@ -50,7 +50,6 @@ internal fun CalendarMonthGroup( .fillMaxSize() .background(White) .padding(horizontal = 20.dp) - ) { dayModels.forEach {week -> CalendarWeekGroup(