From 63fd7ebadaa221972e0122fd7e22cd2bb55a8953 Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 16:17:27 -0500 Subject: [PATCH 01/19] Create DriverRates entity --- .../commonMain/kotlin/entities/DriverRates.kt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 feature/drive/src/commonMain/kotlin/entities/DriverRates.kt diff --git a/feature/drive/src/commonMain/kotlin/entities/DriverRates.kt b/feature/drive/src/commonMain/kotlin/entities/DriverRates.kt new file mode 100644 index 00000000..a19a1e07 --- /dev/null +++ b/feature/drive/src/commonMain/kotlin/entities/DriverRates.kt @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 Pointyware. Use of this software is governed by the GPL-3.0 license. + */ + +package org.pointyware.xyz.drive.entities + +import org.pointyware.xyz.core.entities.business.Rate + +/** + * Rates for a driver's services. + */ +data class DriverRates( + val maintenanceCost: Rate, + val pickupCost: Rate, + val dropoffCost: Rate, +) From feaa77956f019ef869c48139ee09553091e933ce Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 16:44:47 -0500 Subject: [PATCH 02/19] Add DriverSettingsRepository --- .../kotlin/data/DriverSettingsRepository.kt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 feature/drive/src/commonMain/kotlin/data/DriverSettingsRepository.kt diff --git a/feature/drive/src/commonMain/kotlin/data/DriverSettingsRepository.kt b/feature/drive/src/commonMain/kotlin/data/DriverSettingsRepository.kt new file mode 100644 index 00000000..90babffa --- /dev/null +++ b/feature/drive/src/commonMain/kotlin/data/DriverSettingsRepository.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 Pointyware. Use of this software is governed by the GPL-3.0 license. + */ + +package org.pointyware.xyz.drive.data + +import org.pointyware.xyz.core.entities.geo.LatLong +import org.pointyware.xyz.drive.RideFilter +import org.pointyware.xyz.drive.entities.DriverRates + +/** + * Maintains Driver settings. + */ +interface DriverSettingsRepository { + /** + * + */ + fun getFilter(): RideFilter + /** + * + */ + fun setFilter(filter: RideFilter) + /** + * + */ + fun getDriverRates(): DriverRates + /** + * + */ + fun setDriverRates(rates: DriverRates) + + fun getDriverLocation(): LatLong + fun setDriverLocation(location: LatLong) +} From 821f4148755bfe5a7a7f50348f2665161855d0a3 Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 16:44:59 -0500 Subject: [PATCH 03/19] Add plus operator to Length interface --- core/entities/src/commonMain/kotlin/geo/Length.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/entities/src/commonMain/kotlin/geo/Length.kt b/core/entities/src/commonMain/kotlin/geo/Length.kt index 4894dbbf..c78194c2 100644 --- a/core/entities/src/commonMain/kotlin/geo/Length.kt +++ b/core/entities/src/commonMain/kotlin/geo/Length.kt @@ -15,6 +15,10 @@ interface Length: Comparable { fun to(otherUnit: LengthUnit): Length fun format(): String + operator fun plus(other: Length): Length { + val otherToThis = other.to(unit) + return LengthValue(value + otherToThis.value, unit) + } } enum class LengthUnit( From af5a6ab8e320edd1a2219ab7dce2827f7c21bc79 Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 16:56:38 -0500 Subject: [PATCH 04/19] Add plus operator to Currency interface --- .../src/commonMain/kotlin/business/Currency.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/entities/src/commonMain/kotlin/business/Currency.kt b/core/entities/src/commonMain/kotlin/business/Currency.kt index 1bc2167b..baa278f5 100644 --- a/core/entities/src/commonMain/kotlin/business/Currency.kt +++ b/core/entities/src/commonMain/kotlin/business/Currency.kt @@ -22,6 +22,16 @@ interface Currency: Comparable { fun format(): String { return form.format(amount) } + operator fun plus(other: Currency): Currency { + when (other.form.centsPerUnit) { + form.centsPerUnit -> return Currency(amount + other.amount, form) + else -> { + val thisValue = amount + val otherValue = other.amount * other.form.centsPerUnit / form.centsPerUnit + return Currency(thisValue + otherValue, form) + } + } + } sealed class Form( val prefix: String, From f25efc5de7e61a68f8c521f3b0c46b55f72a96d5 Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 16:56:53 -0500 Subject: [PATCH 05/19] Add estimated request interactor model --- .../kotlin/interactors/EstimatedRequest.kt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 feature/drive/src/commonMain/kotlin/interactors/EstimatedRequest.kt diff --git a/feature/drive/src/commonMain/kotlin/interactors/EstimatedRequest.kt b/feature/drive/src/commonMain/kotlin/interactors/EstimatedRequest.kt new file mode 100644 index 00000000..ac459e63 --- /dev/null +++ b/feature/drive/src/commonMain/kotlin/interactors/EstimatedRequest.kt @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024 Pointyware. Use of this software is governed by the GPL-3.0 license. + */ + +package org.pointyware.xyz.drive.interactors + +import org.pointyware.xyz.core.entities.geo.Length +import org.pointyware.xyz.drive.entities.DriverRates +import org.pointyware.xyz.drive.entities.Request + +/** + * A request with estimated pickup distance and driver rates. + */ +data class EstimatedRequest( + val request: Request, + val pickupDistance: Length, + val driverRates: DriverRates +) From c387f392aa1a756b3eb83fe5c9e66c574c4b29fc Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 16:57:08 -0500 Subject: [PATCH 06/19] Add request rating interactor --- .../kotlin/interactors/WatchRatedRequests.kt | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 feature/drive/src/commonMain/kotlin/interactors/WatchRatedRequests.kt diff --git a/feature/drive/src/commonMain/kotlin/interactors/WatchRatedRequests.kt b/feature/drive/src/commonMain/kotlin/interactors/WatchRatedRequests.kt new file mode 100644 index 00000000..370b4e5c --- /dev/null +++ b/feature/drive/src/commonMain/kotlin/interactors/WatchRatedRequests.kt @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 Pointyware. Use of this software is governed by the GPL-3.0 license. + */ + +package org.pointyware.xyz.drive.interactors + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import org.pointyware.xyz.drive.data.DriverSettingsRepository +import org.pointyware.xyz.drive.data.RideRepository + +/** + * + */ +class WatchRatedRequests( + private val repository: RideRepository, + private val driverSettingsRepository: DriverSettingsRepository +) { + + suspend fun invoke(): Result>> { + val filter = driverSettingsRepository.getFilter() + val rates = driverSettingsRepository.getDriverRates() + val location = driverSettingsRepository.getDriverLocation() + + repository.watchRequests(filter) + .onSuccess { flow -> + val estimatedFlow = flow.map { request -> + request.map { + EstimatedRequest( + it, + location.distanceTo(it.route.start.coordinates), + rates + ) + } + } + return Result.success(estimatedFlow) + } + .onFailure { + return Result.failure(it) + } + throw IllegalStateException("Unreachable code") + } +} From d477d2ca136b5e3ea727c204856bdd9d8512bcf6 Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 17:00:08 -0500 Subject: [PATCH 07/19] Add length, rate, and currency properties to ride request ui state --- .../kotlin/viewmodels/RideRequestUiState.kt | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/feature/drive/src/commonMain/kotlin/viewmodels/RideRequestUiState.kt b/feature/drive/src/commonMain/kotlin/viewmodels/RideRequestUiState.kt index 8da9863d..5d10026f 100644 --- a/feature/drive/src/commonMain/kotlin/viewmodels/RideRequestUiState.kt +++ b/feature/drive/src/commonMain/kotlin/viewmodels/RideRequestUiState.kt @@ -8,8 +8,8 @@ import org.pointyware.xyz.core.entities.Uuid import org.pointyware.xyz.core.entities.business.Currency import org.pointyware.xyz.core.entities.business.Rate import org.pointyware.xyz.core.entities.geo.Length -import org.pointyware.xyz.core.entities.geo.Location import org.pointyware.xyz.core.entities.geo.Route +import org.pointyware.xyz.drive.entities.DriverRates /** * Displays information about a new ride request: distance from driver, distance of route, and rider service rate. @@ -18,18 +18,51 @@ interface RideRequestUiState { val requestId: Uuid val riderName: String val route: Route - val distanceFromDriver: Length val riderServiceRate: Rate val totalFair: Currency + + val pickupDistance: Length + val dropoffDistance: Length + val totalDistance: Length + + val pickupRate: Rate + val dropoffRate: Rate + val maintenanceRate: Rate + + val pickupCost: Currency + val dropoffCost: Currency + + val grossProfit: Currency } data class RideRequestUiStateImpl( override val requestId: Uuid, override val riderName: String, override val route: Route, - override val distanceFromDriver: Length, override val riderServiceRate: Rate, + + override val pickupDistance: Length, + val driverRates: DriverRates ): RideRequestUiState { override val totalFair: Currency get() = riderServiceRate * route.distance + + override val dropoffDistance: Length + get() = route.distance + override val totalDistance: Length + get() = pickupDistance + dropoffDistance + + override val pickupRate: Rate + get() = driverRates.pickupCost + override val dropoffRate: Rate + get() = driverRates.dropoffCost + override val maintenanceRate: Rate + get() = driverRates.maintenanceCost + + override val pickupCost: Currency + get() = pickupRate * pickupDistance + override val dropoffCost: Currency + get() = dropoffRate * dropoffDistance + override val grossProfit: Currency + get() = pickupCost + dropoffCost } From 2f27e9a0c7bf1f9afc1769a2ecacebd0ce84d4de Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 17:00:24 -0500 Subject: [PATCH 08/19] replace repository watcher with interactor watcher --- .../kotlin/viewmodels/DriveViewModel.kt | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/feature/drive/src/commonMain/kotlin/viewmodels/DriveViewModel.kt b/feature/drive/src/commonMain/kotlin/viewmodels/DriveViewModel.kt index 69b68a91..87ccab09 100644 --- a/feature/drive/src/commonMain/kotlin/viewmodels/DriveViewModel.kt +++ b/feature/drive/src/commonMain/kotlin/viewmodels/DriveViewModel.kt @@ -11,15 +11,16 @@ import kotlinx.coroutines.launch import org.pointyware.xyz.core.entities.Uuid import org.pointyware.xyz.core.entities.geo.LatLong import org.pointyware.xyz.core.viewmodels.MapViewModelImpl -import org.pointyware.xyz.drive.SimpleRideFilter import org.pointyware.xyz.drive.data.RideRepository +import org.pointyware.xyz.drive.interactors.WatchRatedRequests import org.pointyware.xyz.drive.ui.DriveScreenState /** * */ class DriveViewModel( - private val repository: RideRepository + private val repository: RideRepository, + private val watchRatedRequests: WatchRatedRequests ): MapViewModelImpl() { private val mutableState = MutableStateFlow(DriveScreenState.AvailableRequests(emptyList())) @@ -35,17 +36,19 @@ class DriveViewModel( private fun watchRequests() { requestsJob?.cancel() requestsJob = viewModelScope.launch { - repository.watchRequests(SimpleRideFilter.Permissive) + watchRatedRequests.invoke() .onSuccess { flow -> flow.collect { requestList -> mutableState.value = DriveScreenState.AvailableRequests( requests = requestList.map { + val request = it.request RideRequestUiStateImpl( - requestId = it.rideId, - riderName = it.rider.name.given, - route = it.route, - distanceFromDriver = it.route.start.coordinates.distanceTo(driverLocation), - riderServiceRate = it.rate + requestId = request.rideId, + riderName = request.rider.name.given, + route = request.route, + riderServiceRate = request.rate, + it.pickupDistance, + it.driverRates ) } ) From 16672c9e847b8111711a76fbfe78155f35a34a7d Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 17:01:10 -0500 Subject: [PATCH 09/19] Fix outdated reference --- feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt b/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt index a371d6af..8097851b 100644 --- a/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt +++ b/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt @@ -29,7 +29,7 @@ fun RideRequestView( Text(state.riderName) Text(state.route.start.name) Text(state.route.end.name) - Text(state.distanceFromDriver.toString()) + Text(state.pickupDistance.toString()) Text(state.route.distance.toString()) Text(state.totalFair.toString()) From b6a11a0223876d8df0e6ff5196cd85836705d8c7 Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 17:29:30 -0500 Subject: [PATCH 10/19] Create RideRequestViewUnitTest --- .../ui/RideRequestViewUnitTest.kt | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt diff --git a/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt b/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt new file mode 100644 index 00000000..54252ecb --- /dev/null +++ b/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2024 Pointyware. Use of this software is governed by the GPL-3.0 license. + */ + +package org.pointyware.xyz.feature.drive.ui + +import androidx.compose.ui.test.ComposeUiTest +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.assertTextContains +import androidx.compose.ui.test.onNodeWithContentDescription +import androidx.compose.ui.test.runComposeUiTest +import org.pointyware.xyz.core.entities.Uuid +import org.pointyware.xyz.core.entities.business.Rate.Companion.div +import org.pointyware.xyz.core.entities.business.dollarCents +import org.pointyware.xyz.core.entities.geo.LengthUnit +import org.pointyware.xyz.core.entities.geo.Location +import org.pointyware.xyz.core.entities.geo.Route +import org.pointyware.xyz.core.entities.geo.miles +import org.pointyware.xyz.core.ui.design.XyzTheme +import org.pointyware.xyz.core.ui.di.EmptyTestUiDependencies +import org.pointyware.xyz.drive.entities.DriverRates +import org.pointyware.xyz.drive.ui.RideRequestView +import org.pointyware.xyz.drive.viewmodels.RideRequestUiState +import org.pointyware.xyz.drive.viewmodels.RideRequestUiStateImpl +import kotlin.test.Test +import kotlin.time.Duration.Companion.minutes + +/** + * + */ +@OptIn(ExperimentalTestApi::class) +class RideRequestViewUnitTest { + + + private fun ComposeUiTest.contentUnderTest() { + val missionOfHopeLocation = Location( + 36.103334, -97.051601, + name = "Mission of Hope", + address = "1804 S Perkins Rd", + ) + val walmartLocation = Location( + 36.124656, -97.048823, + name = "Walmart", + address = "111 N Perkins Rd", + ) + val pickupDistance = 1.1.miles() + val pickupDuration = 4.minutes + val routeDistance = 1.6.miles() + val routeDuration = 5.minutes + setContent { + XyzTheme( + uiDependencies = EmptyTestUiDependencies() + ) { + RideRequestView( + state = RideRequestUiStateImpl( + requestId = Uuid.v4(), + riderName = "John", + route = Route( + start = missionOfHopeLocation, + intermediates = emptyList(), + end = walmartLocation, + distance = routeDistance, + duration = routeDuration + ), + riderServiceRate = 100L.dollarCents() / LengthUnit.MILES, + pickupDistance = pickupDistance, + driverRates = DriverRates( + 16L.dollarCents() / LengthUnit.MILES, + 0L.dollarCents() / LengthUnit.MILES, + 83L.dollarCents() / LengthUnit.MILES + ) + ), + onAccept = {}, + onReject = {}, + ) + } + } + } + + @Test + fun `request view displays rider name`() = runComposeUiTest { + + contentUnderTest() + + onNodeWithContentDescription("Rider Name") + .assertExists() + .assertTextContains("John") + } + + @Test + fun `request view displays pickup location + distance + cost`() = runComposeUiTest { + + contentUnderTest() + + onNodeWithContentDescription("Pickup Location") + .assertExists() + .assertTextContains("Mission of Hope") + onNodeWithContentDescription("Pickup Distance") + .assertExists() + .assertTextContains("1.1 miles") + onNodeWithContentDescription("Pickup Rate") + .assertExists() + .assertTextContains("$0.00/mi") + onNodeWithContentDescription("Pickup Cost") + .assertExists() + .assertTextContains("$0.00") + onNodeWithContentDescription("Pickup Maintenance Cost") + .assertExists() + .assertTextContains("$0.18") + } + + @Test + fun `request view displays dropoff location + distance + cost`() = runComposeUiTest { + + contentUnderTest() + + onNodeWithContentDescription("Dropoff Location") + .assertExists() + .assertTextContains("Walmart") + onNodeWithContentDescription("Route Distance") + .assertExists() + .assertTextContains("1.1 miles") + onNodeWithContentDescription("Route Rate") + .assertExists() + .assertTextContains("$0.83/mi") + onNodeWithContentDescription("Route Cost") + .assertExists() + .assertTextContains("$1.33") + onNodeWithContentDescription("Route Maintenance Cost") + .assertExists() + .assertTextContains("$0.88") + } +} From 2a354beed4fb16091a9207bb2ffcf46c47c14794 Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 17:39:59 -0500 Subject: [PATCH 11/19] Look for content description substrings --- .../ui/RideRequestViewUnitTest.kt | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt b/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt index 54252ecb..c25e4687 100644 --- a/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt +++ b/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt @@ -82,9 +82,9 @@ class RideRequestViewUnitTest { contentUnderTest() - onNodeWithContentDescription("Rider Name") + onNodeWithContentDescription("Rider Name", substring = true) .assertExists() - .assertTextContains("John") + .assertTextContains("John", substring = true) } @Test @@ -92,21 +92,21 @@ class RideRequestViewUnitTest { contentUnderTest() - onNodeWithContentDescription("Pickup Location") + onNodeWithContentDescription("Pickup Location", substring = true) .assertExists() - .assertTextContains("Mission of Hope") - onNodeWithContentDescription("Pickup Distance") + .assertTextContains("Mission of Hope", substring = true) + onNodeWithContentDescription("Pickup Distance", substring = true) .assertExists() - .assertTextContains("1.1 miles") - onNodeWithContentDescription("Pickup Rate") + .assertTextContains("1.1 miles", substring = true) + onNodeWithContentDescription("Pickup Rate", substring = true) .assertExists() - .assertTextContains("$0.00/mi") - onNodeWithContentDescription("Pickup Cost") + .assertTextContains("$0.00/mi", substring = true) + onNodeWithContentDescription("Pickup Cost", substring = true) .assertExists() - .assertTextContains("$0.00") - onNodeWithContentDescription("Pickup Maintenance Cost") + .assertTextContains("$0.00", substring = true) + onNodeWithContentDescription("Pickup Maintenance Cost", substring = true) .assertExists() - .assertTextContains("$0.18") + .assertTextContains("$0.18", substring = true) } @Test @@ -114,20 +114,20 @@ class RideRequestViewUnitTest { contentUnderTest() - onNodeWithContentDescription("Dropoff Location") + onNodeWithContentDescription("Dropoff Location", substring = true) .assertExists() - .assertTextContains("Walmart") - onNodeWithContentDescription("Route Distance") + .assertTextContains("Walmart", substring = true) + onNodeWithContentDescription("Route Distance", substring = true) .assertExists() - .assertTextContains("1.1 miles") - onNodeWithContentDescription("Route Rate") + .assertTextContains("1.1 miles", substring = true) + onNodeWithContentDescription("Route Rate", substring = true) .assertExists() - .assertTextContains("$0.83/mi") - onNodeWithContentDescription("Route Cost") + .assertTextContains("$0.83/mi", substring = true) + onNodeWithContentDescription("Route Cost", substring = true) .assertExists() - .assertTextContains("$1.33") - onNodeWithContentDescription("Route Maintenance Cost") + .assertTextContains("$1.33", substring = true) + onNodeWithContentDescription("Route Maintenance Cost", substring = true) .assertExists() - .assertTextContains("$0.88") + .assertTextContains("$0.88", substring = true) } } From 386f9bd9268d1ae8c1cbfca57ca1750c1055b847 Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 17:51:18 -0500 Subject: [PATCH 12/19] Simplify node expectations --- .../ui/RideRequestViewUnitTest.kt | 28 ++++--------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt b/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt index c25e4687..cd60244b 100644 --- a/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt +++ b/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt @@ -95,18 +95,10 @@ class RideRequestViewUnitTest { onNodeWithContentDescription("Pickup Location", substring = true) .assertExists() .assertTextContains("Mission of Hope", substring = true) - onNodeWithContentDescription("Pickup Distance", substring = true) + onNodeWithContentDescription("Pickup Metrics", substring = true) .assertExists() - .assertTextContains("1.1 miles", substring = true) - onNodeWithContentDescription("Pickup Rate", substring = true) - .assertExists() - .assertTextContains("$0.00/mi", substring = true) - onNodeWithContentDescription("Pickup Cost", substring = true) - .assertExists() - .assertTextContains("$0.00", substring = true) - onNodeWithContentDescription("Pickup Maintenance Cost", substring = true) - .assertExists() - .assertTextContains("$0.18", substring = true) + .assertTextContains("1.1 mi @ $0.00/mi", substring = true) + .assertTextContains("$0.00 - $0.18", substring = true) } @Test @@ -117,17 +109,9 @@ class RideRequestViewUnitTest { onNodeWithContentDescription("Dropoff Location", substring = true) .assertExists() .assertTextContains("Walmart", substring = true) - onNodeWithContentDescription("Route Distance", substring = true) - .assertExists() - .assertTextContains("1.1 miles", substring = true) - onNodeWithContentDescription("Route Rate", substring = true) - .assertExists() - .assertTextContains("$0.83/mi", substring = true) - onNodeWithContentDescription("Route Cost", substring = true) - .assertExists() - .assertTextContains("$1.33", substring = true) - onNodeWithContentDescription("Route Maintenance Cost", substring = true) + onNodeWithContentDescription("Route Metrics", substring = true) .assertExists() - .assertTextContains("$0.88", substring = true) + .assertTextContains("1.1 mi @ $0.83/mi", substring = true) + .assertTextContains("$1.33 - $0.88", substring = true) } } From aca43c9bfe2e94c942c2eb66d2f7a8cdf22b2c4d Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 17:55:47 -0500 Subject: [PATCH 13/19] replace old ui with high detail ui --- .../commonMain/kotlin/ui/RideRequestView.kt | 79 +++++++++++++++++-- 1 file changed, 72 insertions(+), 7 deletions(-) diff --git a/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt b/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt index 8097851b..5345a846 100644 --- a/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt +++ b/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt @@ -4,12 +4,17 @@ package org.pointyware.xyz.drive.ui +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material3.Button import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import org.pointyware.xyz.drive.viewmodels.RideRequestUiState /** @@ -25,13 +30,73 @@ fun RideRequestView( Column( modifier = modifier ) { - Text("New Ride Request") - Text(state.riderName) - Text(state.route.start.name) - Text(state.route.end.name) - Text(state.pickupDistance.toString()) - Text(state.route.distance.toString()) - Text(state.totalFair.toString()) + Row { + // AsyncImage( + // model = ImageRequest(), + // contentDescription = "Start location image", + // modifier = Modifier.fillMaxWidth() + // ) + Text( + text = state.riderName, + modifier = Modifier.semantics { + contentDescription = "Rider Name: ${state.riderName}" + } + ) + } + Row( + modifier = Modifier.semantics(mergeDescendants = true) {} + ) { + Image( + imageVector = Icons.Default.PlayArrow, + contentDescription = "Pickup Location" + ) + Text( + text = state.route.start.name, + ) + } + Row( + modifier = Modifier.semantics(mergeDescendants = true) { + contentDescription = "Pickup Metrics" + } + ) { + Text( + text = state.pickupDistance.format() + "@" + state.pickupRate.format(), + ) + Image( + imageVector = Icons.Default.PlayArrow, + contentDescription = null + ) + Text( + text = state.pickupCost.format(), + ) + } + Row( + modifier = Modifier.semantics(mergeDescendants = true) {} + ) { + Image( + imageVector = Icons.Default.PlayArrow, + contentDescription = "Dropoff Location" + ) + Text( + text = state.route.end.name, + ) + } + Row( + modifier = Modifier.semantics(mergeDescendants = true) { + contentDescription = "Route Metrics" + } + ) { + Text( + text = state.dropoffDistance.format() + "@" + state.dropoffRate.format(), + ) + Image( + imageVector = Icons.Default.PlayArrow, + contentDescription = null + ) + Text( + text = state.pickupCost.format(), + ) + } Row { Button(onClick = onReject) { From fa1e2472ede7e008feeda856d069d8007d524e91 Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 17:57:57 -0500 Subject: [PATCH 14/19] Fix expectation with 1 decimal place and wrong value --- .../ui/RideRequestViewUnitTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt b/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt index cd60244b..d429ac58 100644 --- a/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt +++ b/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt @@ -97,7 +97,7 @@ class RideRequestViewUnitTest { .assertTextContains("Mission of Hope", substring = true) onNodeWithContentDescription("Pickup Metrics", substring = true) .assertExists() - .assertTextContains("1.1 mi @ $0.00/mi", substring = true) + .assertTextContains("1.10 mi @ $0.00/mi", substring = true) .assertTextContains("$0.00 - $0.18", substring = true) } @@ -111,7 +111,7 @@ class RideRequestViewUnitTest { .assertTextContains("Walmart", substring = true) onNodeWithContentDescription("Route Metrics", substring = true) .assertExists() - .assertTextContains("1.1 mi @ $0.83/mi", substring = true) + .assertTextContains("1.60 mi @ $0.83/mi", substring = true) .assertTextContains("$1.33 - $0.88", substring = true) } } From 58c838251027ef7e95220e5cacf96e710071fbff Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 17:58:27 -0500 Subject: [PATCH 15/19] Add space around @ symbol --- feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt b/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt index 5345a846..0e1f7724 100644 --- a/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt +++ b/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt @@ -60,7 +60,7 @@ fun RideRequestView( } ) { Text( - text = state.pickupDistance.format() + "@" + state.pickupRate.format(), + text = state.pickupDistance.format() + " @ " + state.pickupRate.format(), ) Image( imageVector = Icons.Default.PlayArrow, @@ -87,7 +87,7 @@ fun RideRequestView( } ) { Text( - text = state.dropoffDistance.format() + "@" + state.dropoffRate.format(), + text = state.dropoffDistance.format() + " @ " + state.dropoffRate.format(), ) Image( imageVector = Icons.Default.PlayArrow, From 139bfe41a585a68644ef515b144fb7387a543989 Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 18:02:09 -0500 Subject: [PATCH 16/19] Fix price called cost; add pickup/dropoff maintenance cost --- .../kotlin/viewmodels/RideRequestUiState.kt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/feature/drive/src/commonMain/kotlin/viewmodels/RideRequestUiState.kt b/feature/drive/src/commonMain/kotlin/viewmodels/RideRequestUiState.kt index 5d10026f..af1a7e3c 100644 --- a/feature/drive/src/commonMain/kotlin/viewmodels/RideRequestUiState.kt +++ b/feature/drive/src/commonMain/kotlin/viewmodels/RideRequestUiState.kt @@ -29,6 +29,9 @@ interface RideRequestUiState { val dropoffRate: Rate val maintenanceRate: Rate + val pickupPrice: Currency + val dropoffPrice: Currency + val pickupCost: Currency val dropoffCost: Currency @@ -59,10 +62,15 @@ data class RideRequestUiStateImpl( override val maintenanceRate: Rate get() = driverRates.maintenanceCost - override val pickupCost: Currency + override val pickupPrice: Currency get() = pickupRate * pickupDistance - override val dropoffCost: Currency + override val dropoffPrice: Currency get() = dropoffRate * dropoffDistance override val grossProfit: Currency - get() = pickupCost + dropoffCost + get() = pickupPrice + dropoffPrice + + override val pickupCost: Currency + get() = maintenanceRate * pickupDistance + override val dropoffCost: Currency + get() = maintenanceRate * dropoffDistance } From 6b7b7f5caa255997e336739f415adf3d3ea4a4c8 Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 18:02:20 -0500 Subject: [PATCH 17/19] Fix price/cost not included --- feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt b/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt index 0e1f7724..af44221d 100644 --- a/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt +++ b/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt @@ -67,7 +67,7 @@ fun RideRequestView( contentDescription = null ) Text( - text = state.pickupCost.format(), + text = state.pickupPrice.format() + " - " + state.pickupCost.format(), ) } Row( @@ -94,7 +94,7 @@ fun RideRequestView( contentDescription = null ) Text( - text = state.pickupCost.format(), + text = state.dropoffPrice.format() + " - " + state.dropoffCost.format(), ) } From 0ec588d099cb4feeb8c9559ccf705cba664884a4 Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 18:02:43 -0500 Subject: [PATCH 18/19] Fix presumed costs --- .../ui/RideRequestViewUnitTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt b/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt index d429ac58..56985822 100644 --- a/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt +++ b/feature/drive/src/commonTest/kotlin/org.pointyware.xyz.feature.drive/ui/RideRequestViewUnitTest.kt @@ -98,7 +98,7 @@ class RideRequestViewUnitTest { onNodeWithContentDescription("Pickup Metrics", substring = true) .assertExists() .assertTextContains("1.10 mi @ $0.00/mi", substring = true) - .assertTextContains("$0.00 - $0.18", substring = true) + .assertTextContains("$0.00 - $0.17", substring = true) } @Test @@ -112,6 +112,6 @@ class RideRequestViewUnitTest { onNodeWithContentDescription("Route Metrics", substring = true) .assertExists() .assertTextContains("1.60 mi @ $0.83/mi", substring = true) - .assertTextContains("$1.33 - $0.88", substring = true) + .assertTextContains("$1.32 - $0.25", substring = true) } } From 480be79b860156bf00ed01741d9b384b793ddcde Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Fri, 13 Sep 2024 18:03:14 -0500 Subject: [PATCH 19/19] Make request fill container width --- feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt b/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt index af44221d..6c12f0b2 100644 --- a/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt +++ b/feature/drive/src/commonMain/kotlin/ui/RideRequestView.kt @@ -7,6 +7,7 @@ package org.pointyware.xyz.drive.ui import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material3.Button @@ -29,6 +30,7 @@ fun RideRequestView( ) { Column( modifier = modifier + .fillMaxWidth() ) { Row { // AsyncImage(