Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI: Refactor DateTime formatting and selection handling #403

Merged
merged 1 commit into from
Nov 30, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
Expand Up @@ -24,7 +24,7 @@ fun rememberCurrentDateTime(): DateTimePickerInfo {

// Formatting the date
val formattedDate = remember(currentDateTime.date) {
formatDate(currentDateTime.date)
toReadableDate(currentDateTime.date)
}

return DateTimePickerInfo(
Expand All @@ -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)
}
Expand All @@ -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() }}"
}
}
}
3 changes: 3 additions & 0 deletions feature/trip-planner/state/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package xyz.ksharma.krail.trip.planner.ui.state.datetimeselector

enum class JourneyTimeOptions(val text: String) {
LEAVE("Leave"),
ARRIVE("Arrive")
}
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -144,7 +140,7 @@ fun DateTimeSelectorScreen(

DateSelection(
themeColor = themeColor,
date = formatDate(selectedDate),
date = toReadableDate(selectedDate),
onNextClicked = {
if (selectedDate < maxDate) {
selectedDate = incrementDateByOneDay(selectedDate)
Expand Down Expand Up @@ -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()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -32,8 +33,3 @@ fun JourneyTimeOptionsGroup(
}
}
}

enum class JourneyTimeOptions(val text: String) {
LEAVE("Leave"),
ARRIVE("Arrive")
}
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
}
)
Expand Down