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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,25 +1,130 @@
package com.cherrish.android.presentation.calendar

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.cherrish.android.core.common.state.UiState
import com.cherrish.android.core.designsystem.theme.CherrishTheme
import com.cherrish.android.presentation.calendar.component.CherrishCalendar
import com.cherrish.android.presentation.calendar.component.ProcedureScheduleCard
import java.time.LocalDate
import java.time.YearMonth

@Composable
fun CalendarRoute(
paddingValues: PaddingValues
paddingValues: PaddingValues,
viewModel: CalendarViewModel = hiltViewModel()
) {
CalendarScreen(paddingValues = paddingValues)
val uiState by viewModel.uiState.collectAsStateWithLifecycle()

when (val state = uiState) {
is UiState.Loading -> {

}

is UiState.Failure -> {

}

is UiState.Success -> {
CalendarScreen(
uiState = state.data,
paddingValues = paddingValues,
onMonthChange = viewModel::onMonthChanged,
onDateClick = viewModel::onDateClick,
onEventClick = viewModel::onEventClick
)
}

else -> {}
}
}
Comment thread
nhyeonii marked this conversation as resolved.

@Composable
private fun CalendarScreen(
paddingValues: PaddingValues,
uiState: CalendarUiState,
onMonthChange: (YearMonth) -> Unit,
onDateClick: (LocalDate) -> Unit,
onEventClick: (Long) -> Unit,
modifier: Modifier = Modifier
) {
Text(
"Calendar",
modifier = modifier.padding(paddingValues)
)
Column(
modifier = modifier
.fillMaxSize()
.background(color = CherrishTheme.colors.gray100)
.padding(paddingValues)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P4: padding이 두 번 들어가있는 것 같은데 이유를 알 수 있을까욥??

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아하 ㅎㅎ 여기서의 paddingValues는 상위 MainScreen에서 받아오는 패딩값 (Scaffold 의 innerPadding)이 전달되는거고, 아래의 패딩값은 실제 화면에서 보이는 수직, 수평 패딩을 의미합니다!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아아 이래서 그래야 하는거군요 !!!저도 리팩토링 요 방식으로 해보겠습니다 !!

.padding(top = 18.dp, bottom = 26.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(20.dp)
) {
CherrishCalendar(
yearMonth = uiState.selectedYearMonth,
selectedDate = uiState.selectedDate,
displayMode = uiState.calendarDisplayMode,
onDateClick = onDateClick,
onMonthChange = onMonthChange,
modifier = Modifier.padding(horizontal = 5.dp)
)

ProcedureScheduleCard(
displayMode = uiState.calendarDisplayMode,
procedureInfo = uiState.procedureInfoList,
onClick = onEventClick,
modifier = Modifier.padding(horizontal = 17.dp)
)
}
}
Comment thread
nhyeonii marked this conversation as resolved.

@Preview
@Composable
private fun CalendarScreenNormalPreview() {
CherrishTheme {
CalendarScreen(
paddingValues = PaddingValues(0.dp),
uiState = CalendarUiState.FakeNormal,
onDateClick = { },
onMonthChange = { },
onEventClick = { }
)
}
}

@Preview
@Composable
private fun CalendarScreenDowntimePreview() {
CherrishTheme {
CalendarScreen(
paddingValues = PaddingValues(0.dp),
uiState = CalendarUiState.FakeDowntime,
onDateClick = { },
onMonthChange = { },
onEventClick = { }
)
}
}

@Preview
@Composable
private fun CalendarScreenNoSchedulePreview() {
CherrishTheme {
CalendarScreen(
paddingValues = PaddingValues(0.dp),
uiState = CalendarUiState.FakeEmpty,
onDateClick = { },
onMonthChange = { },
onEventClick = { }
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.cherrish.android.presentation.calendar

import androidx.compose.runtime.Immutable
import com.cherrish.android.presentation.calendar.model.CalendarDisplayMode
import com.cherrish.android.presentation.calendar.model.DownTimeStatus
import com.cherrish.android.presentation.calendar.model.ProcedureInfoModel
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import java.time.LocalDate
import java.time.YearMonth

@Immutable
data class CalendarUiState(
val selectedYearMonth: YearMonth = YearMonth.now(),
val calendarDisplayMode: CalendarDisplayMode = CalendarDisplayMode.Normal(),
val selectedDate: LocalDate? = LocalDate.now(),
val procedureInfoList: ImmutableList<ProcedureInfoModel> = persistentListOf(),
) {
companion object {
private val today = LocalDate.of(2026, 1, 7)

private val mockProcedures = persistentListOf(
ProcedureInfoModel(
procedureId = 1L,
procedureName = "레이저 토닝",
procedureDay = "1월 7일 수요일",
downTimeDuration = 5
),
ProcedureInfoModel(
procedureId = 2L,
procedureName = "레이저 토닝",
procedureDay = "1월 7일 수요일",
downTimeDuration = 5
),
ProcedureInfoModel(
procedureId = 3L,
procedureName = "울쎄라",
procedureDay = "1월 7일 수요일",
downTimeDuration = 3
)
)

val FakeNormal = CalendarUiState(
selectedYearMonth = YearMonth.of(2026, 1),
calendarDisplayMode = CalendarDisplayMode.Normal(
procedureCountByDate = mapOf(
today to 3,
LocalDate.of(2026, 1, 9) to 1,
LocalDate.of(2026, 1, 19) to 2
)
),
selectedDate = today,
procedureInfoList = mockProcedures
)

val FakeDowntime = CalendarUiState(
selectedYearMonth = YearMonth.of(2026, 1),
calendarDisplayMode = CalendarDisplayMode.Downtime(
downtimeByDate = mapOf(
today to DownTimeStatus.SENSITIVE,
today.plusDays(1) to DownTimeStatus.SENSITIVE,
today.plusDays(2) to DownTimeStatus.CAUTION,
today.plusDays(3) to DownTimeStatus.RECOVERY
),
selectedProcedureId = 1L
),
selectedDate = today,
procedureInfoList = mockProcedures
)

val FakeEmpty = CalendarUiState(
selectedYearMonth = YearMonth.of(2026, 1),
calendarDisplayMode = CalendarDisplayMode.Normal(),
selectedDate = LocalDate.of(2026, 1, 15),
procedureInfoList = persistentListOf()
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.cherrish.android.presentation.calendar

import androidx.lifecycle.ViewModel
import com.cherrish.android.core.common.extension.updateSuccess
import com.cherrish.android.core.common.state.UiState
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import java.time.LocalDate
import java.time.YearMonth
import javax.inject.Inject

@HiltViewModel
class CalendarViewModel @Inject constructor() : ViewModel() {

private val _uiState = MutableStateFlow<UiState<CalendarUiState>>(
UiState.Success(CalendarUiState.FakeNormal)
)
val uiState: StateFlow<UiState<CalendarUiState>> = _uiState.asStateFlow()

fun onMonthChanged(yearMonth: YearMonth) {
_uiState.updateSuccess { currentState ->
currentState.copy(
selectedYearMonth = yearMonth,
selectedDate = null,
procedureInfoList = persistentListOf()
)
}
}

fun onDateClick(date: LocalDate) {

}

fun onEventClick(procedureId: Long) {

}

}
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package com.cherrish.android.presentation.calendar.model

import kotlinx.collections.immutable.persistentMapOf
import java.time.LocalDate

sealed interface CalendarDisplayMode {
data class Normal(
val procedureCountByDate: Map<LocalDate, Int>
val procedureCountByDate: Map<LocalDate, Int> = persistentMapOf()
) : CalendarDisplayMode

data class Downtime(
val downtimeByDate: Map<LocalDate, DownTimeStatus>,
val downtimeByDate: Map<LocalDate, DownTimeStatus> = persistentMapOf(),
val selectedProcedureId: Long? = null
) : CalendarDisplayMode
}
Loading