Skip to content

Commit 971f99e

Browse files
Merge pull request #9 from cuappdev/andrew/home-search-screen-ui-part2
[Home/Search Screen UI] - Implement Home/Search Screen UI
2 parents f9d9b9f + 93559c5 commit 971f99e

10 files changed

Lines changed: 683 additions & 33 deletions

File tree

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.cornellappdev.hustle.ui.components.home
2+
3+
import androidx.compose.foundation.layout.Arrangement
4+
import androidx.compose.foundation.layout.PaddingValues
5+
import androidx.compose.foundation.lazy.LazyRow
6+
import androidx.compose.foundation.lazy.items
7+
import androidx.compose.foundation.lazy.rememberLazyListState
8+
import androidx.compose.material3.Icon
9+
import androidx.compose.runtime.Composable
10+
import androidx.compose.ui.Modifier
11+
import androidx.compose.ui.res.painterResource
12+
import androidx.compose.ui.tooling.preview.Preview
13+
import com.cornellappdev.hustle.ui.components.general.HustleButton
14+
import com.cornellappdev.hustle.ui.theme.HustleSpacing
15+
import com.cornellappdev.hustle.util.constants.CategoryType
16+
import com.cornellappdev.hustle.util.constants.SERVICE_CATEGORIES
17+
18+
@Composable
19+
fun CategoryButtonRow(
20+
onCategoryClick: (CategoryType) -> Unit,
21+
modifier: Modifier = Modifier,
22+
contentPadding: PaddingValues = PaddingValues(horizontal = HustleSpacing.large)
23+
) {
24+
val lazyListState = rememberLazyListState()
25+
LazyRow(
26+
state = lazyListState,
27+
modifier = modifier,
28+
contentPadding = contentPadding,
29+
horizontalArrangement = Arrangement.spacedBy(HustleSpacing.extraSmall)
30+
) {
31+
items(SERVICE_CATEGORIES, key = { it.categoryType }) { category ->
32+
val categoryType = category.categoryType
33+
HustleButton(
34+
onClick = { onCategoryClick(categoryType) },
35+
text = categoryType.typeName,
36+
leadingIcon = {
37+
Icon(
38+
painter = painterResource(id = category.iconResId),
39+
contentDescription = categoryType.typeName,
40+
)
41+
}
42+
)
43+
}
44+
}
45+
}
46+
47+
@Preview(showBackground = true)
48+
@Composable
49+
private fun CategoryButtonRowPreview() {
50+
CategoryButtonRow(
51+
onCategoryClick = {}
52+
)
53+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package com.cornellappdev.hustle.ui.components.home
2+
3+
import androidx.compose.foundation.layout.Arrangement
4+
import androidx.compose.foundation.layout.Column
5+
import androidx.compose.foundation.layout.Spacer
6+
import androidx.compose.foundation.layout.fillMaxSize
7+
import androidx.compose.foundation.layout.height
8+
import androidx.compose.foundation.layout.padding
9+
import androidx.compose.foundation.lazy.LazyColumn
10+
import androidx.compose.runtime.Composable
11+
import androidx.compose.ui.Modifier
12+
import androidx.compose.ui.tooling.preview.Preview
13+
import androidx.compose.ui.unit.dp
14+
import com.cornellappdev.hustle.data.model.services.Service
15+
import com.cornellappdev.hustle.ui.components.general.ClickableSectionHeader
16+
import com.cornellappdev.hustle.ui.components.general.service.ServiceHorizontalCarouselSection
17+
import com.cornellappdev.hustle.ui.theme.HustleSpacing
18+
import com.cornellappdev.hustle.ui.theme.HustleTheme
19+
import com.cornellappdev.hustle.util.constants.CategoryType
20+
import com.cornellappdev.hustle.util.constants.TEST_SERVICES
21+
22+
@Composable
23+
fun MainContent(
24+
popularRightNowListings: List<Service>,
25+
newOnHustleListings: List<Service>,
26+
servicesNearYouListings: List<Service>,
27+
availableThisWeekListings: List<Service>,
28+
navigateToCategorySubpage: (CategoryType) -> Unit,
29+
navigateToServiceDetail: (Int) -> Unit,
30+
onFavoriteClick: (Int) -> Unit,
31+
modifier: Modifier = Modifier
32+
) {
33+
LazyColumn(
34+
modifier = modifier
35+
.fillMaxSize()
36+
.padding(top = HustleSpacing.small),
37+
) {
38+
item {
39+
CategoryButtonRow(onCategoryClick = navigateToCategorySubpage)
40+
}
41+
item {
42+
Spacer(modifier = Modifier.height(HustleSpacing.medium))
43+
}
44+
item {
45+
Column(
46+
verticalArrangement = Arrangement.spacedBy(HustleSpacing.large)
47+
) {
48+
ServiceHorizontalCarouselSection(
49+
serviceListings = popularRightNowListings,
50+
onServiceClick = navigateToServiceDetail,
51+
onFavoriteClick = onFavoriteClick,
52+
header = {
53+
ClickableSectionHeader(
54+
title = CategoryType.POPULAR_RIGHT_NOW.typeName,
55+
onClick = {
56+
navigateToCategorySubpage(CategoryType.POPULAR_RIGHT_NOW)
57+
},
58+
modifier = Modifier.padding(start = 32.dp)
59+
)
60+
}
61+
)
62+
63+
ServiceHorizontalCarouselSection(
64+
serviceListings = newOnHustleListings,
65+
onServiceClick = navigateToServiceDetail,
66+
onFavoriteClick = onFavoriteClick,
67+
header = {
68+
ClickableSectionHeader(
69+
title = CategoryType.NEW_ON_HUSTLE.typeName,
70+
onClick = {
71+
navigateToCategorySubpage(CategoryType.NEW_ON_HUSTLE)
72+
},
73+
modifier = Modifier.padding(start = 32.dp)
74+
)
75+
}
76+
)
77+
78+
ServiceHorizontalCarouselSection(
79+
serviceListings = servicesNearYouListings,
80+
onServiceClick = navigateToServiceDetail,
81+
onFavoriteClick = onFavoriteClick,
82+
header = {
83+
ClickableSectionHeader(
84+
title = CategoryType.SERVICES_NEAR_YOU.typeName,
85+
onClick = {
86+
navigateToCategorySubpage(CategoryType.SERVICES_NEAR_YOU)
87+
},
88+
modifier = Modifier.padding(start = 32.dp)
89+
)
90+
}
91+
)
92+
93+
ServiceHorizontalCarouselSection(
94+
serviceListings = availableThisWeekListings,
95+
onServiceClick = navigateToServiceDetail,
96+
onFavoriteClick = onFavoriteClick,
97+
header = {
98+
ClickableSectionHeader(
99+
title = CategoryType.AVAILABLE_THIS_WEEK.typeName,
100+
onClick = {
101+
navigateToCategorySubpage(CategoryType.AVAILABLE_THIS_WEEK)
102+
},
103+
modifier = Modifier.padding(start = 32.dp)
104+
)
105+
}
106+
)
107+
}
108+
}
109+
}
110+
}
111+
112+
@Preview(showBackground = true)
113+
@Composable
114+
private fun MainContentPreview() {
115+
HustleTheme {
116+
MainContent(
117+
popularRightNowListings = TEST_SERVICES,
118+
newOnHustleListings = TEST_SERVICES,
119+
servicesNearYouListings = TEST_SERVICES,
120+
availableThisWeekListings = TEST_SERVICES,
121+
navigateToCategorySubpage = {},
122+
navigateToServiceDetail = {},
123+
onFavoriteClick = {},
124+
)
125+
}
126+
}
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package com.cornellappdev.hustle.ui.components.home
2+
3+
import androidx.compose.animation.AnimatedVisibility
4+
import androidx.compose.animation.core.tween
5+
import androidx.compose.animation.fadeIn
6+
import androidx.compose.animation.fadeOut
7+
import androidx.compose.foundation.clickable
8+
import androidx.compose.foundation.layout.Arrangement
9+
import androidx.compose.foundation.layout.Column
10+
import androidx.compose.foundation.layout.Row
11+
import androidx.compose.foundation.layout.Spacer
12+
import androidx.compose.foundation.layout.fillMaxSize
13+
import androidx.compose.foundation.layout.height
14+
import androidx.compose.foundation.layout.padding
15+
import androidx.compose.foundation.rememberScrollState
16+
import androidx.compose.foundation.verticalScroll
17+
import androidx.compose.material3.HorizontalDivider
18+
import androidx.compose.material3.Icon
19+
import androidx.compose.material3.MaterialTheme
20+
import androidx.compose.material3.Text
21+
import androidx.compose.runtime.Composable
22+
import androidx.compose.ui.Alignment
23+
import androidx.compose.ui.Modifier
24+
import androidx.compose.ui.graphics.Color
25+
import androidx.compose.ui.res.painterResource
26+
import androidx.compose.ui.tooling.preview.Preview
27+
import androidx.compose.ui.unit.dp
28+
import com.cornellappdev.hustle.R
29+
import com.cornellappdev.hustle.data.model.services.Service
30+
import com.cornellappdev.hustle.ui.components.general.service.ServiceHorizontalCarouselSection
31+
import com.cornellappdev.hustle.ui.theme.HustleColors
32+
import com.cornellappdev.hustle.ui.theme.HustleSpacing
33+
import com.cornellappdev.hustle.ui.theme.HustleTheme
34+
import com.cornellappdev.hustle.util.constants.TEST_RECENT_SEARCHES
35+
import com.cornellappdev.hustle.util.constants.TEST_SERVICES
36+
37+
@Composable
38+
fun SearchContent(
39+
recentSearches: List<String>,
40+
recentlyViewedServices: List<Service>,
41+
onSearchSuggestionClick: (String) -> Unit,
42+
navigateToServiceDetail: (Int) -> Unit,
43+
onFavoriteClick: (Int) -> Unit,
44+
modifier: Modifier = Modifier
45+
) {
46+
Column(
47+
modifier = modifier
48+
.fillMaxSize()
49+
.padding(top = 4.dp)
50+
.verticalScroll(rememberScrollState()),
51+
) {
52+
AnimatedVisibility(
53+
visible = recentSearches.isNotEmpty(),
54+
label = "Recent Searches Visibility",
55+
enter = fadeIn(animationSpec = tween(300)),
56+
exit = fadeOut(animationSpec = tween(300))
57+
) {
58+
RecentSearchesSection(recentSearches, onSearchSuggestionClick)
59+
}
60+
61+
Spacer(modifier = Modifier.height(44.dp))
62+
63+
AnimatedVisibility(
64+
visible = recentlyViewedServices.isNotEmpty(),
65+
label = "Recently Viewed Services Visibility",
66+
enter = fadeIn(animationSpec = tween(300)),
67+
exit = fadeOut(animationSpec = tween(300))
68+
) {
69+
ServiceHorizontalCarouselSection(
70+
serviceListings = recentlyViewedServices,
71+
onServiceClick = navigateToServiceDetail,
72+
onFavoriteClick = onFavoriteClick,
73+
header = {
74+
Text(
75+
text = "Recently viewed",
76+
style = MaterialTheme.typography.headlineSmall,
77+
modifier = Modifier.padding(start = HustleSpacing.large)
78+
)
79+
}
80+
)
81+
}
82+
}
83+
}
84+
85+
@Composable
86+
private fun RecentSearchesSection(
87+
recentSearches: List<String>,
88+
onSearchSuggestionClick: (String) -> Unit
89+
) {
90+
Column(
91+
modifier = Modifier.padding(horizontal = HustleSpacing.large)
92+
) {
93+
Text(
94+
text = "Recent",
95+
style = MaterialTheme.typography.headlineSmall
96+
)
97+
98+
recentSearches.forEach { recentSearch ->
99+
RecentSearchItem(
100+
recentSearch = recentSearch,
101+
onSearchSuggestionClick = onSearchSuggestionClick
102+
)
103+
}
104+
}
105+
}
106+
107+
@Composable
108+
private fun RecentSearchItem(
109+
recentSearch: String,
110+
onSearchSuggestionClick: (String) -> Unit
111+
) {
112+
Column(
113+
verticalArrangement = Arrangement.spacedBy(HustleSpacing.small),
114+
modifier = Modifier
115+
.clickable(
116+
onClick = {
117+
onSearchSuggestionClick(recentSearch)
118+
}
119+
)
120+
.padding(top = HustleSpacing.medium)
121+
) {
122+
Row(
123+
horizontalArrangement = Arrangement.spacedBy(6.dp),
124+
verticalAlignment = Alignment.CenterVertically
125+
126+
) {
127+
Icon(
128+
painter = painterResource(R.drawable.ic_history),
129+
contentDescription = "Recent Search Icon",
130+
tint = Color.Unspecified
131+
)
132+
Text(
133+
text = recentSearch,
134+
style = MaterialTheme.typography.labelLarge
135+
)
136+
}
137+
HorizontalDivider(color = HustleColors.iconInactive)
138+
}
139+
}
140+
141+
@Preview(showBackground = true)
142+
@Composable
143+
private fun SearchContentPreview() {
144+
HustleTheme {
145+
SearchContent(
146+
recentSearches = TEST_RECENT_SEARCHES,
147+
recentlyViewedServices = TEST_SERVICES,
148+
onSearchSuggestionClick = {},
149+
navigateToServiceDetail = {},
150+
onFavoriteClick = {}
151+
)
152+
}
153+
}

0 commit comments

Comments
 (0)