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

Compare menus #148

Merged
merged 27 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
134051d
CM FAB and basic ui structure for Bottom sheet
oliviaxjiang Apr 12, 2024
93328c7
allowed checkmarks to be selected + added navigation to screen
oliviaxjiang Apr 12, 2024
3c02335
bot sheet button color
oliviaxjiang Apr 12, 2024
7fc7e16
bottom sheet filter functionality
oliviaxjiang Apr 17, 2024
278a168
navigation passes parameter (next step: viewmodel)
oliviaxjiang Apr 17, 2024
b954171
some progress on displaying items.
oliviaxjiang Apr 19, 2024
15f896a
Update CompareMenusScreen.kt
oliviaxjiang Apr 23, 2024
8442cea
view eatery details
oliviaxjiang Apr 23, 2024
2f187b6
Changed Compare Menus Icon, added Selected Filter
Gregor-Guerrier Apr 24, 2024
387637f
no eatery menu
oliviaxjiang Apr 24, 2024
2155809
Merge branch 'main' into compare-menus
orangeorangejuice Sep 4, 2024
f8500bb
Add animations for FAB and simplify showing logic
thisjustin123 Sep 4, 2024
4a8e2d6
compare menus sticker header
orangeorangejuice Sep 22, 2024
d99096b
both row and icon button clickable
oliviaxjiang Sep 25, 2024
6541231
compare menus view model refactor
oliviaxjiang Sep 27, 2024
c308810
reformat
oliviaxjiang Sep 27, 2024
90379e0
addressing PR comments
oliviaxjiang Sep 28, 2024
201ace2
address PR comment pt 2
oliviaxjiang Sep 28, 2024
2d4740e
Update CompareMenusScreen.kt
oliviaxjiang Sep 28, 2024
a91b9bd
Update CompareMenusScreen.kt
oliviaxjiang Sep 28, 2024
878d5b6
removed unused functions in homeviewmodel
oliviaxjiang Sep 28, 2024
d5106bb
reformat code
oliviaxjiang Sep 28, 2024
4f2ad53
fix filter logic
oliviaxjiang Oct 2, 2024
9acb865
fixed favorite filter logic
oliviaxjiang Oct 2, 2024
f67c277
Refactor
zachseidner1 Oct 2, 2024
bafe771
Merge remote-tracking branch 'origin/main' into compare-menus
zachseidner1 Oct 2, 2024
ce85db8
resolved conflicts
oliviaxjiang Oct 3, 2024
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
@@ -0,0 +1,226 @@
package com.cornellappdev.android.eatery.ui.components.comparemenus

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.outlined.Schedule
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.ViewModel
import com.cornellappdev.android.eatery.data.models.Eatery
import com.cornellappdev.android.eatery.ui.components.general.CompareFilterRow
import com.cornellappdev.android.eatery.ui.components.general.Filter
import com.cornellappdev.android.eatery.ui.components.general.FilterRow
import com.cornellappdev.android.eatery.ui.components.home.MainLoadingItem
import com.cornellappdev.android.eatery.ui.theme.EateryBlue
import com.cornellappdev.android.eatery.ui.theme.EateryBlueTypography
import com.cornellappdev.android.eatery.ui.theme.GrayFive
import com.cornellappdev.android.eatery.ui.theme.GrayTwo
import com.cornellappdev.android.eatery.ui.theme.GrayZero
import com.cornellappdev.android.eatery.ui.viewmodels.CompareMenusBotViewModel
import com.cornellappdev.android.eatery.ui.viewmodels.CompareMenusViewModel
import com.cornellappdev.android.eatery.ui.viewmodels.HomeViewModel
import com.cornellappdev.android.eatery.ui.viewmodels.state.CompareMenusUIState
import com.cornellappdev.android.eatery.ui.viewmodels.state.EateryApiResponse
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

