-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
UI: Add DateTime selector screen and picker (#394)
### TL;DR Added a new date and time selector screen for trip planning with a custom time picker interface. ### What changed? - Created a new `DateTimeSelectorScreen` with a vertical time picker and date selection UI - Added navigation support for the new date/time selector screen - Made the "Leaving Now" text in TimeTableScreen clickable to navigate to the selector - Implemented a custom time picker with theme-aware colors and styling - Added radio buttons for "Arrive" and "Leave" journey time options ### How to test? 1. Navigate to the TimeTableScreen 2. Tap on "Leaving Now" text 3. Verify the new DateTimeSelector screen appears 4. Test the time picker functionality 5. Verify the date selection arrows work 6. Confirm the Arrive/Leave radio buttons are functional 7. Test the back button navigation ### Why make this change? To provide users with more control over their journey planning by allowing them to select specific dates and times for their trips, rather than being limited to current time departures only.
- Loading branch information
1 parent
489346e
commit eeada6f
Showing
8 changed files
with
278 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
.../kotlin/xyz/ksharma/krail/trip/planner/ui/datetimeselector/DateTimeSelectorDestination.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package xyz.ksharma.krail.trip.planner.ui.datetimeselector | ||
|
||
import androidx.navigation.NavGraphBuilder | ||
import androidx.navigation.NavHostController | ||
import androidx.navigation.compose.composable | ||
import org.koin.compose.viewmodel.koinViewModel | ||
import xyz.ksharma.krail.trip.planner.ui.navigation.DateTimeSelectorRoute | ||
|
||
internal fun NavGraphBuilder.dateTimeSelectorDestination(navController: NavHostController) { | ||
composable<DateTimeSelectorRoute> { backStackEntry -> | ||
val viewModel: DateTimeSelectorViewModel = koinViewModel<DateTimeSelectorViewModel>() | ||
|
||
DateTimeSelectorScreen() | ||
} | ||
} |
193 changes: 193 additions & 0 deletions
193
...nMain/kotlin/xyz/ksharma/krail/trip/planner/ui/datetimeselector/DateTimeSelectorScreen.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
package xyz.ksharma.krail.trip.planner.ui.datetimeselector | ||
|
||
import androidx.compose.foundation.Image | ||
import androidx.compose.foundation.background | ||
import androidx.compose.foundation.layout.Arrangement | ||
import androidx.compose.foundation.layout.Column | ||
import androidx.compose.foundation.layout.PaddingValues | ||
import androidx.compose.foundation.layout.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.lazy.LazyColumn | ||
import androidx.compose.material.icons.Icons | ||
import androidx.compose.material.icons.automirrored.filled.ArrowBack | ||
import androidx.compose.material3.ExperimentalMaterial3Api | ||
import androidx.compose.material3.IconButton | ||
import androidx.compose.material3.TimePicker | ||
import androidx.compose.material3.TimePickerColors | ||
import androidx.compose.material3.TimePickerLayoutType | ||
import androidx.compose.material3.TimePickerState | ||
import androidx.compose.material3.rememberTimePickerState | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.getValue | ||
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.graphics.ColorFilter | ||
import androidx.compose.ui.text.style.TextAlign | ||
import androidx.compose.ui.unit.dp | ||
import krail.feature.trip_planner.ui.generated.resources.Res | ||
import krail.feature.trip_planner.ui.generated.resources.ic_chevron_left | ||
import krail.feature.trip_planner.ui.generated.resources.ic_chevron_right | ||
import org.jetbrains.compose.resources.painterResource | ||
import xyz.ksharma.krail.core.datetime.rememberCurrentDateTime | ||
import xyz.ksharma.krail.taj.LocalThemeColor | ||
import xyz.ksharma.krail.taj.components.Text | ||
import xyz.ksharma.krail.taj.components.TitleBar | ||
import xyz.ksharma.krail.taj.theme.KrailTheme | ||
import xyz.ksharma.krail.taj.theme.getForegroundColor | ||
import xyz.ksharma.krail.trip.planner.ui.components.IconButton | ||
import xyz.ksharma.krail.trip.planner.ui.components.RadioButton | ||
import xyz.ksharma.krail.trip.planner.ui.components.hexToComposeColor | ||
import xyz.ksharma.krail.trip.planner.ui.timetable.ActionButton | ||
|
||
@OptIn(ExperimentalMaterial3Api::class) | ||
@Composable | ||
fun DateTimeSelectorScreen(modifier: Modifier = Modifier, onBackClick: () -> Unit = {}) { | ||
val themeColorHex by LocalThemeColor.current | ||
val themeColor = remember(themeColorHex) { | ||
themeColorHex.hexToComposeColor() | ||
} | ||
|
||
Column( | ||
modifier = modifier | ||
.fillMaxSize() | ||
.background(color = KrailTheme.colors.surface), | ||
) { | ||
TitleBar( | ||
title = { Text(text = "Plan your trip") }, | ||
navAction = { | ||
ActionButton( | ||
onClick = onBackClick, | ||
contentDescription = "Back", | ||
) { | ||
Image( | ||
imageVector = Icons.AutoMirrored.Filled.ArrowBack, | ||
contentDescription = null, | ||
colorFilter = ColorFilter.tint(KrailTheme.colors.onSurface), | ||
modifier = Modifier.size(24.dp), | ||
) | ||
} | ||
}, | ||
) | ||
|
||
LazyColumn(contentPadding = PaddingValues(vertical = 16.dp)) { | ||
item { | ||
JourneyTimeOptionsRow(themeColor) | ||
} | ||
|
||
item { | ||
DateSelection( | ||
themeColor = themeColor, | ||
date = "Today, 12th July", | ||
modifier = Modifier.padding(horizontal = 16.dp), | ||
) | ||
} | ||
|
||
item { | ||
val currentDateTime = rememberCurrentDateTime() | ||
val timePickerState = rememberTimePickerState( | ||
initialHour = currentDateTime.hour, | ||
initialMinute = currentDateTime.minute, | ||
is24Hour = false, | ||
) | ||
TimeSelection( | ||
timePickerState = timePickerState, | ||
modifier = Modifier.padding(horizontal = 16.dp), | ||
) | ||
} | ||
|
||
} | ||
} | ||
} | ||
|
||
@OptIn(ExperimentalMaterial3Api::class) | ||
@Composable | ||
fun TimeSelection( | ||
timePickerState: TimePickerState, | ||
modifier: Modifier, | ||
) { | ||
val themeColorHex by LocalThemeColor.current | ||
val themeColor = themeColorHex.hexToComposeColor() | ||
val themeContentColor = getForegroundColor(themeColor) | ||
|
||
TimePicker( | ||
state = timePickerState, | ||
colors = TimePickerColors( | ||
containerColor = KrailTheme.colors.surface, | ||
clockDialColor = KrailTheme.colors.surface, | ||
selectorColor = themeColor, | ||
periodSelectorBorderColor = themeColor, | ||
clockDialSelectedContentColor = themeContentColor, | ||
clockDialUnselectedContentColor = KrailTheme.colors.onSurface.copy(alpha = 0.6f), | ||
periodSelectorSelectedContainerColor = themeColor, | ||
periodSelectorUnselectedContainerColor = KrailTheme.colors.surface, | ||
periodSelectorSelectedContentColor = themeContentColor, | ||
periodSelectorUnselectedContentColor = KrailTheme.colors.onSurface.copy(alpha = 0.6f), | ||
timeSelectorSelectedContainerColor = themeColor, | ||
timeSelectorUnselectedContainerColor = KrailTheme.colors.surface, | ||
timeSelectorSelectedContentColor = themeContentColor, | ||
timeSelectorUnselectedContentColor = KrailTheme.colors.onSurface.copy(alpha = 0.6f) | ||
), | ||
layoutType = TimePickerLayoutType.Vertical, | ||
modifier = modifier.fillMaxWidth() | ||
) | ||
} | ||
|
||
@Composable | ||
private fun DateSelection( | ||
themeColor: Color, | ||
date: String, | ||
modifier: Modifier = Modifier, | ||
onDateSelected: () -> Unit = {}, | ||
) { | ||
Column(modifier = modifier.fillMaxWidth().padding(vertical = 24.dp)) { | ||
Text( | ||
text = "Select Date", | ||
style = KrailTheme.typography.title, | ||
color = KrailTheme.colors.onSurface, | ||
modifier = Modifier.padding(vertical = 12.dp) | ||
) | ||
|
||
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { | ||
IconButton( | ||
painter = painterResource(Res.drawable.ic_chevron_left), | ||
color = themeColor, | ||
modifier = Modifier.align(Alignment.CenterVertically) | ||
) | ||
Text( | ||
text = date, | ||
style = KrailTheme.typography.bodyLarge, | ||
color = KrailTheme.colors.onSurface, | ||
modifier = Modifier.weight(1f), | ||
textAlign = TextAlign.Center, | ||
) | ||
IconButton( | ||
painter = painterResource(Res.drawable.ic_chevron_right), | ||
color = themeColor, | ||
modifier = Modifier.align(Alignment.CenterVertically) | ||
) | ||
} | ||
} | ||
} | ||
|
||
@Composable | ||
private fun JourneyTimeOptionsRow(themeColor: Color) { | ||
Row( | ||
modifier = Modifier.fillMaxWidth(), | ||
horizontalArrangement = Arrangement.spacedBy(16.dp) | ||
) { | ||
RadioButton( | ||
text = "Arrive", | ||
selected = true, | ||
backgroundColor = themeColor, | ||
) | ||
RadioButton( | ||
text = "Leave", | ||
backgroundColor = themeColor, | ||
) | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
...in/kotlin/xyz/ksharma/krail/trip/planner/ui/datetimeselector/DateTimeSelectorViewModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package xyz.ksharma.krail.trip.planner.ui.datetimeselector | ||
|
||
import androidx.lifecycle.ViewModel | ||
import androidx.lifecycle.viewModelScope | ||
import kotlinx.collections.immutable.persistentListOf | ||
import kotlinx.collections.immutable.toImmutableList | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.IO | ||
import kotlinx.coroutines.delay | ||
import kotlinx.coroutines.flow.MutableStateFlow | ||
import kotlinx.coroutines.flow.SharingStarted | ||
import kotlinx.coroutines.flow.StateFlow | ||
import kotlinx.coroutines.flow.catch | ||
import kotlinx.coroutines.flow.collectLatest | ||
import kotlinx.coroutines.flow.onStart | ||
import kotlinx.coroutines.flow.stateIn | ||
import kotlinx.coroutines.flow.update | ||
import kotlinx.coroutines.launch | ||
import kotlinx.coroutines.withContext | ||
import xyz.ksharma.krail.core.datetime.DateTimeHelper.calculateTimeDifferenceFromNow | ||
import xyz.ksharma.krail.core.datetime.DateTimeHelper.toGenericFormattedTimeString | ||
import xyz.ksharma.krail.sandook.Sandook | ||
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.TripPlanningService | ||
import xyz.ksharma.krail.trip.planner.ui.state.alerts.ServiceAlert | ||
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 | ||
import xyz.ksharma.krail.trip.planner.ui.timetable.business.buildJourneyList | ||
import kotlin.time.Duration.Companion.seconds | ||
|
||
class DateTimeSelectorViewModel : ViewModel() { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters