From 00754bdb353cc734d5bc1b7cd523ead7d32bf628 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Sat, 6 Jul 2024 00:28:40 +0900 Subject: [PATCH 01/19] =?UTF-8?q?[ADD/#9]=20Preview=20=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feature/build.gradle.kts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/feature/build.gradle.kts b/feature/build.gradle.kts index 56209c2ce..3a3843ba0 100644 --- a/feature/build.gradle.kts +++ b/feature/build.gradle.kts @@ -91,4 +91,8 @@ dependencies { implementation(libs.ossLicense) implementation(libs.lottie) + //Compose Preview + implementation(libs.androidx.compose.ui.tooling) + implementation(libs.androidx.compose.ui.tooling.preview) + } \ No newline at end of file From b26784dd0f0d7be8ce5ee630172858b500696f55 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Sat, 6 Jul 2024 01:44:00 +0900 Subject: [PATCH 02/19] =?UTF-8?q?[UI/#9]=20TopBar=EC=99=80=20=EC=9A=94?= =?UTF-8?q?=EC=9D=BC=20=ED=97=A4=EB=8D=94=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/calendar/CalendarTopBar.kt | 96 +++++++++++++++++++ .../feature/calendar/WeekDaysHeader.kt | 60 ++++++++++++ .../drawable/ic_calendar_list_selected.xml | 13 +++ .../drawable/ic_calendar_list_unselected.xml | 13 +++ .../main/res/drawable/ic_calendar_next.xml | 9 ++ .../res/drawable/ic_calendar_previous.xml | 13 +++ feature/src/main/res/drawable/ic_home.xml | 8 +- feature/src/main/res/values/strings.xml | 11 +++ 8 files changed, 219 insertions(+), 4 deletions(-) create mode 100644 feature/src/main/java/com/terning/feature/calendar/CalendarTopBar.kt create mode 100644 feature/src/main/java/com/terning/feature/calendar/WeekDaysHeader.kt create mode 100644 feature/src/main/res/drawable/ic_calendar_list_selected.xml create mode 100644 feature/src/main/res/drawable/ic_calendar_list_unselected.xml create mode 100644 feature/src/main/res/drawable/ic_calendar_next.xml create mode 100644 feature/src/main/res/drawable/ic_calendar_previous.xml diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarTopBar.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarTopBar.kt new file mode 100644 index 000000000..68722b737 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/CalendarTopBar.kt @@ -0,0 +1,96 @@ +package com.terning.feature.calendar + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Icon +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.res.painterResource +import androidx.compose.ui.res.stringResource +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.Grey300 +import com.terning.core.designsystem.theme.TerningTheme +import com.terning.core.extension.noRippleClickable +import com.terning.feature.R + +@Composable +fun CalendarTopBar( + modifier: Modifier = Modifier, + title: String, + isListExpanded: Boolean, + onListButtonClicked: () -> Unit, + onMonthNavigationButtonClicked: (Int) -> Unit, +) { + Box( + modifier = modifier + .fillMaxWidth() + .background(color = Color.White) + .padding( + top = 23.dp, + bottom = 22.dp, + start = 22.dp, + end = 22.dp) + ) { + Row( + modifier = Modifier.align(Alignment.Center), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + painter = painterResource(id = R.drawable.ic_calendar_previous), + contentDescription = stringResource(id = R.string.calendar_button_description_previous), + tint = Grey300, + modifier = Modifier.noRippleClickable { onMonthNavigationButtonClicked(-1) } + ) + Text( + text = title, + style = TerningTheme.typography.title2, + color = Black, + modifier = Modifier.padding(horizontal = 8.dp) + ) + Icon( + painter = painterResource(id = R.drawable.ic_calendar_next), + contentDescription = stringResource(id = R.string.calendar_button_description_next), + tint = Grey300, + modifier = Modifier.noRippleClickable { onMonthNavigationButtonClicked(1) } + ) + } + Box( + modifier = Modifier + .align(Alignment.CenterEnd) + ) { + Icon( + painter = painterResource( + id = if (isListExpanded) { + R.drawable.ic_calendar_list_selected + } else { + R.drawable.ic_calendar_list_unselected + } + ), + contentDescription = stringResource(id = R.string.calendar_button_description_list), + modifier = Modifier.noRippleClickable { onListButtonClicked() }, + tint = if (isListExpanded) Color.Green else Color.LightGray, + ) + } + } +} + +@Preview(showBackground = true) +@Composable +fun CalendarTopBarPreview() { + TerningTheme { + CalendarTopBar( + title = "2024년 7월", + isListExpanded = false, + onListButtonClicked = {}, + onMonthNavigationButtonClicked = {} + ) + } +} \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/calendar/WeekDaysHeader.kt b/feature/src/main/java/com/terning/feature/calendar/WeekDaysHeader.kt new file mode 100644 index 000000000..f08f3cb45 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/WeekDaysHeader.kt @@ -0,0 +1,60 @@ +package com.terning.feature.calendar + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +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.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.terning.core.designsystem.theme.Black +import com.terning.core.designsystem.theme.SundayRed +import com.terning.core.designsystem.theme.TerningTheme +import com.terning.feature.R + +@Composable +fun WeekDaysHeader( + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier + .fillMaxWidth() + .background(Color.White) + .padding( + horizontal = 37.dp, + vertical = 18.dp), + horizontalArrangement = Arrangement.SpaceBetween + ){ + 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 -> + Text( + modifier = Modifier, + text = stringResource(id = day), + style = TerningTheme.typography.body7, + color = if(day == R.string.calendar_text_sunday) SundayRed else Black, + fontSize = 13.sp + ) + } + } +} + +@Preview(showBackground = true) +@Composable +fun WeekDaysHeaderPreview() { + TerningTheme{ + WeekDaysHeader() + } +} \ No newline at end of file diff --git a/feature/src/main/res/drawable/ic_calendar_list_selected.xml b/feature/src/main/res/drawable/ic_calendar_list_selected.xml new file mode 100644 index 000000000..686920353 --- /dev/null +++ b/feature/src/main/res/drawable/ic_calendar_list_selected.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/feature/src/main/res/drawable/ic_calendar_list_unselected.xml b/feature/src/main/res/drawable/ic_calendar_list_unselected.xml new file mode 100644 index 000000000..fa8821985 --- /dev/null +++ b/feature/src/main/res/drawable/ic_calendar_list_unselected.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/feature/src/main/res/drawable/ic_calendar_next.xml b/feature/src/main/res/drawable/ic_calendar_next.xml new file mode 100644 index 000000000..36a9b4af7 --- /dev/null +++ b/feature/src/main/res/drawable/ic_calendar_next.xml @@ -0,0 +1,9 @@ + + + diff --git a/feature/src/main/res/drawable/ic_calendar_previous.xml b/feature/src/main/res/drawable/ic_calendar_previous.xml new file mode 100644 index 000000000..f9001fd4b --- /dev/null +++ b/feature/src/main/res/drawable/ic_calendar_previous.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/feature/src/main/res/drawable/ic_home.xml b/feature/src/main/res/drawable/ic_home.xml index 6fcd9a120..9b5f41b94 100644 --- a/feature/src/main/res/drawable/ic_home.xml +++ b/feature/src/main/res/drawable/ic_home.xml @@ -3,7 +3,7 @@ android:height="18dp" android:viewportWidth="18" android:viewportHeight="18"> - - + + \ No newline at end of file diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index 51ab71090..6a7da7ac8 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -8,4 +8,15 @@ first mock + + + + + + + + previous + next + list + \ No newline at end of file From 6cd55a19725cda7bd478f73f150dc381e76a2f63 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Sun, 7 Jul 2024 04:18:29 +0900 Subject: [PATCH 03/19] =?UTF-8?q?[FEAT/#9]=20Day,=20Month=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EB=AA=A8=EB=8D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/calendar/models/DayModel.kt | 10 +++++ .../feature/calendar/models/MonthModel.kt | 37 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 feature/src/main/java/com/terning/feature/calendar/models/DayModel.kt create mode 100644 feature/src/main/java/com/terning/feature/calendar/models/MonthModel.kt diff --git a/feature/src/main/java/com/terning/feature/calendar/models/DayModel.kt b/feature/src/main/java/com/terning/feature/calendar/models/DayModel.kt new file mode 100644 index 000000000..891a9f470 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/models/DayModel.kt @@ -0,0 +1,10 @@ +package com.terning.feature.calendar.models + +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/src/main/java/com/terning/feature/calendar/models/MonthModel.kt b/feature/src/main/java/com/terning/feature/calendar/models/MonthModel.kt new file mode 100644 index 000000000..01a10041d --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/models/MonthModel.kt @@ -0,0 +1,37 @@ +package com.terning.feature.calendar.models + +import androidx.compose.runtime.Immutable +import java.time.YearMonth + +@Immutable +data class MonthModel( + val yearMonth: YearMonth, + val weekDays: List> +) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as MonthModel + + if (yearMonth != other.yearMonth) return false + if (weekDays.first().first() != other.weekDays.first().first()) return false + if (weekDays.last().last() != other.weekDays.last().last()) return false + + return true + } + + override fun hashCode(): Int { + var result = yearMonth.hashCode() + result = 31 * result + weekDays.first().first().hashCode() + result = 31 * result + weekDays.last().last().hashCode() + return result + } + + override fun toString(): String { + return "CalendarMonth { " + + "first = ${weekDays.first().first()}, " + + "last = ${weekDays.last().last()} " + + "} " + } +} From c71a9f83d6109694755355decb1c62009e6bf36c Mon Sep 17 00:00:00 2001 From: boiledegg Date: Sun, 7 Jul 2024 04:19:07 +0900 Subject: [PATCH 04/19] =?UTF-8?q?[FEAT/#9]=20=EC=9B=94=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=EB=B0=8F=20=EB=8B=AC=EB=A0=A5=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/calendar/models/CalendarState.kt | 61 +++++++++++++++++++ .../feature/calendar/models/MonthData.kt | 30 +++++++++ 2 files changed, 91 insertions(+) create mode 100644 feature/src/main/java/com/terning/feature/calendar/models/CalendarState.kt create mode 100644 feature/src/main/java/com/terning/feature/calendar/models/MonthData.kt diff --git a/feature/src/main/java/com/terning/feature/calendar/models/CalendarState.kt b/feature/src/main/java/com/terning/feature/calendar/models/CalendarState.kt new file mode 100644 index 000000000..bb8764f9e --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/models/CalendarState.kt @@ -0,0 +1,61 @@ +package com.terning.feature.calendar.models + +import androidx.compose.runtime.Stable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import java.time.LocalDate +import java.time.YearMonth + +@Stable +class CalendarState internal constructor( + startMonth: YearMonth = YearMonth.of(START_YEAR, 1), + endMonth: YearMonth = YearMonth.of(END_YEAR, 12), + firstVisibleMonth: YearMonth = YearMonth.now(), +) { + private var _startMonth by mutableStateOf(startMonth) + var startMonth: YearMonth + get() = _startMonth + set(value) { + if (value != _startMonth) { + _startMonth = value + } + } + + private var _endMonth by mutableStateOf(endMonth) + var endMonth: YearMonth + get() = _endMonth + set(value) { + if (value != _endMonth) { + _endMonth = value + } + } + + private var _firstVisibleMonth by mutableStateOf(firstVisibleMonth) + var firstVisibleMonth: YearMonth + get() = _firstVisibleMonth + set(value) { + if (value != _firstVisibleMonth) { + _firstVisibleMonth = value + } + } + + fun getPageCount(): Int { + return (END_YEAR - START_YEAR) * 12 + } + + fun getInitialPage(): Int { + return (firstVisibleMonth.year - START_YEAR) * 12 + firstVisibleMonth.monthValue - 1 + } + + companion object { + const val START_YEAR = 2020 + const val END_YEAR = 2030 + + fun getDateByPage(page: Int): LocalDate = LocalDate.of( + START_YEAR + page / 12, + page % 12 + 1, + 1 + ) + } +} \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/calendar/models/MonthData.kt b/feature/src/main/java/com/terning/feature/calendar/models/MonthData.kt new file mode 100644 index 000000000..2c82457bc --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/models/MonthData.kt @@ -0,0 +1,30 @@ +package com.terning.feature.calendar.models + +import androidx.compose.runtime.Immutable +import java.time.YearMonth + +@Immutable +data class MonthData( + 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) + 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) + } +} From 45df9d92766c28ed5f8e7e306e482f502b57ddfe Mon Sep 17 00:00:00 2001 From: boiledegg Date: Sun, 7 Jul 2024 04:19:44 +0900 Subject: [PATCH 05/19] =?UTF-8?q?[MOD/#9]=20=EB=8B=AC=EB=A0=A5=20=ED=97=A4?= =?UTF-8?q?=EB=8D=94,=20=ED=83=91=EB=B0=94=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/terning/feature/calendar/CalendarTopBar.kt | 8 +++++--- .../com/terning/feature/calendar/WeekDaysHeader.kt | 10 ++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarTopBar.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarTopBar.kt index 68722b737..a45309d84 100644 --- a/feature/src/main/java/com/terning/feature/calendar/CalendarTopBar.kt +++ b/feature/src/main/java/com/terning/feature/calendar/CalendarTopBar.kt @@ -18,13 +18,15 @@ import androidx.compose.ui.unit.dp import com.terning.core.designsystem.theme.Black import com.terning.core.designsystem.theme.Grey300 import com.terning.core.designsystem.theme.TerningTheme +import com.terning.core.extension.getStringAsTitle import com.terning.core.extension.noRippleClickable import com.terning.feature.R +import java.time.LocalDate @Composable fun CalendarTopBar( modifier: Modifier = Modifier, - title: String, + date: LocalDate, isListExpanded: Boolean, onListButtonClicked: () -> Unit, onMonthNavigationButtonClicked: (Int) -> Unit, @@ -50,7 +52,7 @@ fun CalendarTopBar( modifier = Modifier.noRippleClickable { onMonthNavigationButtonClicked(-1) } ) Text( - text = title, + text = date.getStringAsTitle(), style = TerningTheme.typography.title2, color = Black, modifier = Modifier.padding(horizontal = 8.dp) @@ -87,7 +89,7 @@ fun CalendarTopBar( fun CalendarTopBarPreview() { TerningTheme { CalendarTopBar( - title = "2024년 7월", + date = LocalDate.now(), isListExpanded = false, onListButtonClicked = {}, onMonthNavigationButtonClicked = {} diff --git a/feature/src/main/java/com/terning/feature/calendar/WeekDaysHeader.kt b/feature/src/main/java/com/terning/feature/calendar/WeekDaysHeader.kt index f08f3cb45..21bcbeed6 100644 --- a/feature/src/main/java/com/terning/feature/calendar/WeekDaysHeader.kt +++ b/feature/src/main/java/com/terning/feature/calendar/WeekDaysHeader.kt @@ -5,11 +5,13 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width 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 import androidx.compose.ui.unit.sp @@ -27,9 +29,8 @@ fun WeekDaysHeader( .fillMaxWidth() .background(Color.White) .padding( - horizontal = 37.dp, + horizontal = 20.dp, vertical = 18.dp), - horizontalArrangement = Arrangement.SpaceBetween ){ val dayOfWeek = listOf( R.string.calendar_text_sunday, @@ -41,11 +42,12 @@ fun WeekDaysHeader( R.string.calendar_text_saturday,) dayOfWeek.forEach { day -> Text( - modifier = Modifier, + modifier = Modifier.weight(1f), text = stringResource(id = day), style = TerningTheme.typography.body7, color = if(day == R.string.calendar_text_sunday) SundayRed else Black, - fontSize = 13.sp + fontSize = 13.sp, + textAlign = TextAlign.Center ) } } From a0c85411710d6acaf9a6da2dcb3ff80a613ee0b5 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Sun, 7 Jul 2024 04:22:03 +0900 Subject: [PATCH 06/19] =?UTF-8?q?[FEAT/#9]=20=EC=8A=A4=ED=81=AC=EB=A1=A4?= =?UTF-8?q?=20=EA=B4=80=EB=A0=A8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../calendar/models/CalendarDefault.kt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 feature/src/main/java/com/terning/feature/calendar/models/CalendarDefault.kt diff --git a/feature/src/main/java/com/terning/feature/calendar/models/CalendarDefault.kt b/feature/src/main/java/com/terning/feature/calendar/models/CalendarDefault.kt new file mode 100644 index 000000000..59a554d7d --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/models/CalendarDefault.kt @@ -0,0 +1,34 @@ +package com.terning.feature.calendar.models + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.gestures.FlingBehavior +import androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider +import androidx.compose.foundation.gestures.snapping.SnapPosition +import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember + +internal object CalendarDefaults { + /** + * Returns the fling behavior for the given [LazyListState]. + * From Github [https://github.com/kizitonwose/Calendar] + */ + @OptIn(ExperimentalFoundationApi::class) + @Composable + fun flingBehavior(state: LazyListState): FlingBehavior { + val snappingLayout = remember(state) { + val provider = SnapLayoutInfoProvider(state, SnapPosition.Start) + CalendarSnapLayoutInfoProvider(provider) + } + return rememberSnapFlingBehavior(snappingLayout) + } +} + +@ExperimentalFoundationApi +@Suppress("FunctionName") +private fun CalendarSnapLayoutInfoProvider( + snapLayoutInfoProvider: SnapLayoutInfoProvider, +): SnapLayoutInfoProvider = object : SnapLayoutInfoProvider by snapLayoutInfoProvider { + override fun calculateApproachOffset(velocity: Float, decayOffset: Float): Float = 0f +} \ No newline at end of file From 35070bbbdad97eab1ab7b91b18f4cf8143d5ccb6 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Sun, 7 Jul 2024 04:39:01 +0900 Subject: [PATCH 07/19] =?UTF-8?q?[UI/#9]=20CalendarDay=20=EB=B7=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../terning/feature/calendar/CalendarDay.kt | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 feature/src/main/java/com/terning/feature/calendar/CalendarDay.kt diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarDay.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarDay.kt new file mode 100644 index 000000000..a7cf7039e --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/CalendarDay.kt @@ -0,0 +1,106 @@ +package com.terning.feature.calendar + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Box +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.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.TerningTheme +import com.terning.core.designsystem.theme.White +import com.terning.feature.calendar.models.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) Grey200 else Color.Transparent + val textColor = + if (dayData.isOutDate) { + Grey150 + } else { + if (isSelected) + White + else + Black + } + + Box( + modifier = modifier, + contentAlignment = Alignment.Center + ) { + Box( + modifier = Modifier + .size(22.dp) + .clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = null, + onClick = { + 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() { + TerningTheme { + Row { + CalendarDay( + dayData = DayModel(LocalDate.now(), false), + isSelected = true, + isToday = true, + onDateSelected = {} + ) + CalendarDay( + dayData = DayModel(LocalDate.now(), false), + isSelected = false, + isToday = true, + onDateSelected = {} + ) + CalendarDay( + dayData = DayModel(LocalDate.now(), false), + isSelected = false, + isToday = false, + onDateSelected = {} + ) + } + } +} \ No newline at end of file From ed0a12e76fc989321a372f0f1f9ff528293c5b43 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Sun, 7 Jul 2024 04:39:28 +0900 Subject: [PATCH 08/19] =?UTF-8?q?[UI/#9]=20CalendarMonth=20=EB=B7=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../terning/feature/calendar/CalendarMonth.kt | 92 +++++++++++++++++++ .../feature/calendar/CalendarMonths.kt | 45 +++++++++ 2 files changed, 137 insertions(+) create mode 100644 feature/src/main/java/com/terning/feature/calendar/CalendarMonth.kt create mode 100644 feature/src/main/java/com/terning/feature/calendar/CalendarMonths.kt diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarMonth.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarMonth.kt new file mode 100644 index 000000000..9e6cc397f --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/CalendarMonth.kt @@ -0,0 +1,92 @@ +package com.terning.feature.calendar + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.Text +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.theme.Grey150 +import com.terning.core.designsystem.theme.Grey200 +import com.terning.core.designsystem.theme.Grey300 +import com.terning.core.designsystem.theme.TerningTheme +import com.terning.feature.calendar.models.MonthData +import java.time.LocalDate +import java.time.YearMonth + +@Composable +fun CalendarMonth( + modifier: Modifier = Modifier, + monthData: MonthData, + onDateSelected: (LocalDate) -> Unit, + selectedDate: LocalDate, + taskList: List> = listOf( + listOf("Task 1", "Task 2", "Task 3"), + listOf("Task 4", "Task 5", "Task 6"), + listOf("Task 7", "Task 8", "Task 9") + ) +) { + Column( + modifier = modifier + .fillMaxSize() + .padding(horizontal = 20.dp), + ) { + val month = monthData.calendarMonth.weekDays + for (week in month) { + Row( + modifier = Modifier.weight(1f), + ) { + for (day in week) { + Column( + modifier = Modifier + .weight(1f) + .padding(top = 15.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + CalendarDay( + dayData = day, + isSelected = selectedDate == day.date, + isToday = day.date == LocalDate.now(), + onDateSelected = onDateSelected + ) + } + } + } + if(month.indexOf(week) != month.lastIndex) { + Spacer( + modifier = Modifier + .fillMaxWidth() + .height(1.dp) + .background(color = Grey150) + ) + } + } + } +} + +@Preview(showBackground = true) +@Composable +fun CalendarMonthPreview() { + TerningTheme { + CalendarMonth( + monthData = MonthData(YearMonth.now()), + selectedDate = LocalDate.now(), + onDateSelected = {}, + taskList = listOf( + listOf("Task 1", "Task 2", "Task 3"), + listOf("Task 4", "Task 5", "Task 6"), + listOf("Task 7", "Task 8", "Task 9") + ) + ) + } +} \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarMonths.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarMonths.kt new file mode 100644 index 000000000..0b36d458f --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/CalendarMonths.kt @@ -0,0 +1,45 @@ +package com.terning.feature.calendar + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.terning.core.designsystem.theme.White +import com.terning.feature.calendar.models.CalendarDefaults.flingBehavior +import com.terning.feature.calendar.models.CalendarState.Companion.getDateByPage +import com.terning.feature.calendar.models.MonthData +import java.time.LocalDate +import java.time.YearMonth + +@Composable +fun CalendarMonths( + modifier: Modifier = Modifier, + listState: LazyListState, + onDateSelected: (LocalDate) -> Unit, + pages: Int, + selectedDate: LocalDate, +) { + LazyRow( + modifier = modifier + .background(White), + state = listState, + userScrollEnabled = true, + flingBehavior = flingBehavior( + state = listState + ) + ) { + items(pages) { page -> + val date = getDateByPage(page) + val monthData = MonthData(YearMonth.of(date.year, date.month)) + + CalendarMonth( + modifier = Modifier.fillParentMaxSize(), + selectedDate = selectedDate, + onDateSelected = onDateSelected, + monthData = monthData + ) + } + } +} \ No newline at end of file From 6177a9ed3a030ca89993a2f344a3c70aa9c89425 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Sun, 7 Jul 2024 04:39:43 +0900 Subject: [PATCH 09/19] =?UTF-8?q?[UI/#9]=20CalendarScreen=20=EB=B7=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/calendar/CalendarScreen.kt | 108 ++++++++++++++++++ .../feature/calendar/CalendarViewModel.kt | 27 +++++ 2 files changed, 135 insertions(+) create mode 100644 feature/src/main/java/com/terning/feature/calendar/CalendarScreen.kt create mode 100644 feature/src/main/java/com/terning/feature/calendar/CalendarViewModel.kt diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarScreen.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarScreen.kt new file mode 100644 index 000000000..dfa2794a1 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/CalendarScreen.kt @@ -0,0 +1,108 @@ +package com.terning.feature.calendar + +import androidx.activity.compose.BackHandler +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.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshotFlow +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.terning.core.designsystem.theme.Grey200 +import com.terning.feature.calendar.models.CalendarState +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.launch + +@Composable +fun CalendarScreen( + modifier: Modifier = Modifier, + viewModel: CalendarViewModel = viewModel() +) { + val selectedDate by viewModel.selectedDate.collectAsState() + val state by remember{ mutableStateOf(CalendarState()) } + + val listState = rememberLazyListState( + initialFirstVisibleItemIndex = state.getInitialPage() + ) + + var currentDate by remember { mutableStateOf(selectedDate) } + var currentPage by remember { mutableIntStateOf(listState.firstVisibleItemIndex)} + + var isListExpanded by remember { mutableStateOf(false) } + var isWeekEnabled by remember { mutableStateOf(false) } + + LaunchedEffect(key1 = listState) { + snapshotFlow { listState.firstVisibleItemIndex } + .distinctUntilChanged() + .collect{ + val swipeDirection = (listState.firstVisibleItemIndex - currentPage).coerceIn(-1, 1).toLong() + currentDate = currentDate.plusMonths(swipeDirection) + currentPage = listState.firstVisibleItemIndex + } + } + + LaunchedEffect(key1 = selectedDate) { + isWeekEnabled = true + } + + BackHandler { + isWeekEnabled = false + } + + Scaffold( + modifier = modifier, + topBar = { + val coroutineScope = rememberCoroutineScope() + CalendarTopBar( + date = currentDate, + isListExpanded = isListExpanded, + onListButtonClicked = { isListExpanded = !isListExpanded }, + onMonthNavigationButtonClicked = { direction -> + coroutineScope.launch { + listState.animateScrollToItem( + index = listState.firstVisibleItemIndex + direction, + ) + } + } + ) + } + ) { paddingValues -> + Column( + modifier = Modifier + .fillMaxWidth() + .padding(paddingValues) + ) { + WeekDaysHeader() + Spacer(modifier = Modifier + .fillMaxWidth() + .height(1.dp) + .background(color = Grey200) + ) + CalendarMonths( + modifier = Modifier.fillMaxSize(), + selectedDate = selectedDate, + onDateSelected = { + viewModel.updateSelectedDate(it) + }, + listState = listState, + pages = state.getPageCount() + ) + } + + } +} diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarViewModel.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarViewModel.kt new file mode 100644 index 000000000..aaa463dd2 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/CalendarViewModel.kt @@ -0,0 +1,27 @@ +package com.terning.feature.calendar + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import java.time.LocalDate + + +class CalendarViewModel: ViewModel() { + private val _selectedDate = MutableStateFlow(LocalDate.now()) + val selectedDate get() = _selectedDate.asStateFlow() + + fun updateSelectedDate(date: LocalDate) = viewModelScope.launch{ + if(_selectedDate.value != date) { + _selectedDate.value = date + } + } + + + fun initDateToToday() = viewModelScope.launch { + _selectedDate.value = LocalDate.now() + } + +} \ No newline at end of file From cac95b8f32dfb39e9778a5e6cfc67b3d6e788193 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Sun, 7 Jul 2024 04:40:09 +0900 Subject: [PATCH 10/19] =?UTF-8?q?[FEAT/#9]=20LocalDateExt=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/terning/core/extension/LocalDateExt.kt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 core/src/main/java/com/terning/core/extension/LocalDateExt.kt diff --git a/core/src/main/java/com/terning/core/extension/LocalDateExt.kt b/core/src/main/java/com/terning/core/extension/LocalDateExt.kt new file mode 100644 index 000000000..edcf61c96 --- /dev/null +++ b/core/src/main/java/com/terning/core/extension/LocalDateExt.kt @@ -0,0 +1,6 @@ +package com.terning.core.extension + +import java.time.LocalDate + +fun LocalDate.getStringAsTitle(): String = + "${year}년 ${monthValue.toString().padStart(2, '0')}월" \ No newline at end of file From 51cb189c08466ea35cbe51ceb87c3e84b34c7fcd Mon Sep 17 00:00:00 2001 From: boiledegg Date: Sun, 7 Jul 2024 14:37:31 +0900 Subject: [PATCH 11/19] =?UTF-8?q?[UI/#9]=20=EC=8A=A4=ED=81=AC=EB=9E=A9=20?= =?UTF-8?q?=EB=B7=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../terning/feature/calendar/CalendarScrap.kt | 55 +++++++++++++++++++ .../terning/feature/calendar/models/Scrap.kt | 10 ++++ 2 files changed, 65 insertions(+) create mode 100644 feature/src/main/java/com/terning/feature/calendar/CalendarScrap.kt create mode 100644 feature/src/main/java/com/terning/feature/calendar/models/Scrap.kt diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarScrap.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarScrap.kt new file mode 100644 index 000000000..a28d47c19 --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/CalendarScrap.kt @@ -0,0 +1,55 @@ +package com.terning.feature.calendar + +import androidx.compose.foundation.background +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.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import com.terning.core.designsystem.theme.TerningTheme +import com.terning.core.designsystem.theme.White +import com.terning.feature.calendar.models.Scrap + +@Composable +fun CalendarScrap( + modifier: Modifier = Modifier, + scrapList: List +) { + LazyColumn( + modifier = modifier.fillMaxWidth().padding(top = 3.dp) + ) { + items(scrapList.subList(0, MAX_SCRAP_COUNT.coerceAtMost(scrapList.size))) { scrap -> + Text( + text = scrap.text, + style = TerningTheme.typography.body5, + textAlign = TextAlign.Center, + color = White, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier + .fillMaxWidth() + .background(color = scrap.backgroundColor) + ) + } + + item{ + if(scrapList.size > MAX_SCRAP_COUNT) { + Text( + text = "+${(scrapList.size - MAX_SCRAP_COUNT)}", + style = TerningTheme.typography.detail4, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth() + ) + } + } + + } +} + +private const val MAX_SCRAP_COUNT = 2 + diff --git a/feature/src/main/java/com/terning/feature/calendar/models/Scrap.kt b/feature/src/main/java/com/terning/feature/calendar/models/Scrap.kt new file mode 100644 index 000000000..73698591a --- /dev/null +++ b/feature/src/main/java/com/terning/feature/calendar/models/Scrap.kt @@ -0,0 +1,10 @@ +package com.terning.feature.calendar.models + +import androidx.compose.runtime.Immutable +import androidx.compose.ui.graphics.Color + +@Immutable +data class Scrap( + val text: String, + val backgroundColor: Color +) From d9f82fdded7bb17a949fa6e1855ba96c67b12345 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Sun, 7 Jul 2024 14:39:10 +0900 Subject: [PATCH 12/19] =?UTF-8?q?[UI/#9]=20=EC=8A=A4=ED=81=AC=EB=9E=A9=20?= =?UTF-8?q?=ED=91=9C=EC=8B=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../terning/feature/calendar/CalendarMonth.kt | 24 ++---- .../feature/calendar/CalendarMonths.kt | 5 +- .../feature/calendar/CalendarScreen.kt | 3 +- .../feature/calendar/CalendarViewModel.kt | 83 +++++++++++++++++-- 4 files changed, 91 insertions(+), 24 deletions(-) diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarMonth.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarMonth.kt index 9e6cc397f..e9d41dcf0 100644 --- a/feature/src/main/java/com/terning/feature/calendar/CalendarMonth.kt +++ b/feature/src/main/java/com/terning/feature/calendar/CalendarMonth.kt @@ -8,19 +8,15 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.Text 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.theme.Grey150 -import com.terning.core.designsystem.theme.Grey200 -import com.terning.core.designsystem.theme.Grey300 import com.terning.core.designsystem.theme.TerningTheme import com.terning.feature.calendar.models.MonthData +import com.terning.feature.calendar.models.Scrap import java.time.LocalDate import java.time.YearMonth @@ -30,11 +26,7 @@ fun CalendarMonth( monthData: MonthData, onDateSelected: (LocalDate) -> Unit, selectedDate: LocalDate, - taskList: List> = listOf( - listOf("Task 1", "Task 2", "Task 3"), - listOf("Task 4", "Task 5", "Task 6"), - listOf("Task 7", "Task 8", "Task 9") - ) + scrapLists: List> = listOf() ) { Column( modifier = modifier @@ -59,6 +51,12 @@ fun CalendarMonth( isToday = day.date == LocalDate.now(), onDateSelected = onDateSelected ) + if(!day.isOutDate) { + val index = day.date.dayOfWeek.value - 1 + CalendarScrap( + scrapList = scrapLists[index] + ) + } } } } @@ -82,11 +80,7 @@ fun CalendarMonthPreview() { monthData = MonthData(YearMonth.now()), selectedDate = LocalDate.now(), onDateSelected = {}, - taskList = listOf( - listOf("Task 1", "Task 2", "Task 3"), - listOf("Task 4", "Task 5", "Task 6"), - listOf("Task 7", "Task 8", "Task 9") - ) + scrapLists = listOf() ) } } \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarMonths.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarMonths.kt index 0b36d458f..4f179af8d 100644 --- a/feature/src/main/java/com/terning/feature/calendar/CalendarMonths.kt +++ b/feature/src/main/java/com/terning/feature/calendar/CalendarMonths.kt @@ -10,6 +10,7 @@ import com.terning.core.designsystem.theme.White import com.terning.feature.calendar.models.CalendarDefaults.flingBehavior import com.terning.feature.calendar.models.CalendarState.Companion.getDateByPage import com.terning.feature.calendar.models.MonthData +import com.terning.feature.calendar.models.Scrap import java.time.LocalDate import java.time.YearMonth @@ -20,6 +21,7 @@ fun CalendarMonths( onDateSelected: (LocalDate) -> Unit, pages: Int, selectedDate: LocalDate, + scrapLists: List> ) { LazyRow( modifier = modifier @@ -38,7 +40,8 @@ fun CalendarMonths( modifier = Modifier.fillParentMaxSize(), selectedDate = selectedDate, onDateSelected = onDateSelected, - monthData = monthData + monthData = monthData, + scrapLists = scrapLists ) } } diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarScreen.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarScreen.kt index dfa2794a1..da9bef3c3 100644 --- a/feature/src/main/java/com/terning/feature/calendar/CalendarScreen.kt +++ b/feature/src/main/java/com/terning/feature/calendar/CalendarScreen.kt @@ -100,7 +100,8 @@ fun CalendarScreen( viewModel.updateSelectedDate(it) }, listState = listState, - pages = state.getPageCount() + pages = state.getPageCount(), + scrapLists = viewModel.mockScrapList ) } diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarViewModel.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarViewModel.kt index aaa463dd2..79acf8f6e 100644 --- a/feature/src/main/java/com/terning/feature/calendar/CalendarViewModel.kt +++ b/feature/src/main/java/com/terning/feature/calendar/CalendarViewModel.kt @@ -2,6 +2,14 @@ package com.terning.feature.calendar import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.terning.core.designsystem.theme.CalBlue1 +import com.terning.core.designsystem.theme.CalGreen1 +import com.terning.core.designsystem.theme.CalGreen2 +import com.terning.core.designsystem.theme.CalPink +import com.terning.core.designsystem.theme.CalPurple +import com.terning.core.designsystem.theme.CalRed +import com.terning.core.designsystem.theme.CalYellow +import com.terning.feature.calendar.models.Scrap import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update @@ -9,19 +17,80 @@ import kotlinx.coroutines.launch import java.time.LocalDate -class CalendarViewModel: ViewModel() { +class CalendarViewModel : ViewModel() { private val _selectedDate = MutableStateFlow(LocalDate.now()) val selectedDate get() = _selectedDate.asStateFlow() - fun updateSelectedDate(date: LocalDate) = viewModelScope.launch{ - if(_selectedDate.value != date) { - _selectedDate.value = date - } + fun updateSelectedDate(date: LocalDate) = viewModelScope.launch { + if (_selectedDate.value != date) { + _selectedDate.value = date } + } fun initDateToToday() = viewModelScope.launch { - _selectedDate.value = LocalDate.now() - } + _selectedDate.value = LocalDate.now() + } + + + //To be erased in future + val mockScrapList: List> + get() { + val list: MutableList> = mutableListOf() + for (i in 0..30) { + when (i % 6) { + 0 -> { + list.add( + i, + listOf() + ) + } + 1 -> { + list.add( + i, + listOf( + Scrap("Task1_1", CalBlue1), + ) + ) + } + + 2 -> { + list.add( + i, + listOf( + Scrap("Task2_1", CalPink), + Scrap("Task2_2", CalGreen1) + ) + ) + } + 3 -> { + list.add( + i, + listOf() + ) + } + 4 -> { + list.add( + i, + listOf() + ) + } + 5 -> { + list.add( + i, + listOf( + Scrap("Task3_1", CalPink), + Scrap("Task3_2", CalPurple), + Scrap("Task3_3", CalRed), + Scrap("Task3_4", CalBlue1), + Scrap("Task3_5", CalGreen2), + Scrap("Task3_6", CalYellow) + ) + ) + } + } + } + return list.toList() + } } \ No newline at end of file From b3df5e2adac2240f303c158ee1bab026bc14db1e Mon Sep 17 00:00:00 2001 From: boiledegg Date: Sun, 7 Jul 2024 14:42:02 +0900 Subject: [PATCH 13/19] =?UTF-8?q?[ADD/#9]=20MonthData=20=EC=A3=BC=EC=84=9D?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../terning/feature/calendar/models/MonthData.kt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/feature/src/main/java/com/terning/feature/calendar/models/MonthData.kt b/feature/src/main/java/com/terning/feature/calendar/models/MonthData.kt index 2c82457bc..425f7beb6 100644 --- a/feature/src/main/java/com/terning/feature/calendar/models/MonthData.kt +++ b/feature/src/main/java/com/terning/feature/calendar/models/MonthData.kt @@ -3,6 +3,17 @@ package com.terning.feature.calendar.models import androidx.compose.runtime.Immutable import java.time.YearMonth +/** + * [MonthData] 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 MonthData( val month: YearMonth @@ -13,7 +24,7 @@ data class MonthData( val inDays = firstDayOfWeek % 7 val monthDays = month.lengthOfMonth() - val outDays = 7 - ((inDays + monthDays) % 7) + val outDays = (7 - ((inDays + monthDays) % 7)) % 7 val totalDays = monthDays + inDays + outDays private val rows = (0 until totalDays).chunked(7) From a7f65c89b37792e220844474bf368aee053e96d9 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Sun, 7 Jul 2024 14:43:07 +0900 Subject: [PATCH 14/19] =?UTF-8?q?[CHORE/#9]=20Import=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/terning/feature/calendar/CalendarDay.kt | 3 --- .../main/java/com/terning/feature/calendar/WeekDaysHeader.kt | 2 -- 2 files changed, 5 deletions(-) diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarDay.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarDay.kt index a7cf7039e..e059e36e9 100644 --- a/feature/src/main/java/com/terning/feature/calendar/CalendarDay.kt +++ b/feature/src/main/java/com/terning/feature/calendar/CalendarDay.kt @@ -5,9 +5,6 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Box 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.foundation.layout.size import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.Text diff --git a/feature/src/main/java/com/terning/feature/calendar/WeekDaysHeader.kt b/feature/src/main/java/com/terning/feature/calendar/WeekDaysHeader.kt index 21bcbeed6..bb154e886 100644 --- a/feature/src/main/java/com/terning/feature/calendar/WeekDaysHeader.kt +++ b/feature/src/main/java/com/terning/feature/calendar/WeekDaysHeader.kt @@ -1,11 +1,9 @@ package com.terning.feature.calendar import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier From 914f9cdce9b157d60f2d277b375de8edafc580ea Mon Sep 17 00:00:00 2001 From: boiledegg Date: Sun, 7 Jul 2024 15:11:52 +0900 Subject: [PATCH 15/19] =?UTF-8?q?[FEAT/#9]=20hilt=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/terning/feature/calendar/CalendarScreen.kt | 3 ++- .../terning/feature/calendar/CalendarViewModel.kt | 13 +++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarScreen.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarScreen.kt index da9bef3c3..dafb5df70 100644 --- a/feature/src/main/java/com/terning/feature/calendar/CalendarScreen.kt +++ b/feature/src/main/java/com/terning/feature/calendar/CalendarScreen.kt @@ -22,6 +22,7 @@ import androidx.compose.runtime.setValue 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.viewmodel.compose.viewModel import com.terning.core.designsystem.theme.Grey200 import com.terning.feature.calendar.models.CalendarState @@ -31,7 +32,7 @@ import kotlinx.coroutines.launch @Composable fun CalendarScreen( modifier: Modifier = Modifier, - viewModel: CalendarViewModel = viewModel() + viewModel: CalendarViewModel = hiltViewModel() ) { val selectedDate by viewModel.selectedDate.collectAsState() val state by remember{ mutableStateOf(CalendarState()) } diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarViewModel.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarViewModel.kt index 79acf8f6e..d57863782 100644 --- a/feature/src/main/java/com/terning/feature/calendar/CalendarViewModel.kt +++ b/feature/src/main/java/com/terning/feature/calendar/CalendarViewModel.kt @@ -10,14 +10,17 @@ import com.terning.core.designsystem.theme.CalPurple import com.terning.core.designsystem.theme.CalRed import com.terning.core.designsystem.theme.CalYellow import com.terning.feature.calendar.models.Scrap +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 - -class CalendarViewModel : ViewModel() { +@HiltViewModel +class CalendarViewModel @Inject constructor( +) : ViewModel() { private val _selectedDate = MutableStateFlow(LocalDate.now()) val selectedDate get() = _selectedDate.asStateFlow() @@ -27,12 +30,6 @@ class CalendarViewModel : ViewModel() { } } - - fun initDateToToday() = viewModelScope.launch { - _selectedDate.value = LocalDate.now() - } - - //To be erased in future val mockScrapList: List> get() { From 7dfa4dfd30cb76203470728578353b29118b60e6 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Sun, 7 Jul 2024 15:28:40 +0900 Subject: [PATCH 16/19] =?UTF-8?q?[FEAT/#9]=20=EB=B0=94=ED=85=80=EB=B0=94?= =?UTF-8?q?=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../calendar/{CalendarScreen.kt => CalendarRoute.kt} | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) rename feature/src/main/java/com/terning/feature/calendar/{CalendarScreen.kt => CalendarRoute.kt} (96%) diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarScreen.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarRoute.kt similarity index 96% rename from feature/src/main/java/com/terning/feature/calendar/CalendarScreen.kt rename to feature/src/main/java/com/terning/feature/calendar/CalendarRoute.kt index dafb5df70..92190caa1 100644 --- a/feature/src/main/java/com/terning/feature/calendar/CalendarScreen.kt +++ b/feature/src/main/java/com/terning/feature/calendar/CalendarRoute.kt @@ -23,12 +23,16 @@ 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.viewmodel.compose.viewModel import com.terning.core.designsystem.theme.Grey200 import com.terning.feature.calendar.models.CalendarState import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.launch +@Composable +fun CalendarRoute() { + CalendarScreen() +} + @Composable fun CalendarScreen( modifier: Modifier = Modifier, @@ -86,7 +90,7 @@ fun CalendarScreen( Column( modifier = Modifier .fillMaxWidth() - .padding(paddingValues) + .padding(top = paddingValues.calculateTopPadding()) ) { WeekDaysHeader() Spacer(modifier = Modifier From 110230c70570952092aa95514243382992e051e9 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Sun, 7 Jul 2024 15:29:07 +0900 Subject: [PATCH 17/19] =?UTF-8?q?[DEL/#9]=20=EA=B8=B0=EC=A1=B4=20CalendarR?= =?UTF-8?q?oute=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../terning/feature/calendar/CalendarRouth.kt | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 feature/src/main/java/com/terning/feature/calendar/CalendarRouth.kt diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarRouth.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarRouth.kt deleted file mode 100644 index 76ef0be7f..000000000 --- a/feature/src/main/java/com/terning/feature/calendar/CalendarRouth.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.terning.feature.calendar - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier - -@Composable -fun CalendarRoute() { - CalendarScreen() -} - -@Composable -fun CalendarScreen() { - Column(modifier = Modifier.fillMaxSize()) { - Text(text = "캘린더 스크린") - } -} \ No newline at end of file From c9680c0cc7eb545051d8ca908e6f8c20a1fa1f48 Mon Sep 17 00:00:00 2001 From: boiledegg Date: Mon, 8 Jul 2024 00:00:14 +0900 Subject: [PATCH 18/19] =?UTF-8?q?[REFACTOR/#9]=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EA=B8=B0=EB=B0=98=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 --- .../java/com/terning/feature/calendar/CalendarRoute.kt | 2 ++ .../feature/calendar/{ => component}/CalendarTopBar.kt | 2 +- .../feature/calendar/{ => component}/WeekDaysHeader.kt | 4 +--- .../com/terning/feature/calendar/models/CalendarState.kt | 9 +++------ .../main/java/com/terning/feature/main/MainNavigator.kt | 3 ++- 5 files changed, 9 insertions(+), 11 deletions(-) rename feature/src/main/java/com/terning/feature/calendar/{ => component}/CalendarTopBar.kt (98%) rename feature/src/main/java/com/terning/feature/calendar/{ => component}/WeekDaysHeader.kt (94%) diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarRoute.kt b/feature/src/main/java/com/terning/feature/calendar/CalendarRoute.kt index 92190caa1..c706c5715 100644 --- a/feature/src/main/java/com/terning/feature/calendar/CalendarRoute.kt +++ b/feature/src/main/java/com/terning/feature/calendar/CalendarRoute.kt @@ -24,6 +24,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.terning.core.designsystem.theme.Grey200 +import com.terning.feature.calendar.component.CalendarTopBar +import com.terning.feature.calendar.component.WeekDaysHeader import com.terning.feature.calendar.models.CalendarState import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.launch diff --git a/feature/src/main/java/com/terning/feature/calendar/CalendarTopBar.kt b/feature/src/main/java/com/terning/feature/calendar/component/CalendarTopBar.kt similarity index 98% rename from feature/src/main/java/com/terning/feature/calendar/CalendarTopBar.kt rename to feature/src/main/java/com/terning/feature/calendar/component/CalendarTopBar.kt index a45309d84..c9730b832 100644 --- a/feature/src/main/java/com/terning/feature/calendar/CalendarTopBar.kt +++ b/feature/src/main/java/com/terning/feature/calendar/component/CalendarTopBar.kt @@ -1,4 +1,4 @@ -package com.terning.feature.calendar +package com.terning.feature.calendar.component import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box diff --git a/feature/src/main/java/com/terning/feature/calendar/WeekDaysHeader.kt b/feature/src/main/java/com/terning/feature/calendar/component/WeekDaysHeader.kt similarity index 94% rename from feature/src/main/java/com/terning/feature/calendar/WeekDaysHeader.kt rename to feature/src/main/java/com/terning/feature/calendar/component/WeekDaysHeader.kt index bb154e886..d4983af70 100644 --- a/feature/src/main/java/com/terning/feature/calendar/WeekDaysHeader.kt +++ b/feature/src/main/java/com/terning/feature/calendar/component/WeekDaysHeader.kt @@ -1,4 +1,4 @@ -package com.terning.feature.calendar +package com.terning.feature.calendar.component import androidx.compose.foundation.background import androidx.compose.foundation.layout.Row @@ -12,7 +12,6 @@ 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 -import androidx.compose.ui.unit.sp import com.terning.core.designsystem.theme.Black import com.terning.core.designsystem.theme.SundayRed import com.terning.core.designsystem.theme.TerningTheme @@ -44,7 +43,6 @@ fun WeekDaysHeader( text = stringResource(id = day), style = TerningTheme.typography.body7, color = if(day == R.string.calendar_text_sunday) SundayRed else Black, - fontSize = 13.sp, textAlign = TextAlign.Center ) } diff --git a/feature/src/main/java/com/terning/feature/calendar/models/CalendarState.kt b/feature/src/main/java/com/terning/feature/calendar/models/CalendarState.kt index bb8764f9e..98e3cfd94 100644 --- a/feature/src/main/java/com/terning/feature/calendar/models/CalendarState.kt +++ b/feature/src/main/java/com/terning/feature/calendar/models/CalendarState.kt @@ -40,13 +40,10 @@ class CalendarState internal constructor( } } - fun getPageCount(): Int { - return (END_YEAR - START_YEAR) * 12 - } + fun getPageCount(): Int = (END_YEAR - START_YEAR) * 12 - fun getInitialPage(): Int { - return (firstVisibleMonth.year - START_YEAR) * 12 + firstVisibleMonth.monthValue - 1 - } + fun getInitialPage(): Int = + (firstVisibleMonth.year - START_YEAR) * 12 + firstVisibleMonth.monthValue - 1 companion object { const val START_YEAR = 2020 diff --git a/feature/src/main/java/com/terning/feature/main/MainNavigator.kt b/feature/src/main/java/com/terning/feature/main/MainNavigator.kt index 472557036..2956286a2 100644 --- a/feature/src/main/java/com/terning/feature/main/MainNavigator.kt +++ b/feature/src/main/java/com/terning/feature/main/MainNavigator.kt @@ -10,6 +10,7 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navOptions import com.terning.feature.calendar.navigation.navigateCalendar +import com.terning.feature.home.navigation.Home import com.terning.feature.home.navigation.navigateHome import com.terning.feature.mypage.navigation.navigateMyPage import com.terning.feature.onboarding.signin.navigation.SignIn @@ -22,7 +23,7 @@ class MainNavigator( @Composable get() = navController .currentBackStackEntryAsState().value?.destination - val startDestination = SignIn + val startDestination = Home val currentTab: MainTab? @Composable get() = MainTab.find { tab -> From a86695a8a8a2bb32eab49f80e21c9429e5dda7ae Mon Sep 17 00:00:00 2001 From: boiledegg Date: Mon, 8 Jul 2024 00:14:29 +0900 Subject: [PATCH 19/19] =?UTF-8?q?[FIX/#9]=20MainNavigator=20Home->SignIn?= =?UTF-8?q?=20=EC=9E=AC=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/terning/feature/main/MainNavigator.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/feature/src/main/java/com/terning/feature/main/MainNavigator.kt b/feature/src/main/java/com/terning/feature/main/MainNavigator.kt index 2956286a2..472557036 100644 --- a/feature/src/main/java/com/terning/feature/main/MainNavigator.kt +++ b/feature/src/main/java/com/terning/feature/main/MainNavigator.kt @@ -10,7 +10,6 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navOptions import com.terning.feature.calendar.navigation.navigateCalendar -import com.terning.feature.home.navigation.Home import com.terning.feature.home.navigation.navigateHome import com.terning.feature.mypage.navigation.navigateMyPage import com.terning.feature.onboarding.signin.navigation.SignIn @@ -23,7 +22,7 @@ class MainNavigator( @Composable get() = navController .currentBackStackEntryAsState().value?.destination - val startDestination = Home + val startDestination = SignIn val currentTab: MainTab? @Composable get() = MainTab.find { tab ->