@Composable
fun CompareMenusBotSheet(
onDismiss: () -> Unit,
onCompareMenusClick: (selectedEateriesIds: List<Int>) -> Unit,
compareMenusBotViewModel: CompareMenusBotViewModel = hiltViewModel()
zachseidner1 marked this conversation as resolved.
Show resolved Hide resolved
) {
val compareMenusUIState by compareMenusBotViewModel.compareMenusUiState.collectAsState()
val filters = compareMenusUIState.filters
val selectedEateries = compareMenusUIState.selected
val eateries = compareMenusUIState.eateries

Column(
modifier = Modifier
.fillMaxWidth()
.padding(top = 14.dp)
.padding(16.dp),
horizontalAlignment = Alignment.Start
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = "Compare Menus", style = EateryBlueTypography.h4,
color = Color.Black
)
IconButton(
onClick = {
compareMenusBotViewModel.resetSelected()
onDismiss()
},
modifier = Modifier
.size(40.dp)
.background(color = GrayZero, shape = CircleShape)
) {
Icon(
Icons.Default.Close,
contentDescription = Icons.Default.Close.name,
tint = Color.Black
)
}
}

CompareFilterRow(
currentFiltersSelected = filters,
onPaymentMethodsClicked = {},
onFilterClicked = { filter ->
if (filters.contains(filter)) {
compareMenusBotViewModel.removeFilterCM(filter)
} else {
compareMenusBotViewModel.addFilterCM(filter)
}
},
showPaymentFilter = false
)

Spacer(modifier = Modifier.height(12.dp))

Box(
modifier = Modifier
.background(Color.White)
.fillMaxHeight(0.4f)
.fillMaxWidth()
) {
SelectableEateriesList(eateries, selectedEateries, compareMenusBotViewModel)
}

Spacer(modifier = Modifier.height(12.dp))
val coroutineScope = rememberCoroutineScope()
Button(
onClick = {
if (selectedEateries.size < 2) {

} else {
coroutineScope.launch {
delay(100)
onCompareMenusClick(compareMenusUIState.selected.mapNotNull { it.id })
}
}
},
modifier = Modifier
.fillMaxWidth()
.height(48.dp)
.align(Alignment.CenterHorizontally),
shape = RoundedCornerShape(100),
colors = ButtonDefaults.buttonColors(
backgroundColor = if (selectedEateries.size < 2) GrayTwo else EateryBlue,
contentColor = if (selectedEateries.size < 2) GrayZero else Color.White
)
) {
Text(
text = if (selectedEateries.size < 2) "Select at least ${2 - selectedEateries.size} more"
else "Compare ${selectedEateries.size} now",
style = EateryBlueTypography.h5,
color = Color.White
)
}
}
}

@Composable
private fun SelectableEateriesList(
eateries: List<Eatery>,
selectedEateries: List<Eatery>,
compareMenusBotViewModel: CompareMenusBotViewModel
) {
LazyColumn {
items(eateries) { eatery ->
Row(
modifier = Modifier
.fillMaxWidth()
.clickable {
if (selectedEateries.contains(eatery)) {
compareMenusBotViewModel.removeSelected(eatery)
} else {
compareMenusBotViewModel.addSelected(eatery)
}
},
verticalAlignment = Alignment.CenterVertically,

) {
IconButton(
onClick = {
if (selectedEateries.contains(eatery)) {
compareMenusBotViewModel.removeSelected(eatery)
} else {
compareMenusBotViewModel.addSelected(eatery)
}
},
modifier = Modifier.align(Alignment.CenterVertically)
) {
if (selectedEateries.contains(eatery)) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.size(26.dp)
.background(Color.Black, CircleShape)
) {
Icon(
imageVector = Icons.Default.Check,
contentDescription = "Selected",
tint = Color.White,
modifier = Modifier.size(24.dp)
)
}
} else {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.size(26.dp)
.background(Color.White, CircleShape)
.border(2.dp, Color.Black, CircleShape)
) {
}
}
}
eatery.name?.let {
Text(
text = it, style = EateryBlueTypography.body1,
color = Color.Black
)
}
}


}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.cornellappdev.android.eatery.ui.components.comparemenus

