From 67b1586a29911ee17b3db3d1e1a5d53a268dbd9c Mon Sep 17 00:00:00 2001 From: Karan Sharma <55722391+ksharma-xyz@users.noreply.github.com> Date: Sat, 30 Nov 2024 16:14:43 +1100 Subject: [PATCH] Refactor add state objects --- .../krail/core/datetime/DateTimePickerInfo.kt | 40 ++++++++------ feature/trip-planner/state/build.gradle.kts | 3 ++ .../datetimeselector/DateTimeSelectionItem.kt | 48 +++++++++++++++++ .../datetimeselector/JourneyTimeOptions.kt | 6 +++ .../ui/state/timetable/TimeTableUiEvent.kt | 5 ++ .../DateTimeSelectorScreen.kt | 53 ++----------------- .../JourneyTimeOptionsGroup.kt | 6 +-- .../ui/timetable/TimeTableDestination.kt | 5 +- .../planner/ui/timetable/TimeTableScreen.kt | 2 +- .../ui/timetable/TimeTableViewModel.kt | 14 +++-- 10 files changed, 103 insertions(+), 79 deletions(-) create mode 100644 feature/trip-planner/state/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/state/datetimeselector/DateTimeSelectionItem.kt create mode 100644 feature/trip-planner/state/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/state/datetimeselector/JourneyTimeOptions.kt diff --git a/core/date-time/src/commonMain/kotlin/xyz/ksharma/krail/core/datetime/DateTimePickerInfo.kt b/core/date-time/src/commonMain/kotlin/xyz/ksharma/krail/core/datetime/DateTimePickerInfo.kt index d49caf80..ffcbbd27 100644 --- a/core/date-time/src/commonMain/kotlin/xyz/ksharma/krail/core/datetime/DateTimePickerInfo.kt +++ b/core/date-time/src/commonMain/kotlin/xyz/ksharma/krail/core/datetime/DateTimePickerInfo.kt @@ -24,7 +24,7 @@ fun rememberCurrentDateTime(): DateTimePickerInfo { // Formatting the date val formattedDate = remember(currentDateTime.date) { - formatDate(currentDateTime.date) + toReadableDate(currentDateTime.date) } return DateTimePickerInfo( @@ -34,21 +34,6 @@ fun rememberCurrentDateTime(): DateTimePickerInfo { ) } -fun formatDate(date: LocalDate): String { - val today = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).date - val tomorrow = today.plus(1, DateTimeUnit.DAY) - - return when (date) { - today -> "Today" - tomorrow -> "Tomorrow" - else -> { - val dayOfWeek = date.dayOfWeek.name.substring(0, 3) // Short day name (e.g., Mon, Tue) - val month = date.month.name.substring(0, 3) // Short month name (e.g., Jan, Feb) - "$dayOfWeek ${date.dayOfMonth} ${month.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }}" - } - } -} - fun incrementDateByOneDay(date: LocalDate): LocalDate { return date.plus(1, DateTimeUnit.DAY) } @@ -57,9 +42,30 @@ fun decrementDateByOneDay(date: LocalDate): LocalDate { return date.plus(-1, DateTimeUnit.DAY) } -fun formatTime(hour: Int, minute: Int): String { +/** + * Formats the time in 12-hour format (e.g., 1:30 PM) + */ +fun to12HourTimeString(hour: Int, minute: Int): String { val displayHour = if (hour == 0 || hour == 12) 12 else hour % 12 val amPm = if (hour < 12) "AM" else "PM" val formattedMinute = if (minute < 10) "0$minute" else minute.toString() return "$displayHour:$formattedMinute $amPm" } + +/** + * Formats the date in a human-readable format (e.g., Today, Tomorrow, Mon 1 Jan) + */ +fun toReadableDate(date: LocalDate): String { + val today = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault()).date + val tomorrow = today.plus(1, DateTimeUnit.DAY) + + return when (date) { + today -> "Today" + tomorrow -> "Tomorrow" + else -> { + val dayOfWeek = date.dayOfWeek.name.substring(0, 3) // Short day name (e.g., Mon, Tue) + val month = date.month.name.substring(0, 3) // Short month name (e.g., Jan, Feb) + "$dayOfWeek, ${date.dayOfMonth} ${month.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }}" + } + } +} diff --git a/feature/trip-planner/state/build.gradle.kts b/feature/trip-planner/state/build.gradle.kts index 6ea023c0..4780fe34 100644 --- a/feature/trip-planner/state/build.gradle.kts +++ b/feature/trip-planner/state/build.gradle.kts @@ -27,10 +27,13 @@ kotlin { sourceSets { commonMain { dependencies { + implementation(projects.core.dateTime) + implementation(libs.kotlinx.collections.immutable) implementation(libs.kotlinx.serialization.json) implementation(compose.runtime) + implementation(libs.kotlinx.datetime) } } } diff --git a/feature/trip-planner/state/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/state/datetimeselector/DateTimeSelectionItem.kt b/feature/trip-planner/state/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/state/datetimeselector/DateTimeSelectionItem.kt new file mode 100644 index 00000000..e5fb8abb --- /dev/null +++ b/feature/trip-planner/state/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/state/datetimeselector/DateTimeSelectionItem.kt @@ -0,0 +1,48 @@ +package xyz.ksharma.krail.trip.planner.ui.state.datetimeselector + +import kotlinx.datetime.LocalDate +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json +import xyz.ksharma.krail.core.datetime.toReadableDate +import xyz.ksharma.krail.core.datetime.to12HourTimeString + +@Serializable +data class DateTimeSelectionItem( + val option: JourneyTimeOptions, + val hour: Int, + val minute: Int, + val date: LocalDate, +) { + fun toDateTimeText(): String = when (option) { + JourneyTimeOptions.LEAVE -> { + "Leave: ${toReadableDate(date)} ${to12HourTimeString(hour, minute)}" + } + + JourneyTimeOptions.ARRIVE -> { + "Arrive: ${toReadableDate(date)} ${to12HourTimeString(hour, minute)}" + } + } + + fun toJsonString() = Json.encodeToString(serializer(), this) + + fun toHHMM(): String { + val hh = hour.toString().padStart(2, '0') + val mm = minute.toString().padStart(2, '0') + return "$hh$mm" + } + + fun toYYYYMMDD(): String { + val yyyy = date.year.toString() + val mm = date.monthNumber.toString().padStart(2, '0') + val dd = date.dayOfMonth.toString().padStart(2, '0') + return "$yyyy$mm$dd" + } + + @Suppress("ConstPropertyName") + companion object { + private const val serialVersionUID: Long = 1L + + fun fromJsonString(json: String) = + kotlin.runCatching { Json.decodeFromString(serializer(), json) }.getOrNull() + } +} diff --git a/feature/trip-planner/state/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/state/datetimeselector/JourneyTimeOptions.kt b/feature/trip-planner/state/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/state/datetimeselector/JourneyTimeOptions.kt new file mode 100644 index 00000000..3a571cd4 --- /dev/null +++ b/feature/trip-planner/state/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/state/datetimeselector/JourneyTimeOptions.kt @@ -0,0 +1,6 @@ +package xyz.ksharma.krail.trip.planner.ui.state.datetimeselector + +enum class JourneyTimeOptions(val text: String) { + LEAVE("Leave"), + ARRIVE("Arrive") +} diff --git a/feature/trip-planner/state/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/state/timetable/TimeTableUiEvent.kt b/feature/trip-planner/state/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/state/timetable/TimeTableUiEvent.kt index 0679f876..e2b8b1ea 100644 --- a/feature/trip-planner/state/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/state/timetable/TimeTableUiEvent.kt +++ b/feature/trip-planner/state/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/state/timetable/TimeTableUiEvent.kt @@ -1,9 +1,14 @@ package xyz.ksharma.krail.trip.planner.ui.state.timetable +import xyz.ksharma.krail.trip.planner.ui.state.datetimeselector.DateTimeSelectionItem + sealed interface TimeTableUiEvent { data object SaveTripButtonClicked : TimeTableUiEvent data class LoadTimeTable(val trip: Trip) : TimeTableUiEvent data class JourneyCardClicked(val journeyId: String) : TimeTableUiEvent + data class DateTimeSelectionChanged(val dateTimeSelectionItem: DateTimeSelectionItem?) : + TimeTableUiEvent + data object ReverseTripButtonClicked : TimeTableUiEvent data object RetryButtonClicked : TimeTableUiEvent } diff --git a/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/datetimeselector/DateTimeSelectorScreen.kt b/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/datetimeselector/DateTimeSelectorScreen.kt index d8130b8c..6ae168c0 100644 --- a/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/datetimeselector/DateTimeSelectorScreen.kt +++ b/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/datetimeselector/DateTimeSelectorScreen.kt @@ -33,16 +33,12 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import kotlinx.datetime.Clock import kotlinx.datetime.DateTimeUnit -import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDateTime import kotlinx.datetime.TimeZone import kotlinx.datetime.plus import kotlinx.datetime.toLocalDateTime -import kotlinx.serialization.Serializable -import kotlinx.serialization.json.Json import xyz.ksharma.krail.core.datetime.decrementDateByOneDay -import xyz.ksharma.krail.core.datetime.formatDate -import xyz.ksharma.krail.core.datetime.formatTime +import xyz.ksharma.krail.core.datetime.toReadableDate import xyz.ksharma.krail.core.datetime.incrementDateByOneDay import xyz.ksharma.krail.core.datetime.rememberCurrentDateTime import xyz.ksharma.krail.taj.LocalThemeColor @@ -53,8 +49,8 @@ import xyz.ksharma.krail.taj.theme.KrailTheme import xyz.ksharma.krail.trip.planner.ui.components.hexToComposeColor import xyz.ksharma.krail.trip.planner.ui.components.themeBackgroundColor import xyz.ksharma.krail.trip.planner.ui.components.themeContentColor -import xyz.ksharma.krail.trip.planner.ui.datetimeselector.JourneyTimeOptions.ARRIVE -import xyz.ksharma.krail.trip.planner.ui.datetimeselector.JourneyTimeOptions.LEAVE +import xyz.ksharma.krail.trip.planner.ui.state.datetimeselector.DateTimeSelectionItem +import xyz.ksharma.krail.trip.planner.ui.state.datetimeselector.JourneyTimeOptions import xyz.ksharma.krail.trip.planner.ui.timetable.ActionButton @OptIn(ExperimentalMaterial3Api::class) @@ -144,7 +140,7 @@ fun DateTimeSelectorScreen( DateSelection( themeColor = themeColor, - date = formatDate(selectedDate), + date = toReadableDate(selectedDate), onNextClicked = { if (selectedDate < maxDate) { selectedDate = incrementDateByOneDay(selectedDate) @@ -212,44 +208,3 @@ fun DateTimeSelectorScreen( } } } - -@Serializable -data class DateTimeSelectionItem( - val option: JourneyTimeOptions, - val hour: Int, - val minute: Int, - val date: LocalDate, -) { - fun toDateTimeText(): String = when (option) { - LEAVE -> { - "Leave: ${formatDate(date)} ${formatTime(hour, minute)}" - } - - ARRIVE -> { - "Arrive: ${formatDate(date)} ${formatTime(hour, minute)}" - } - } - - fun toJsonString() = Json.encodeToString(serializer(), this) - - fun toHHMM(): String { - val hh = hour.toString().padStart(2, '0') - val mm = minute.toString().padStart(2, '0') - return "$hh$mm" - } - - fun toYYYYMMDD(): String { - val yyyy = date.year.toString() - val mm = date.monthNumber.toString().padStart(2, '0') - val dd = date.dayOfMonth.toString().padStart(2, '0') - return "$yyyy$mm$dd" - } - - @Suppress("ConstPropertyName") - companion object { - private const val serialVersionUID: Long = 1L - - fun fromJsonString(json: String) = - kotlin.runCatching { Json.decodeFromString(serializer(), json) }.getOrNull() - } -} diff --git a/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/datetimeselector/JourneyTimeOptionsGroup.kt b/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/datetimeselector/JourneyTimeOptionsGroup.kt index 1631d245..15f15200 100644 --- a/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/datetimeselector/JourneyTimeOptionsGroup.kt +++ b/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/datetimeselector/JourneyTimeOptionsGroup.kt @@ -9,6 +9,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import xyz.ksharma.krail.trip.planner.ui.components.RadioButton +import xyz.ksharma.krail.trip.planner.ui.state.datetimeselector.JourneyTimeOptions @Composable fun JourneyTimeOptionsGroup( @@ -32,8 +33,3 @@ fun JourneyTimeOptionsGroup( } } } - -enum class JourneyTimeOptions(val text: String) { - LEAVE("Leave"), - ARRIVE("Arrive") -} diff --git a/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/timetable/TimeTableDestination.kt b/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/timetable/TimeTableDestination.kt index 60c391e9..885275ff 100644 --- a/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/timetable/TimeTableDestination.kt +++ b/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/timetable/TimeTableDestination.kt @@ -12,11 +12,11 @@ import androidx.navigation.NavOptions import androidx.navigation.compose.composable import androidx.navigation.toRoute import org.koin.compose.viewmodel.koinViewModel -import xyz.ksharma.krail.trip.planner.ui.datetimeselector.DateTimeSelectionItem -import xyz.ksharma.krail.trip.planner.ui.datetimeselector.DateTimeSelectionItem.Companion.fromJsonString import xyz.ksharma.krail.trip.planner.ui.navigation.DateTimeSelectorRoute import xyz.ksharma.krail.trip.planner.ui.navigation.ServiceAlertRoute import xyz.ksharma.krail.trip.planner.ui.navigation.TimeTableRoute +import xyz.ksharma.krail.trip.planner.ui.state.datetimeselector.DateTimeSelectionItem +import xyz.ksharma.krail.trip.planner.ui.state.datetimeselector.DateTimeSelectionItem.Companion.fromJsonString import xyz.ksharma.krail.trip.planner.ui.state.timetable.TimeTableUiEvent import xyz.ksharma.krail.trip.planner.ui.state.timetable.Trip @@ -47,6 +47,7 @@ internal fun NavGraphBuilder.timeTableDestination(navController: NavHostControll LaunchedEffect(dateTimeSelectionJson) { println("Changed dateTimeSelectionItem: $dateTimeSelectionItem") dateTimeSelectionItem = dateTimeSelectionJson?.let { fromJsonString(it) } + viewModel.onEvent(TimeTableUiEvent.DateTimeSelectionChanged(dateTimeSelectionItem)) } TimeTableScreen( diff --git a/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/timetable/TimeTableScreen.kt b/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/timetable/TimeTableScreen.kt index 7fcaf40e..0ab50077 100644 --- a/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/timetable/TimeTableScreen.kt +++ b/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/timetable/TimeTableScreen.kt @@ -54,9 +54,9 @@ import xyz.ksharma.krail.trip.planner.ui.components.OriginDestination import xyz.ksharma.krail.trip.planner.ui.components.hexToComposeColor import xyz.ksharma.krail.trip.planner.ui.components.loading.LoadingEmojiAnim import xyz.ksharma.krail.trip.planner.ui.components.themeContentColor -import xyz.ksharma.krail.trip.planner.ui.datetimeselector.DateTimeSelectionItem import xyz.ksharma.krail.trip.planner.ui.state.TransportMode import xyz.ksharma.krail.trip.planner.ui.state.TransportModeLine +import xyz.ksharma.krail.trip.planner.ui.state.datetimeselector.DateTimeSelectionItem import xyz.ksharma.krail.trip.planner.ui.state.timetable.TimeTableState import xyz.ksharma.krail.trip.planner.ui.state.timetable.TimeTableUiEvent import xyz.ksharma.krail.trip.planner.ui.state.timetable.Trip diff --git a/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/timetable/TimeTableViewModel.kt b/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/timetable/TimeTableViewModel.kt index b7721dae..24802fff 100644 --- a/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/timetable/TimeTableViewModel.kt +++ b/feature/trip-planner/ui/src/commonMain/kotlin/xyz/ksharma/krail/trip/planner/ui/timetable/TimeTableViewModel.kt @@ -24,10 +24,9 @@ import xyz.ksharma.krail.trip.planner.network.api.model.TripResponse import xyz.ksharma.krail.trip.planner.network.api.ratelimit.RateLimiter import xyz.ksharma.krail.trip.planner.network.api.service.DepArr import xyz.ksharma.krail.trip.planner.network.api.service.TripPlanningService -import xyz.ksharma.krail.trip.planner.ui.datetimeselector.DateTimeSelectionItem -import xyz.ksharma.krail.trip.planner.ui.datetimeselector.JourneyTimeOptions -import xyz.ksharma.krail.trip.planner.ui.datetimeselector.JourneyTimeOptions.* import xyz.ksharma.krail.trip.planner.ui.state.alerts.ServiceAlert +import xyz.ksharma.krail.trip.planner.ui.state.datetimeselector.DateTimeSelectionItem +import xyz.ksharma.krail.trip.planner.ui.state.datetimeselector.JourneyTimeOptions import xyz.ksharma.krail.trip.planner.ui.state.timetable.TimeTableState import xyz.ksharma.krail.trip.planner.ui.state.timetable.TimeTableUiEvent import xyz.ksharma.krail.trip.planner.ui.state.timetable.Trip @@ -80,9 +79,14 @@ class TimeTableViewModel( TimeTableUiEvent.SaveTripButtonClicked -> onSaveTripButtonClicked() TimeTableUiEvent.ReverseTripButtonClicked -> onReverseTripButtonClicked() TimeTableUiEvent.RetryButtonClicked -> onLoadTimeTable(tripInfo!!) + is TimeTableUiEvent.DateTimeSelectionChanged -> onDateTimeSelectionChanged(event.dateTimeSelectionItem) } } + private fun onDateTimeSelectionChanged(dateTimeSelectionItem: DateTimeSelectionItem?) { + + } + private fun fetchTrip() { println("fetchTrip API Call") viewModelScope.launch(Dispatchers.IO) { @@ -124,8 +128,8 @@ class TimeTableViewModel( date = dateTimeSelectionItem?.toYYYYMMDD(), time = dateTimeSelectionItem?.toHHMM(), depArr = when (dateTimeSelectionItem?.option) { - LEAVE -> DepArr.DEP - ARRIVE -> DepArr.ARR + JourneyTimeOptions.LEAVE -> DepArr.DEP + JourneyTimeOptions.ARRIVE -> DepArr.ARR else -> DepArr.DEP } )