From a13db7aa7df01307478bf88ca70eebb48b551fff Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Wed, 12 Apr 2023 10:43:32 -0400 Subject: [PATCH] expandable cards --- .../qweather/domain/mappers/WeatherMappers.kt | 29 ++++----- .../domain/weather/HourlyWeatherInfo.kt | 2 +- .../components/weather/WeatherCard.kt | 6 +- .../components/weather/WeatherForecast.kt | 18 +++--- .../components/weather/WeatherHour.kt | 59 +++++++++++++------ .../screenmodel/HourlyWeatherScreenModel.kt | 10 +++- .../qweather/presentation/tabs/TodayTab.kt | 10 +++- 7 files changed, 84 insertions(+), 50 deletions(-) diff --git a/app/src/main/java/com/henryhiles/qweather/domain/mappers/WeatherMappers.kt b/app/src/main/java/com/henryhiles/qweather/domain/mappers/WeatherMappers.kt index 76f5002..2cc9695 100644 --- a/app/src/main/java/com/henryhiles/qweather/domain/mappers/WeatherMappers.kt +++ b/app/src/main/java/com/henryhiles/qweather/domain/mappers/WeatherMappers.kt @@ -12,22 +12,17 @@ import java.time.LocalDateTime import java.time.format.DateTimeFormatter import kotlin.math.roundToInt -private data class IndexedHourlyWeatherData(val index: Int, val data: HourlyWeatherData) - -fun HourlyWeatherDataDto.toHourlyWeatherDataMap(): Map> { - return time.mapIndexed { index, time -> - IndexedHourlyWeatherData( - index = index, - data = HourlyWeatherData( - time = LocalDateTime.parse(time, DateTimeFormatter.ISO_DATE_TIME), - temperature = temperature[index].roundToInt(), - apparentTemperature = apparentTemperature[index].roundToInt(), - windSpeed = windSpeed[index].roundToInt(), - precipitationProbability = precipitationProbability.getOrNull(index), - weatherType = WeatherType.fromWMO(weatherCode[index]) - ) +fun HourlyWeatherDataDto.toHourlyWeatherDataMap(): List { + return time.subList(0, 24).mapIndexed { index, time -> + HourlyWeatherData( + time = LocalDateTime.parse(time, DateTimeFormatter.ISO_DATE_TIME), + temperature = temperature[index].roundToInt(), + apparentTemperature = apparentTemperature[index].roundToInt(), + windSpeed = windSpeed[index].roundToInt(), + precipitationProbability = precipitationProbability.getOrNull(index), + weatherType = WeatherType.fromWMO(weatherCode[index]) ) - }.groupBy { it.index / 24 }.mapValues { entry -> entry.value.map { it.data } } + } } fun DailyWeatherDataDto.toDailyWeatherDataMap(): List { @@ -48,11 +43,11 @@ fun DailyWeatherDataDto.toDailyWeatherDataMap(): List { fun WeatherDto.toHourlyWeatherInfo(): HourlyWeatherInfo { val weatherDataMap = hourlyWeatherData.toHourlyWeatherDataMap() val now = LocalDateTime.now() - val currentWeatherData = weatherDataMap[0]?.find { + val currentWeatherData = weatherDataMap.find { it.time.hour == now.hour } return HourlyWeatherInfo( - weatherDataPerDay = weatherDataMap, + weatherData = weatherDataMap, currentWeatherData = currentWeatherData ) } \ No newline at end of file diff --git a/app/src/main/java/com/henryhiles/qweather/domain/weather/HourlyWeatherInfo.kt b/app/src/main/java/com/henryhiles/qweather/domain/weather/HourlyWeatherInfo.kt index 87d9255..22ba71b 100644 --- a/app/src/main/java/com/henryhiles/qweather/domain/weather/HourlyWeatherInfo.kt +++ b/app/src/main/java/com/henryhiles/qweather/domain/weather/HourlyWeatherInfo.kt @@ -1,6 +1,6 @@ package com.henryhiles.qweather.domain.weather data class HourlyWeatherInfo( - val weatherDataPerDay: Map>, + val weatherData: List, val currentWeatherData: HourlyWeatherData? ) \ No newline at end of file diff --git a/app/src/main/java/com/henryhiles/qweather/presentation/components/weather/WeatherCard.kt b/app/src/main/java/com/henryhiles/qweather/presentation/components/weather/WeatherCard.kt index a2c7b37..23099ce 100644 --- a/app/src/main/java/com/henryhiles/qweather/presentation/components/weather/WeatherCard.kt +++ b/app/src/main/java/com/henryhiles/qweather/presentation/components/weather/WeatherCard.kt @@ -18,12 +18,12 @@ import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.henryhiles.qweather.R -import com.henryhiles.qweather.presentation.screenmodel.HourlyWeatherState +import com.henryhiles.qweather.domain.weather.HourlyWeatherData import java.time.format.DateTimeFormatter @Composable -fun WeatherCard(state: HourlyWeatherState, modifier: Modifier = Modifier) { - state.hourlyWeatherInfo?.currentWeatherData?.let { +fun WeatherCard(hour: HourlyWeatherData?, modifier: Modifier = Modifier) { + hour?.let { val formattedTime = remember(it) { it.time.format(DateTimeFormatter.ofPattern("HH:mm")) } diff --git a/app/src/main/java/com/henryhiles/qweather/presentation/components/weather/WeatherForecast.kt b/app/src/main/java/com/henryhiles/qweather/presentation/components/weather/WeatherForecast.kt index 8ef50eb..d09069b 100644 --- a/app/src/main/java/com/henryhiles/qweather/presentation/components/weather/WeatherForecast.kt +++ b/app/src/main/java/com/henryhiles/qweather/presentation/components/weather/WeatherForecast.kt @@ -2,7 +2,7 @@ package com.henryhiles.qweather.presentation.components.weather import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -14,8 +14,12 @@ import com.henryhiles.qweather.presentation.screenmodel.HourlyWeatherState import java.time.LocalDateTime @Composable -fun WeatherForecast(state: HourlyWeatherState, modifier: Modifier = Modifier) { - state.hourlyWeatherInfo?.weatherDataPerDay?.get(0)?.let { +fun WeatherForecast( + state: HourlyWeatherState, + modifier: Modifier = Modifier, + onChangeSelected: (Int) -> Unit +) { + state.hourlyWeatherInfo?.weatherData?.let { Column( modifier = modifier .fillMaxWidth() @@ -26,12 +30,12 @@ fun WeatherForecast(state: HourlyWeatherState, modifier: Modifier = Modifier) { val rowState = rememberLazyListState(LocalDateTime.now().hour) LazyRow(state = rowState) { - items(it) { + itemsIndexed(it) { index, data -> WeatherHour( - data = it, + data = data, modifier = Modifier - .height(100.dp) - .padding(horizontal = 16.dp) + .padding(horizontal = 8.dp), + onChangeSelected = { onChangeSelected(index) } ) } } diff --git a/app/src/main/java/com/henryhiles/qweather/presentation/components/weather/WeatherHour.kt b/app/src/main/java/com/henryhiles/qweather/presentation/components/weather/WeatherHour.kt index a01c6fd..13f92a4 100644 --- a/app/src/main/java/com/henryhiles/qweather/presentation/components/weather/WeatherHour.kt +++ b/app/src/main/java/com/henryhiles/qweather/presentation/components/weather/WeatherHour.kt @@ -1,13 +1,13 @@ package com.henryhiles.qweather.presentation.components.weather import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.width +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.material3.Card import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment +import androidx.compose.ui.Alignment.Companion.CenterHorizontally import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp @@ -15,25 +15,50 @@ import com.henryhiles.qweather.domain.weather.HourlyWeatherData import java.time.format.DateTimeFormatter @Composable -fun WeatherHour(data: HourlyWeatherData, modifier: Modifier = Modifier) { +fun WeatherHour( + data: HourlyWeatherData, + modifier: Modifier = Modifier, + onChangeSelected: () -> Unit +) { data.let { val formattedTime = remember(it) { it.time.format(DateTimeFormatter.ofPattern("HH:mm")) } + Card(modifier = modifier.clickable { + onChangeSelected() + }) { + Column( + modifier = Modifier + .height(128.dp) + .padding(16.dp), + verticalArrangement = Arrangement.SpaceBetween, + horizontalAlignment = CenterHorizontally + ) { + Text(text = formattedTime) + + Image( + painter = painterResource(id = it.weatherType.iconRes), + contentDescription = "Image of ${it.weatherType.weatherDesc}", + modifier = Modifier.width(40.dp) + ) + + Text(text = "${it.temperature}°C") + } - Column( - modifier = modifier, - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.SpaceBetween - ) { - Text(text = formattedTime) - Image( - painter = painterResource(id = it.weatherType.iconRes), - contentDescription = "Image of ${it.weatherType.weatherDesc}", - modifier = Modifier.width(40.dp) - ) - Text(text = "${it.temperature}°C") } +// Column( +// horizontalAlignment = Alignment.CenterHorizontally, +// verticalArrangement = Arrangement.SpaceBetween, +// modifier = modifier +// ) { +// Text(text = formattedTime) +// Image( +// painter = painterResource(id = it.weatherType.iconRes), +// contentDescription = "Image of ${it.weatherType.weatherDesc}", +// modifier = Modifier.width(40.dp) +// ) +// Text(text = "${it.temperature}°C") +// } } } \ No newline at end of file diff --git a/app/src/main/java/com/henryhiles/qweather/presentation/screenmodel/HourlyWeatherScreenModel.kt b/app/src/main/java/com/henryhiles/qweather/presentation/screenmodel/HourlyWeatherScreenModel.kt index 919b0df..a0cc0e8 100644 --- a/app/src/main/java/com/henryhiles/qweather/presentation/screenmodel/HourlyWeatherScreenModel.kt +++ b/app/src/main/java/com/henryhiles/qweather/presentation/screenmodel/HourlyWeatherScreenModel.kt @@ -17,7 +17,7 @@ data class HourlyWeatherState( val hourlyWeatherInfo: HourlyWeatherInfo? = null, val isLoading: Boolean = false, val error: String? = null, - val expanded: Int? = null + val selected: Int? = null ) class HourlyWeatherScreenModel constructor( @@ -30,7 +30,7 @@ class HourlyWeatherScreenModel constructor( fun loadWeatherInfo(cache: Boolean = true) { coroutineScope.launch { - state = state.copy(isLoading = true, error = null) + state = state.copy(isLoading = true, error = null, selected = null) val currentLocation = locationTracker.getCurrentLocation() currentLocation?.let { location -> state = when (val result = @@ -43,7 +43,7 @@ class HourlyWeatherScreenModel constructor( state.copy( hourlyWeatherInfo = result.data, isLoading = false, - error = null + error = null, ) } @@ -63,4 +63,8 @@ class HourlyWeatherScreenModel constructor( } } } + + fun setSelected(index: Int) { + state = state.copy(selected = index) + } } \ No newline at end of file diff --git a/app/src/main/java/com/henryhiles/qweather/presentation/tabs/TodayTab.kt b/app/src/main/java/com/henryhiles/qweather/presentation/tabs/TodayTab.kt index a2fa590..800848d 100644 --- a/app/src/main/java/com/henryhiles/qweather/presentation/tabs/TodayTab.kt +++ b/app/src/main/java/com/henryhiles/qweather/presentation/tabs/TodayTab.kt @@ -87,9 +87,15 @@ object TodayTab : NavigationTab { modifier = Modifier .fillMaxSize() ) { - WeatherCard(state = weatherViewModel.state) + WeatherCard( + hour = weatherViewModel.state.selected?.let { + weatherViewModel.state.hourlyWeatherInfo?.weatherData?.get(it) + } ?: weatherViewModel.state.hourlyWeatherInfo?.currentWeatherData + ) Spacer(modifier = Modifier.height(16.dp)) - WeatherForecast(state = weatherViewModel.state) + WeatherForecast( + state = weatherViewModel.state + ) { weatherViewModel.setSelected(it) } } } }