import androidx.compose.foundation.layout.padding
import androidx.compose.material.FloatingActionButton
import androidx.compose.material.Icon
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import com.cornellappdev.android.eatery.R
import com.cornellappdev.android.eatery.ui.theme.EateryBlue

@Composable
fun CompareMenusFAB(
modifier: Modifier = Modifier,
onClick: () -> Unit
) {
FloatingActionButton(
onClick = { onClick() },
modifier = modifier
.padding(16.dp),
backgroundColor = EateryBlue
) {
Icon(
painter = painterResource(id = R.drawable.ic_compare_menus),
"Compare Menus Floating Action Button",
tint = Color.White
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,19 @@ fun EateryDetailsStickyHeader(
filterText: String,
fullMenuList: MutableList<String>,
listState: LazyListState,
eateryDetailViewModel: EateryDetailViewModel = hiltViewModel(),
onItemClick: (Int) -> Unit
) {
startIndex: Int,
onItemClick: (Int) -> Unit,

) {
val rowState = rememberLazyListState()
val rowCoroutine = rememberCoroutineScope()
val selectedEvent = nextEvent?.menu?.find { category ->
highlightCategory(
category,
listState,
nextEvent,
fullMenuList
fullMenuList,
startIndex
)
}
val selectedIndex: Int =
Expand All @@ -90,52 +92,7 @@ fun EateryDetailsStickyHeader(
modifier = Modifier
.fillMaxWidth()
.background(Color.White)
.padding(top = 48.dp, bottom = 12.dp)
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(40.dp)
) {
Text(
modifier = Modifier
.height(26.dp)
.widthIn(0.dp, 280.dp)
.align(Alignment.Center),
textAlign = TextAlign.Center,
text = eatery.name ?: "Loading...",
maxLines = 1,
overflow = TextOverflow.Ellipsis,
color = Color.Black,
style = TextStyle(
fontWeight = FontWeight.SemiBold,
fontSize = 20.sp
)
)

Button(
onClick = { eateryDetailViewModel.toggleFavorite() },
modifier = Modifier
.align(Alignment.CenterEnd)
.padding(end = 16.dp)
.size(40.dp),
contentPadding = PaddingValues(6.dp),
shape = CircleShape,
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.White,
),
elevation = ButtonDefaults.elevation(
defaultElevation = 0.dp,
pressedElevation = 0.dp
)
) {
Icon(
imageVector = if (eateryDetailViewModel.isFavorite) Icons.Filled.Star else Icons.Outlined.StarOutline,
tint = if (eateryDetailViewModel.isFavorite) Yellow else GrayFive,
contentDescription = null
)
}
}

Spacer(modifier = Modifier.height(6.dp))

Expand Down Expand Up @@ -167,7 +124,8 @@ fun EateryDetailsStickyHeader(
category,
listState,
nextEvent,
fullMenuList
fullMenuList,
startIndex
)
CategoryItem(
category.category ?: "Category",
Expand All @@ -192,6 +150,7 @@ fun EateryDetailsStickyHeader(
}
}
}
Spacer(modifier = Modifier.height(6.dp))
}

Divider(
Expand Down Expand Up @@ -245,12 +204,13 @@ fun highlightCategory(
category: MenuCategory,
listState: LazyListState,
nextEvent: Event?,
fullMenuList: MutableList<String>
fullMenuList: MutableList<String>,
startIndex: Int
): Boolean {
val firstVisibleState = remember { derivedStateOf { listState.firstVisibleItemIndex } }
// Note: - 5 here assumes that there are 5 UI elements above the menu, which is true currently.
// If that changes, this must be tweaked.
val firstMenuItemIndex = firstVisibleState.value - 5
val firstMenuItemIndex = firstVisibleState.value - startIndex

if (firstMenuItemIndex >= 0 && firstMenuItemIndex < fullMenuList.size) {
val item = fullMenuList[firstMenuItemIndex]
Expand Down
Loading