Skip to content

Commit 5408d2e

Browse files
authored
Merge pull request #22 from cuappdev/maxwell/SearchViewModel
Finished high fidelity for searching and fixed viewmodel bugs
2 parents e6f4b3b + 98a40a7 commit 5408d2e

File tree

11 files changed

+105
-150
lines changed

11 files changed

+105
-150
lines changed

.idea/compiler.xml

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/deploymentTargetDropDown.xml

+17
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/gradle.xml

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/kotlinc.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/src/main/java/com/cornellappdev/scoop/ui/components/general/DatePicker.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ fun DatePicker(
4949
) {
5050

5151
val dateFormatter =
52-
SimpleDateFormat(stringResource(R.string.date_format), Locale.getDefault())
52+
SimpleDateFormat(stringResource(R.string.month_name_day_year_format), Locale.getDefault())
5353

5454
val datePickerDialog = createDatePickerDialog(
5555
LocalContext.current,
@@ -72,7 +72,7 @@ fun DatePicker(
7272
) {
7373
Row(
7474
modifier = Modifier
75-
.padding(horizontal = 10.dp)
75+
.padding(horizontal = 15.dp)
7676
.fillMaxWidth(),
7777
horizontalArrangement = Arrangement.SpaceBetween
7878
) {

app/src/main/java/com/cornellappdev/scoop/ui/components/search/DisplaySearchesPage.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ import com.cornellappdev.scoop.ui.viewmodel.SearchScreenViewModel
4242
@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
4343
@Composable
4444
fun DisplaySearchesPage(
45-
searchScreenViewModel: SearchScreenViewModel
45+
searchScreenViewModel: SearchScreenViewModel,
46+
onBack: () -> Unit
4647
) {
4748
val searchResults: MutableState<List<Ride>> = remember {
4849
mutableStateOf(listOf())
@@ -85,7 +86,7 @@ fun DisplaySearchesPage(
8586
SearchCard(
8687
searchScreenViewModel,
8788
filter,
88-
isEditing
89+
onBack
8990
) {
9091
// To save computation time, try adding/replacing only what's new, etc.
9192
searchResults.value = it

app/src/main/java/com/cornellappdev/scoop/ui/components/search/SearchCard.kt

+51-135
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,37 @@ package com.cornellappdev.scoop.ui.components.search
33
import androidx.compose.foundation.BorderStroke
44
import androidx.compose.foundation.Canvas
55
import androidx.compose.foundation.clickable
6-
import androidx.compose.foundation.layout.*
6+
import androidx.compose.foundation.layout.Arrangement
7+
import androidx.compose.foundation.layout.Column
8+
import androidx.compose.foundation.layout.Row
9+
import androidx.compose.foundation.layout.Spacer
10+
import androidx.compose.foundation.layout.fillMaxWidth
11+
import androidx.compose.foundation.layout.height
12+
import androidx.compose.foundation.layout.padding
13+
import androidx.compose.foundation.layout.size
14+
import androidx.compose.foundation.layout.wrapContentHeight
715
import androidx.compose.foundation.shape.RoundedCornerShape
8-
import androidx.compose.material.*
16+
import androidx.compose.material.Card
17+
import androidx.compose.material.Icon
18+
import androidx.compose.material.MaterialTheme
19+
import androidx.compose.material.Text
920
import androidx.compose.material.icons.Icons
21+
import androidx.compose.material.icons.filled.CalendarToday
1022
import androidx.compose.material.icons.filled.NearMe
1123
import androidx.compose.material.icons.filled.Place
12-
import androidx.compose.material.icons.outlined.CalendarToday
13-
import androidx.compose.material.icons.outlined.NearMe
14-
import androidx.compose.material.icons.outlined.Place
1524
import androidx.compose.runtime.Composable
1625
import androidx.compose.runtime.MutableState
17-
import androidx.compose.runtime.mutableStateOf
18-
import androidx.compose.runtime.remember
1926
import androidx.compose.ui.Alignment
2027
import androidx.compose.ui.Modifier
2128
import androidx.compose.ui.geometry.Offset
2229
import androidx.compose.ui.graphics.Color
2330
import androidx.compose.ui.graphics.PathEffect
24-
import androidx.compose.ui.platform.LocalContext
2531
import androidx.compose.ui.res.painterResource
2632
import androidx.compose.ui.res.stringResource
2733
import androidx.compose.ui.unit.dp
2834
import com.cornellappdev.scoop.R
2935
import com.cornellappdev.scoop.data.models.Ride
30-
import com.cornellappdev.scoop.ui.components.general.CityPicker
31-
import com.cornellappdev.scoop.ui.components.post.createDatePickerDialog
3236
import com.cornellappdev.scoop.ui.viewmodel.SearchScreenViewModel
33-
import java.text.SimpleDateFormat
34-
import java.util.*
3537

3638
/**
3739
* Composable that displays information about the current state of search of the user.
@@ -43,42 +45,22 @@ import java.util.*
4345
* on in the SearchCard, the manager of this composable is responsible for stopping it (this composable
4446
* has no icons to switch editing mode off).
4547
*
46-
* @param search State that represents the current state of search of the user
48+
* @param searchScreenViewModel State that represents the current state of search of the user
4749
* @param filter State that represents the current filter applied to the results of search
48-
* @param isEditing State that represents the current mode of the [SearchCard]
50+
* @param onBack Function to return to editing Search
4951
* @param onSearchCompleted Callback that returns the results of the edited search back to the caller
5052
*/
5153
@Composable
5254
fun SearchCard(
5355
searchScreenViewModel: SearchScreenViewModel,
5456
filter: MutableState<String?>,
55-
isEditing: MutableState<Boolean>,
57+
onBack: () -> Unit,
5658
onSearchCompleted: (List<Ride>) -> Unit,
5759
) {
5860
// CityPicker requires MutableStates for its values but the Search model does
5961
// not have MutableStates for its fields, so we must convert them and update the
6062
// search state in the callback of CityPicker.
61-
val departureLocationName =
62-
remember { mutableStateOf(searchScreenViewModel.search.departureLocationName.orEmpty()) }
63-
val arrivalLocationName =
64-
remember { mutableStateOf(searchScreenViewModel.search.arrivalLocationName.orEmpty()) }
65-
val departureDate =
66-
remember { mutableStateOf(searchScreenViewModel.search.departureDate.orEmpty()) }
6763

68-
val dateFormatter =
69-
SimpleDateFormat(stringResource(R.string.month_name_day_year_format), Locale.US)
70-
val datePickerDialog = createDatePickerDialog(
71-
LocalContext.current,
72-
{ newDate ->
73-
if (departureDate.value != newDate) {
74-
searchScreenViewModel.search.departureDate = newDate
75-
departureDate.value = newDate
76-
77-
// Query backend to get results with given date, filter if there's a filter
78-
onSearchCompleted(listOf())
79-
}
80-
}, dateFormatter
81-
)
8264
Column(modifier = Modifier.fillMaxWidth()) {
8365
Card(
8466
shape = RoundedCornerShape(10.dp),
@@ -94,137 +76,71 @@ fun SearchCard(
9476
) {
9577
Row {
9678
Icon(
97-
Icons.Outlined.NearMe,
79+
Icons.Filled.NearMe,
9880
modifier = Modifier
9981
.padding(end = 12.dp)
10082
.size(32.dp)
10183
.align(Alignment.CenterVertically),
10284
contentDescription = stringResource(R.string.details_icon_description)
10385
)
104-
CityPicker(
105-
cityState = departureLocationName,
106-
modifier = Modifier.apply {
107-
if (isEditing.value) {
108-
align(Alignment.Bottom)
109-
} else {
110-
align(Alignment.CenterVertically)
111-
}
112-
},
113-
icon = Icons.Filled.NearMe,
114-
placeholder = "", // CityPicker should never be empty.
115-
enabled = isEditing.value,
116-
disabledTextStyle = MaterialTheme.typography.subtitle1,
117-
disableDivider = !isEditing.value
118-
) { name, id ->
119-
if (searchScreenViewModel.search.departureLocationPlaceId != id) {
120-
searchScreenViewModel.setDepartureName(name)
121-
searchScreenViewModel.setDeparturePlaceId(id)
122-
123-
// TODO: Networking for searching for rides should be inserted here and passed into callback.
124-
onSearchCompleted(listOf())
125-
}
126-
}
86+
Text(
87+
text = searchScreenViewModel.search.departureLocationName ?: "null",
88+
style = MaterialTheme.typography.subtitle1
89+
)
12790
}
12891

12992
Icon(
13093
painterResource(R.drawable.ic_details_icon),
13194
modifier = Modifier
132-
.size(32.dp)
133-
.clickable { isEditing.value = !isEditing.value }
95+
.size(26.dp)
96+
.clickable { onBack() }
13497
.align(Alignment.CenterVertically),
13598
contentDescription = stringResource(R.string.details_icon_description)
13699
)
137100
}
138-
139-
if (!isEditing.value) {
140-
Canvas(
141-
Modifier
142-
.padding(start = 16.dp)
143-
.height(17.dp)
144-
) {
145-
drawLine(
146-
color = Color.Black,
147-
start = Offset(0f, 0f),
148-
end = Offset(0f, size.height),
149-
pathEffect = PathEffect.dashPathEffect(floatArrayOf(8f, 8f), 0f),
150-
strokeWidth = 3f
151-
)
152-
}
101+
Canvas(
102+
Modifier
103+
.padding(start = 16.dp)
104+
.height(10.dp)
105+
) {
106+
drawLine(
107+
color = Color.Black,
108+
start = Offset(0f, 0f),
109+
end = Offset(0f, size.height),
110+
pathEffect = PathEffect.dashPathEffect(floatArrayOf(8f, 8f), 0f),
111+
strokeWidth = 3f
112+
)
153113
}
154-
155-
Row(modifier = Modifier.padding(top = if (isEditing.value) 17.dp else 0.dp)) {
114+
Row {
156115
Icon(
157-
Icons.Outlined.Place,
116+
Icons.Filled.Place,
158117
modifier = Modifier
159118
.padding(end = 12.dp)
160119
.size(32.dp)
161120
.align(Alignment.CenterVertically),
162121
contentDescription = stringResource(R.string.details_icon_description)
163122
)
164-
CityPicker(
165-
cityState = arrivalLocationName,
166-
modifier = Modifier.apply {
167-
if (isEditing.value) {
168-
align(Alignment.Bottom)
169-
} else {
170-
align(Alignment.CenterVertically)
171-
}
172-
},
173-
icon = Icons.Filled.Place,
174-
placeholder = "",
175-
enabled = isEditing.value,
176-
disabledTextStyle = MaterialTheme.typography.subtitle1,
177-
disableDivider = !isEditing.value
178-
) { name, id ->
179-
if (searchScreenViewModel.search.arrivalLocationPlaceId != id) {
180-
searchScreenViewModel.setArrivalName(name)
181-
searchScreenViewModel.setArrivalPlaceId(id)
182-
183-
/** TODO: Networking for searching for rides should be inserted here and passed into callback. */
184-
onSearchCompleted(listOf())
185-
}
186-
}
123+
Text(
124+
text = searchScreenViewModel.search.arrivalLocationName ?: "null",
125+
style = MaterialTheme.typography.subtitle1
126+
)
187127
}
188-
189-
Row(modifier = Modifier.padding(top = if (isEditing.value) 17.dp else 0.dp)) {
128+
Spacer(
129+
modifier = Modifier.height(10.dp)
130+
)
131+
Row {
190132
Icon(
191-
Icons.Outlined.CalendarToday,
133+
Icons.Filled.CalendarToday,
192134
modifier = Modifier
193135
.padding(end = 12.dp)
194136
.size(32.dp)
195137
.align(Alignment.CenterVertically),
196138
contentDescription = stringResource(R.string.calendar_icon_description)
197139
)
198-
TextButton(
199-
enabled = isEditing.value,
200-
modifier = Modifier.apply {
201-
if (isEditing.value) {
202-
align(Alignment.Bottom)
203-
} else {
204-
align(Alignment.CenterVertically)
205-
}
206-
},
207-
contentPadding = PaddingValues(
208-
all = 0.dp
209-
),
210-
onClick = {
211-
/** TODO: Change with custom calendar view if made eventually. */
212-
datePickerDialog.show()
213-
}) {
214-
Column {
215-
Text(
216-
departureDate.value,
217-
style = if (isEditing.value) MaterialTheme.typography.h5 else MaterialTheme.typography.subtitle1
218-
)
219-
if (isEditing.value) {
220-
Divider(
221-
modifier = Modifier.padding(top = 4.dp),
222-
color = Color.Black,
223-
thickness = 2.dp
224-
)
225-
}
226-
}
227-
}
140+
Text(
141+
text = searchScreenViewModel.search.departureDate ?: "null",
142+
style = MaterialTheme.typography.subtitle1
143+
)
228144
}
229145
}
230146
}

app/src/main/java/com/cornellappdev/scoop/ui/components/search/SearchFirstPage.kt

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
package com.cornellappdev.scoop.ui.components.search
22

33
import androidx.compose.foundation.background
4-
import androidx.compose.foundation.layout.*
4+
import androidx.compose.foundation.layout.Arrangement
5+
import androidx.compose.foundation.layout.Box
6+
import androidx.compose.foundation.layout.Column
7+
import androidx.compose.foundation.layout.Spacer
8+
import androidx.compose.foundation.layout.fillMaxSize
9+
import androidx.compose.foundation.layout.fillMaxWidth
10+
import androidx.compose.foundation.layout.height
11+
import androidx.compose.foundation.layout.padding
512
import androidx.compose.foundation.shape.RoundedCornerShape
613
import androidx.compose.material.ButtonDefaults
714
import androidx.compose.material.Text
@@ -36,8 +43,8 @@ import com.cornellappdev.scoop.ui.viewmodel.SearchScreenViewModel
3643
*/
3744
@Composable
3845
fun SearchFirstPage(
39-
onProceedClicked: () -> Unit,
40-
searchScreenViewModel: SearchScreenViewModel
46+
searchScreenViewModel: SearchScreenViewModel,
47+
onProceedClicked: () -> Unit
4148
) {
4249
val departureLocation = rememberSaveable { mutableStateOf("") }
4350
val arrivalLocation = rememberSaveable { mutableStateOf("") }
@@ -114,7 +121,9 @@ fun SearchFirstPage(
114121
modifier = Modifier.height(71.dp)
115122
)
116123
TextButton(
117-
onClick = onProceedClicked,
124+
onClick = {
125+
onProceedClicked()
126+
},
118127
modifier = Modifier
119128
.fillMaxWidth()
120129
.height(50.dp)

0 commit comments

Comments
 (0)