From 989bad6c4c6b5a6b32b76c1b53b26ca06ec4a876 Mon Sep 17 00:00:00 2001 From: yura Date: Fri, 19 May 2023 16:32:20 +0300 Subject: [PATCH 01/20] implement search cocktails --- .../main/java/org/mixdrinks/mixdrinks/App.kt | 28 ++- .../mixdrinks/mixdrinks/app/MixDrinksApp.kt | 58 +++-- .../mixdrinks/mixdrinks/app/RetrofitClient.kt | 2 +- .../org/mixdrinks/mixdrinks/app/Routes.kt | 1 + .../mixdrinks/mixdrinks/app/ui/theme/Type.kt | 6 + .../mixdrinks/database/dao/CocktailDao.kt | 36 ++- .../mixdrinks/database/dao/FilterGroupDao.kt | 17 +- .../features/common/ui/NotFoundScreen.kt | 3 +- .../common/ui/widgets/IconTextFieldIcon.kt | 22 ++ .../mixdrinks/features/data/CocktailFull.kt | 9 + .../mixdrinks/features/data/DetailGood.kt | 4 +- .../features/data/FilterGroupFull.kt | 8 +- ...CocktailProvider.kt => MixDrinkService.kt} | 2 +- .../ui/cocktail/DetailScreenCocktail.kt | 12 +- .../cocktail/DetailScreenCocktailViewModel.kt | 7 +- .../mixdrinks/features/fetcher/Fetcher.kt | 89 ++++++-- .../filter/ui/FilterScreenViewModel.kt | 81 ------- .../features/header/ui/SearchHintContent.kt | 47 ---- .../features/start/StartRepository.kt | 47 ++++ .../start/ui/filter/FilterRepository.kt | 40 ++++ .../start/ui/filter/SelectedFilterStore.kt | 37 +++ .../ui/filter/ui/main}/FilterScreen.kt | 126 ++++++----- .../filter/ui/main/FilterScreenViewModel.kt | 66 ++++++ .../ui/filter/ui/search/FilterSearchScreen.kt | 214 ++++++++++++++++++ .../filter/ui/search/FilterSearchViewModel.kt | 46 ++++ .../start/ui/{ => main}/CocktailListItem.kt | 13 +- .../start/ui/{ => main}/StartScreen.kt | 59 +++-- .../ui/{ => main}/StartScreenViewModel.kt | 25 +- .../ui/main/header}/HeaderScreen.kt | 26 ++- .../ui/main/header}/SearchTextField.kt | 59 ++--- app/src/main/res/values-uk/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + 32 files changed, 845 insertions(+), 349 deletions(-) create mode 100644 app/src/main/java/org/mixdrinks/mixdrinks/features/common/ui/widgets/IconTextFieldIcon.kt rename app/src/main/java/org/mixdrinks/mixdrinks/features/data/{CocktailProvider.kt => MixDrinkService.kt} (86%) delete mode 100644 app/src/main/java/org/mixdrinks/mixdrinks/features/filter/ui/FilterScreenViewModel.kt delete mode 100644 app/src/main/java/org/mixdrinks/mixdrinks/features/header/ui/SearchHintContent.kt create mode 100644 app/src/main/java/org/mixdrinks/mixdrinks/features/start/StartRepository.kt create mode 100644 app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/FilterRepository.kt create mode 100644 app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/SelectedFilterStore.kt rename app/src/main/java/org/mixdrinks/mixdrinks/features/{filter/ui => start/ui/filter/ui/main}/FilterScreen.kt (61%) create mode 100644 app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/main/FilterScreenViewModel.kt create mode 100644 app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchScreen.kt create mode 100644 app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchViewModel.kt rename app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/{ => main}/CocktailListItem.kt (86%) rename app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/{ => main}/StartScreen.kt (56%) rename app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/{ => main}/StartScreenViewModel.kt (63%) rename app/src/main/java/org/mixdrinks/mixdrinks/features/{header/ui => start/ui/main/header}/HeaderScreen.kt (72%) rename app/src/main/java/org/mixdrinks/mixdrinks/features/{header/ui => start/ui/main/header}/SearchTextField.kt (63%) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/App.kt b/app/src/main/java/org/mixdrinks/mixdrinks/App.kt index 1d5446f..602df20 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/App.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/App.kt @@ -9,20 +9,23 @@ import org.koin.core.context.GlobalContext.startKoin import org.koin.dsl.module import org.mixdrinks.mixdrinks.app.RetrofitClient import org.mixdrinks.mixdrinks.database.AppDatabase -import org.mixdrinks.mixdrinks.features.data.CocktailProvider +import org.mixdrinks.mixdrinks.features.data.MixDrinkService import org.mixdrinks.mixdrinks.features.detail.ui.cocktail.DetailScreenCocktailViewModel import org.mixdrinks.mixdrinks.features.detail.ui.good.DetailScreenGoodViewModel import org.mixdrinks.mixdrinks.features.detail.ui.tool.DetailScreenToolViewModel import org.mixdrinks.mixdrinks.features.fetcher.Fetcher -import org.mixdrinks.mixdrinks.features.filter.ui.FilterScreenViewModel -import org.mixdrinks.mixdrinks.features.start.ui.StartScreenViewModel +import org.mixdrinks.mixdrinks.features.start.StartRepository +import org.mixdrinks.mixdrinks.features.start.ui.filter.ui.main.FilterScreenViewModel +import org.mixdrinks.mixdrinks.features.start.ui.filter.SelectedFilterStorage +import org.mixdrinks.mixdrinks.features.start.ui.main.StartScreenViewModel +import org.mixdrinks.mixdrinks.features.start.ui.filter.FilterRepository +import org.mixdrinks.mixdrinks.features.start.ui.filter.ui.search.FilterSearchViewModel class App : Application() { override fun onCreate() { super.onCreate() val appModule = module { - single { Room.databaseBuilder( androidContext(), @@ -30,16 +33,23 @@ class App : Application() { "mix-drinks-database" ).build() } + single { RetrofitClient.retrofit.create(MixDrinkService::class.java) } + + single { Fetcher (get(), get()) } + + // Repository + single { StartRepository(get(), get()) } + single { FilterRepository (get(), get()) } + + single { SelectedFilterStorage() } - single { RetrofitClient.retrofit.create(CocktailProvider::class.java) } viewModel { StartScreenViewModel(get()) } - viewModel { (id: Int) -> DetailScreenCocktailViewModel(cocktailId = id, get()) } + viewModel { (id: Int) -> DetailScreenCocktailViewModel(cocktailId = id, get(), get()) } viewModel { (id: Int) -> DetailScreenGoodViewModel(goodId = id, get())} viewModel { (id: Int) -> DetailScreenToolViewModel(toolId = id, get()) } - viewModel { FilterScreenViewModel(get()) } - - single { Fetcher(get(), get()) } + viewModel { FilterScreenViewModel(get(), get()) } + viewModel { FilterSearchViewModel(get(), get()) } } startKoin { diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt b/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt index b6ef8b3..8cf88e1 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt @@ -6,77 +6,75 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import org.koin.androidx.compose.get -import org.mixdrinks.mixdrinks.features.fetcher.Fetcher import org.mixdrinks.mixdrinks.app.ui.theme.MixDrinksTheme import org.mixdrinks.mixdrinks.features.common.ui.NotFoundScreen import org.mixdrinks.mixdrinks.features.detail.ui.cocktail.DetailScreen import org.mixdrinks.mixdrinks.features.detail.ui.good.DetailScreenGood import org.mixdrinks.mixdrinks.features.detail.ui.tool.DetailScreenTool -import org.mixdrinks.mixdrinks.features.filter.ui.FilterScreen -import org.mixdrinks.mixdrinks.features.start.ui.StartScreen +import org.mixdrinks.mixdrinks.features.fetcher.Fetcher +import org.mixdrinks.mixdrinks.features.start.ui.main.StartScreen +import org.mixdrinks.mixdrinks.features.start.ui.filter.ui.main.FilterScreen +import org.mixdrinks.mixdrinks.features.start.ui.filter.ui.search.FilterSearchScreen + @Suppress("LongMethod") @Composable fun MixDrinksApp(modifier: Modifier = Modifier) { Fetcher(get(), get()) - MixDrinksTheme { val navController = rememberNavController() NavHost( - navController = navController, - startDestination = Routes.start + navController = navController, startDestination = Routes.start ) { composable(Routes.start) { - StartScreen( - modifier = modifier, +// FilterSearchScreen(Modifier) + StartScreen(modifier = modifier, onNavigateToDetail = { navController.navigate("${Routes.cocktail}/$it") }, onNavigateToFilter = { navController.navigate(Routes.filter) }, - ) + onNavigateToStart = { navController.navigate(Routes.start) }) } - composable("${Routes.cocktail}/{${Routes.cocktailId}}") { - backStackEntry -> + composable("${Routes.cocktail}/{${Routes.cocktailId}}") { backStackEntry -> val cocktailId = backStackEntry.arguments?.getString(Routes.cocktailId) cocktailId?.toInt()?.let { - DetailScreen( - modifier = modifier, + DetailScreen(modifier = modifier, cocktailId = it, - onNavigateToDetailGood = { navController.navigate("${Routes.good}/$it")}, - onNavigateToDetailTool = { navController.navigate("${Routes.tool}/$it")}, - onBack = { navController.popBackStack() } - ) + onNavigateToStart = { navController.navigate(Routes.start) }, + onNavigateToDetailGood = { navController.navigate("${Routes.good}/$it") }, + onNavigateToDetailTool = { navController.navigate("${Routes.tool}/$it") }, + onBack = { navController.popBackStack() }) } } - composable("${Routes.good}/{${Routes.goodId}}") { - backStackEntry -> + composable("${Routes.good}/{${Routes.goodId}}") { backStackEntry -> val goodId = backStackEntry.arguments?.getString(Routes.goodId) goodId?.toInt()?.let { DetailScreenGood( modifier = modifier, goodId = it, - onBack = { navController.popBackStack() } - ) + onBack = { navController.popBackStack() }) } } - composable("${Routes.tool}/{${Routes.toolId}}") { - backStackEntry -> + composable("${Routes.tool}/{${Routes.toolId}}") { backStackEntry -> val toolId = backStackEntry.arguments?.getString(Routes.toolId) toolId?.toInt()?.let { DetailScreenTool( modifier = modifier, toolId = it, - onBack = { navController.popBackStack() } - ) + onBack = { navController.popBackStack() }) } } composable(Routes.filter) { - FilterScreen( + FilterScreen(modifier = modifier, + onNavigateToStart = { navController.navigate(Routes.start) }, + onNavigateToFilterSearch = { navController.navigate(Routes.filterSearch) }) + } + composable(Routes.filterSearch) { + FilterSearchScreen( modifier = modifier, + onNavigateToFilter = { navController.navigate(Routes.filter) }, ) } composable(Routes.notFound) { - NotFoundScreen( - modifier = modifier, - onNavigateToStart = { navController.navigate(Routes.start) } - ) + NotFoundScreen(modifier = modifier, + onNavigateToStart = { navController.navigate(Routes.start) }) } } } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/app/RetrofitClient.kt b/app/src/main/java/org/mixdrinks/mixdrinks/app/RetrofitClient.kt index 7ebb743..cbfedff 100755 --- a/app/src/main/java/org/mixdrinks/mixdrinks/app/RetrofitClient.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/app/RetrofitClient.kt @@ -10,7 +10,7 @@ import retrofit2.Retrofit import java.util.concurrent.TimeUnit object RetrofitClient { - private const val BASE_URL = "https://api.mixdrinks.org/v2/" + private const val BASE_URL = "https://api.mixdrinks.org/" private const val TIME_OUT: Long = 60 private val logging = HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/app/Routes.kt b/app/src/main/java/org/mixdrinks/mixdrinks/app/Routes.kt index c4ac714..092cf1b 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/app/Routes.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/app/Routes.kt @@ -3,6 +3,7 @@ package org.mixdrinks.mixdrinks.app object Routes { const val start = "start" const val filter = "filter" + const val filterSearch = "filter_search" const val notFound = "not_found" const val cocktail = "cocktail" diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/app/ui/theme/Type.kt b/app/src/main/java/org/mixdrinks/mixdrinks/app/ui/theme/Type.kt index 5e87fa2..7e575d5 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/app/ui/theme/Type.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/app/ui/theme/Type.kt @@ -46,6 +46,12 @@ val Typography = Typography( fontSize = 14.sp, color = Green700 ), + h5 = TextStyle( + fontSize = 12.sp, + fontWeight = FontWeight.W400, + lineHeight = 18.sp, + // letterSpacing = + ), button = TextStyle( fontSize = 14.sp, color = Color.White, diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/database/dao/CocktailDao.kt b/app/src/main/java/org/mixdrinks/mixdrinks/database/dao/CocktailDao.kt index 7efcb1a..fd7f1f1 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/database/dao/CocktailDao.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/database/dao/CocktailDao.kt @@ -1,7 +1,6 @@ package org.mixdrinks.mixdrinks.database.dao -import android.util.Log import androidx.room.ColumnInfo import androidx.room.Dao import androidx.room.Embedded @@ -22,12 +21,14 @@ import org.mixdrinks.mixdrinks.database.entities.CocktailToGoodRelation import org.mixdrinks.mixdrinks.database.entities.CocktailToTag import org.mixdrinks.mixdrinks.database.entities.CocktailToTaste import org.mixdrinks.mixdrinks.database.entities.CocktailToTool +import org.mixdrinks.mixdrinks.database.entities.FilterWithCocktailIds import org.mixdrinks.mixdrinks.database.entities.Glassware import org.mixdrinks.mixdrinks.database.entities.Good import org.mixdrinks.mixdrinks.database.entities.Tag import org.mixdrinks.mixdrinks.database.entities.Taste import org.mixdrinks.mixdrinks.database.entities.Tool import org.mixdrinks.mixdrinks.features.data.CocktailFull +import org.mixdrinks.mixdrinks.features.data.CocktailShort @Dao interface CocktailDao { @@ -58,8 +59,17 @@ interface CocktailDao { @Query("SELECT * FROM cocktails WHERE cocktail_id = :id") suspend fun getById(id: Int): CocktailSnapshotDatabase + @Query("SELECT co.cocktail_id, co.name FROM cocktails AS co " + + "JOIN filter_with_cocktail_ids AS fi " + + "ON co.cocktail_id = fi.cocktail_id WHERE fi.filter_id IN (:filtersId) ") + suspend fun getCocktailWithFiltersShort(filtersId: List): List + @Query("SELECT cocktail_id, name FROM cocktails") - suspend fun getAllShortCocktail(): List + suspend fun getAllCocktailShort(): List + + @Query("SELECT * FROM cocktails") + suspend fun getAllCocktailShort2(): List + } data class CocktailSnapshotDatabase( @@ -111,7 +121,6 @@ data class CocktailSnapshotDatabase( } fun toCocktailFull(): CocktailFull { - Log.d("good", goods.size.toString() + goods.toString()) return CocktailFull( id = CocktailId(cocktail.cocktailId), name = cocktail.name, @@ -150,8 +159,27 @@ data class CocktailSnapshotDatabase( } } -data class CocktailShort( +data class CocktailShort2( @ColumnInfo(name = "cocktail_id") val cocktailId: Int, val name: String, + @Relation( + parentColumn = "cocktail_id", + entityColumn = "cocktail_id", + ) + val filters: List +) { + fun toCocktailsWithFilters(): CocktailsWithFilters { + return CocktailsWithFilters( + cocktailId = cocktailId, + name = name, + filters = filters.map { it.filterId } + ) + } +} + +data class CocktailsWithFilters( + val cocktailId: Int, + val name: String, + val filters: List ) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/database/dao/FilterGroupDao.kt b/app/src/main/java/org/mixdrinks/mixdrinks/database/dao/FilterGroupDao.kt index b076a28..4a343f3 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/database/dao/FilterGroupDao.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/database/dao/FilterGroupDao.kt @@ -17,17 +17,23 @@ interface FilterGroupDao { @Insert(onConflict = OnConflictStrategy.REPLACE) @Transaction suspend fun addAllFilterGroups(filterGroup: List) + @Insert(onConflict = OnConflictStrategy.REPLACE) + @Transaction + suspend fun addFilterGroup(filterGroup: FilterGroup) @Insert(onConflict = OnConflictStrategy.REPLACE) @Transaction suspend fun addAllFilters(filterGroup: List) - + @Insert(onConflict = OnConflictStrategy.REPLACE) + @Transaction + suspend fun addFilter(filterGroup: Filters) @Insert(onConflict = OnConflictStrategy.REPLACE) @Transaction suspend fun addAllFilterWithCocktailId(filterWithCocktailId: List) @Query("SELECT * FROM filter_groups") suspend fun getAllFilterGroups() : List + } data class FilterGroups( @@ -37,6 +43,13 @@ data class FilterGroups( parentColumn = "id", entityColumn = "filter_group_id", ) - val filters: List + val filters: List, + @Relation( + parentColumn = "id", + entityColumn = "filter_id", + ) + val cocktailIds: List, + + ) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/common/ui/NotFoundScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/common/ui/NotFoundScreen.kt index 1b10985..8aeae48 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/common/ui/NotFoundScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/common/ui/NotFoundScreen.kt @@ -1,7 +1,6 @@ package org.mixdrinks.mixdrinks.features.common.ui import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -24,8 +23,8 @@ import org.mixdrinks.mixdrinks.R fun NotFoundScreen(modifier: Modifier, onNavigateToStart: () -> Unit) { Column( modifier = modifier + .padding(top = 50.dp) .fillMaxSize(), - verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Image( diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/common/ui/widgets/IconTextFieldIcon.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/common/ui/widgets/IconTextFieldIcon.kt new file mode 100644 index 0000000..fa5dc14 --- /dev/null +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/common/ui/widgets/IconTextFieldIcon.kt @@ -0,0 +1,22 @@ +package org.mixdrinks.mixdrinks.features.common.ui.widgets + +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.MaterialTheme +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Close +import androidx.compose.runtime.Composable + + +@Composable +fun IconTextFieldIcon(text: String, onClick: () -> Unit) { + if (text.isNotEmpty()) { + IconButton(onClick = { onClick() }) { + Icon( + imageVector = Icons.Outlined.Close, + tint = MaterialTheme.colors.secondary, + contentDescription = null + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/CocktailFull.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/CocktailFull.kt index b3e4e3d..6973254 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/CocktailFull.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/CocktailFull.kt @@ -1,5 +1,6 @@ package org.mixdrinks.mixdrinks.features.data +import androidx.room.ColumnInfo import org.mixdrinks.dto.CocktailId import org.mixdrinks.dto.GlasswareId import org.mixdrinks.dto.GoodId @@ -43,3 +44,11 @@ data class CocktailFull( ) } + + +data class CocktailShort( + @ColumnInfo(name = "cocktail_id") + val cocktailId: Int, + val name: String, +) + diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/DetailGood.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/DetailGood.kt index ebad3e7..36c4532 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/DetailGood.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/DetailGood.kt @@ -3,13 +3,13 @@ package org.mixdrinks.mixdrinks.features.data import org.mixdrinks.dto.GoodId import org.mixdrinks.dto.ToolId -data class DetailGood ( +data class DetailGood( val id: GoodId, val name: String, val about: String ) -data class DetailTool ( +data class DetailTool( val id: ToolId, val name: String, val about: String diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/FilterGroupFull.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/FilterGroupFull.kt index 474b2b9..15ee02c 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/FilterGroupFull.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/FilterGroupFull.kt @@ -6,11 +6,13 @@ data class FilterGroupFull( val id: Int, val name: String, val selectionType: SelectionType, - val filters: List - ) { - data class Filters( + val filters: List +) { + data class Filter( val id: Int, val name: String, + val enabled: Boolean, + val checked: Boolean, val cocktailIds: Set ) } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/CocktailProvider.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/MixDrinkService.kt similarity index 86% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/data/CocktailProvider.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/data/MixDrinkService.kt index 37d4a2a..6e54003 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/CocktailProvider.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/MixDrinkService.kt @@ -3,7 +3,7 @@ package org.mixdrinks.mixdrinks.features.data import org.mixdrinks.dto.SnapshotDto import retrofit2.http.GET -interface CocktailProvider { +interface MixDrinkService { @GET("snapshot") suspend fun getAllCocktails(): SnapshotDto } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt index 5e2fc6e..2532a37 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt @@ -39,6 +39,7 @@ fun DetailScreen( onNavigateToDetailGood: (id: Int) -> Unit, onNavigateToDetailTool: (id: Int) -> Unit, onBack: () -> Unit, + onNavigateToStart: () -> Unit, viewModel: DetailScreenCocktailViewModel = koinViewModel { parametersOf(cocktailId) }, ) { val cocktail by viewModel.uiState.collectAsState() @@ -52,7 +53,8 @@ fun DetailScreen( onNavigateToDetailTool = onNavigateToDetailTool, onNavigateToDetailGood = onNavigateToDetailGood, onBack = onBack, - viewModel = viewModel + viewModel = viewModel, + onClickTagAction = onNavigateToStart ) } is DetailScreenCocktailViewModel.DetailUiState.Loading -> { @@ -74,7 +76,8 @@ fun DetailsScreenData( onNavigateToDetailGood: (id: Int) -> Unit, onNavigateToDetailTool: (id: Int) -> Unit, onBack: () -> Unit, - viewModel: DetailScreenCocktailViewModel + viewModel: DetailScreenCocktailViewModel, + onClickTagAction: () -> Unit, ) { Column( modifier = modifier @@ -93,7 +96,10 @@ fun DetailsScreenData( TagListItem( modifier = modifier, listTags = data.cocktail.tags, - onClickAction = { Log.d("MyLog", it.toString()) } + onClickAction = {tagId -> + viewModel.onClickTag(tagId) + onClickTagAction() + } ) Spacer(modifier = modifier.padding(5.dp)) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktailViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktailViewModel.kt index 35e66ab..f7f0201 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktailViewModel.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktailViewModel.kt @@ -7,12 +7,14 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import org.mixdrinks.mixdrinks.database.AppDatabase import org.mixdrinks.mixdrinks.features.data.CocktailFull +import org.mixdrinks.mixdrinks.features.start.ui.filter.SelectedFilterStorage import java.io.IOException @Suppress("TooGenericExceptionCaught") class DetailScreenCocktailViewModel( private val cocktailId: Int, private val roomDatabase: AppDatabase, + private val filterStorage: SelectedFilterStorage ) : ViewModel() { private val _uiState = MutableStateFlow(DetailUiState.Loading) @@ -21,7 +23,6 @@ class DetailScreenCocktailViewModel( private lateinit var cocktail: CocktailFull private var portions: Int = 1 - init { _uiState.value = DetailUiState.Loading viewModelScope.launch { @@ -46,6 +47,10 @@ class DetailScreenCocktailViewModel( _uiState.value = DetailUiState.Loaded(DetailItemUiState(cocktail, portions)) } + fun onClickTag(id: Int) { + filterStorage.onClickTag(id) + } + sealed class DetailUiState { object Loading : DetailUiState() class Loaded(val itemState: DetailItemUiState) : DetailUiState() diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/fetcher/Fetcher.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/fetcher/Fetcher.kt index cac5ec9..80877e0 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/fetcher/Fetcher.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/fetcher/Fetcher.kt @@ -1,5 +1,6 @@ package org.mixdrinks.mixdrinks.features.fetcher +import android.util.Log import androidx.room.Transaction import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch @@ -25,21 +26,27 @@ import org.mixdrinks.mixdrinks.database.entities.Good import org.mixdrinks.mixdrinks.database.entities.Tag import org.mixdrinks.mixdrinks.database.entities.Taste import org.mixdrinks.mixdrinks.database.entities.Tool -import org.mixdrinks.mixdrinks.features.data.CocktailProvider +import org.mixdrinks.mixdrinks.features.data.MixDrinkService class Fetcher( - private val cocktailProvider: CocktailProvider, - private val roomDatabase: AppDatabase + private val cocktailProvider: MixDrinkService, + private val roomDatabase: AppDatabase, ) { private val scope = MainScope() init { + Log.d("init", "init") scope.launch { if (roomDatabase.cocktailDao().getAll().isEmpty()) { insertToDataBase(cocktailProvider.getAllCocktails()) } + //insertToDataBase(cocktailProvider.getAllCocktails()) + + // Log.d("init", "launch") + } } + private suspend fun insertToDataBase(snapshot: SnapshotDto) { insertAllGlasswares(snapshot.glassware) insertAllGoods(snapshot.goods) @@ -49,6 +56,7 @@ class Fetcher( insertAllCocktails(snapshot.cocktails) insertAllFilters(snapshot.filterGroups) } + @Transaction private suspend fun insertAllGlasswares(glasswares: List) { roomDatabase.glasswareDao().addAll(glasswares.map { glassware -> @@ -59,6 +67,7 @@ class Fetcher( ) }) } + @Transaction private suspend fun insertAllGoods(goods: List) { roomDatabase.goodDao().addAll(goods.map { good -> @@ -69,6 +78,7 @@ class Fetcher( ) }) } + @Transaction private suspend fun insertAllTags(tags: List) { roomDatabase.tagDao().addAll(tags.map { tag -> @@ -78,6 +88,7 @@ class Fetcher( ) }) } + @Transaction private suspend fun insertAllTastes(tastes: List) { roomDatabase.tasteDao().addAll(tastes.map { taste -> @@ -87,6 +98,7 @@ class Fetcher( ) }) } + @Transaction private suspend fun insertAllTools(tools: List) { roomDatabase.toolDao().addAll(tools.map { tool -> @@ -97,6 +109,7 @@ class Fetcher( ) }) } + @Transaction private suspend fun insertAllCocktails(cocktails: List) { roomDatabase.cocktailDao().addAllCocktails( @@ -146,39 +159,67 @@ class Fetcher( ) } } - @Transaction + + // @Transaction private suspend fun insertAllFilters(filterGroup: List) { - roomDatabase.filterGroupDao().addAllFilterGroups( - filterGroup.map { + filterGroup.map { item -> + roomDatabase.filterGroupDao().addFilterGroup( FilterGroup( - id = it.id.value, - name = it.name, - selectionType = it.selectionType + id = item.id.value, + name = item.name, + selectionType = item.selectionType ) - } - ) - filterGroup.map { - roomDatabase.filterGroupDao().addAllFilters( - it.filters.map { filter -> + ) + item.filters.map { + roomDatabase.filterGroupDao().addFilter( Filters( - filterId = filter.id.value, - filterGroupId = it.id.value, - name = filter.name + filterId = it.id.value, + filterGroupId = item.id.value, + name = it.name ) - } - ) - } - filterGroup.map { - it.filters.map { filter -> + ) roomDatabase.filterGroupDao().addAllFilterWithCocktailId( - filter.cocktailIds.map { cocktailId -> + it.cocktailIds.map { cocktailId -> FilterWithCocktailIds( - filterId = filter.id.value, + filterId = it.id.value, cocktailId = cocktailId.id ) } ) } } + +// roomDatabase.filterGroupDao().addAllFilterGroups( +// filterGroup.map { +// FilterGroup( +// id = it.id.value, +// name = it.name, +// selectionType = it.selectionType +// ) +// } +// ) +// filterGroup.map { +// roomDatabase.filterGroupDao().addAllFilters( +// it.filters.map { filter -> +// Filters( +// filterId = filter.id.value, +// filterGroupId = it.id.value, +// name = filter.name +// ) +// } +// ) +// } +// filterGroup.map { +// it.filters.map { filter -> +// roomDatabase.filterGroupDao().addAllFilterWithCocktailId( +// filter.cocktailIds.map { cocktailId -> +// FilterWithCocktailIds( +// filterId = filter.id.value, +// cocktailId = cocktailId.id +// ) +// } +// ) +// } +// } } } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/filter/ui/FilterScreenViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/filter/ui/FilterScreenViewModel.kt deleted file mode 100644 index fcba097..0000000 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/filter/ui/FilterScreenViewModel.kt +++ /dev/null @@ -1,81 +0,0 @@ -package org.mixdrinks.mixdrinks.features.filter.ui - -import android.util.Log -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.State -import androidx.compose.runtime.mutableStateOf -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch -import org.mixdrinks.mixdrinks.database.AppDatabase -import org.mixdrinks.mixdrinks.features.data.FilterGroupFull -import java.io.IOException - -@Suppress("TooGenericExceptionCaught") -class FilterScreenViewModel( - private val roomDatabase: AppDatabase -) : ViewModel() { - private val _listCheckedFilter: MutableState> = mutableStateOf(mutableListOf()) - val listCheckedFilter: State> = _listCheckedFilter - - private val _uiState = MutableStateFlow( - FilterUiState.Loading) - val uiState: StateFlow = _uiState - - init { - _uiState.value = FilterUiState.Loading - - viewModelScope.launch { - try { - val result = roomDatabase.filterGroupDao().getAllFilterGroups() - _uiState.value = FilterUiState.Loaded(FilterItemUiState( - result.map { - FilterGroupFull( - id = it.filterGroup.id, - name = it.filterGroup.name, - selectionType = it.filterGroup.selectionType, - filters = it.filters.map {filter -> - FilterGroupFull.Filters( - id = filter.filterId, - name = filter.name, - cocktailIds = setOf() - ) - } - ) - } - )) - } catch (error: IOException) { - _uiState.value = FilterUiState.Error(error.toString()) - } catch (error: Exception) { - _uiState.value = FilterUiState.Error(error.toString()) - } - } - } - - sealed class FilterUiState { - object Loading : FilterUiState() - class Loaded(val itemState: FilterItemUiState) : FilterUiState() - class Error(val message: String) : FilterUiState() - } - - fun checkedAction(id: Int) { - if(_listCheckedFilter.value.find { it == id } == null) { - _listCheckedFilter.value.add(id) - } else { - _listCheckedFilter.value.remove(id) - } - Log.d("CheckedAction", _listCheckedFilter.value.toString()) - } - - fun clearFilters() { - _listCheckedFilter.value.clear() - } -} - -data class FilterItemUiState( - val filters: List -) - - diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/header/ui/SearchHintContent.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/header/ui/SearchHintContent.kt deleted file mode 100644 index 39602ff..0000000 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/header/ui/SearchHintContent.kt +++ /dev/null @@ -1,47 +0,0 @@ -package org.mixdrinks.mixdrinks.features.header.ui - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp - - -@Composable -fun SearchHintContent(modifier: Modifier, listHints: List = listItems, onClickAction: (item: String) -> Unit) { - LazyColumn( - contentPadding = PaddingValues(horizontal = 8.dp, vertical = 8.dp), - verticalArrangement = Arrangement.spacedBy(8.dp), - ) { - items(listHints) { item -> - Row( - modifier = modifier - .fillMaxWidth() - .clickable { - onClickAction(item) - } - ) { - Text( - color = MaterialTheme.colors.primary, - style = MaterialTheme.typography.h3, - text = item - ) - } - - } - } -} - -private val listItems = listOf( - "Джин тонік", - "Джин тонік 2", - "Джин тонік 3", -) - diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/StartRepository.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/StartRepository.kt new file mode 100644 index 0000000..9dad20a --- /dev/null +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/StartRepository.kt @@ -0,0 +1,47 @@ +package org.mixdrinks.mixdrinks.features.start; + +import org.mixdrinks.mixdrinks.database.AppDatabase +import org.mixdrinks.mixdrinks.database.dao.CocktailsWithFilters +import org.mixdrinks.mixdrinks.features.data.CocktailShort +import org.mixdrinks.mixdrinks.features.start.ui.filter.SelectedFilterStorage + + +class StartRepository( + private val roomDatabase: AppDatabase, + private val filterStorage: SelectedFilterStorage, +) { + private var cocktails: List = listOf() + + suspend fun getCocktails(): List { + if (cocktails.isEmpty()) { + cocktails = getCocktailFromDatabase() + } + if (filterStorage.selectedFilters.value.isNotEmpty()) { + return filterCocktail(cocktails).map { CocktailShort(it.cocktailId, it.name) } + } + + return cocktails.map { CocktailShort(it.cocktailId, it.name) } + } + + fun searchCocktail(search: String): List { + return cocktails + .filter { it.name.lowercase().contains(search.lowercase()) } + .map { CocktailShort(it.cocktailId, it.name) } + } + + + private fun filterCocktail(cocktails: List): List { + return cocktails.filter { cocktail -> + cocktail.filters.find { filterId -> + filterStorage.selectedFilters.value.find { it == filterId } != null + } != null + } + } + + private suspend fun getCocktailFromDatabase(): List { + return roomDatabase.cocktailDao().getAllCocktailShort2().map { it.toCocktailsWithFilters() } + } + + +} + diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/FilterRepository.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/FilterRepository.kt new file mode 100644 index 0000000..fae8e6e --- /dev/null +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/FilterRepository.kt @@ -0,0 +1,40 @@ +package org.mixdrinks.mixdrinks.features.start.ui.filter + +import org.mixdrinks.mixdrinks.database.AppDatabase +import org.mixdrinks.mixdrinks.database.dao.FilterGroups +import org.mixdrinks.mixdrinks.features.data.FilterGroupFull + +class FilterRepository( + private val roomDatabase: AppDatabase, + private val filterStorage: SelectedFilterStorage + +) { + private var filters: List = listOf() + + suspend fun getFilters(): List { + if (filters.isEmpty()) { + filters = getFiltersFromDatabase() + } + return filters.map { + FilterGroupFull( + id = it.filterGroup.id, + name = it.filterGroup.name, + selectionType = it.filterGroup.selectionType, + filters = it.filters.map { filter -> + FilterGroupFull.Filter( + id = filter.filterId, + name = filter.name, + cocktailIds = setOf(), + checked = (filterStorage.selectedFilters.value.find { f -> f == filter.filterId } != null), + enabled = true + ) + } + ) + } + } + + private suspend fun getFiltersFromDatabase(): List { + return roomDatabase.filterGroupDao().getAllFilterGroups() + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/SelectedFilterStore.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/SelectedFilterStore.kt new file mode 100644 index 0000000..7a10a7d --- /dev/null +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/SelectedFilterStore.kt @@ -0,0 +1,37 @@ +package org.mixdrinks.mixdrinks.features.start.ui.filter + +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update + +class SelectedFilterStorage { + private val _selectedFilters = MutableStateFlow(mutableListOf()) + val selectedFilters: StateFlow> = _selectedFilters + + fun add(id: Int) { + val list = mutableListOf() + list.addAll((_selectedFilters.value)) + if(list.find { it == id } == null) { + list.add(id) + } else { + list.remove(id) + } + + _selectedFilters.update { + list.toMutableList() + } + } + + fun clear() { + _selectedFilters.update { + mutableListOf() + } + } + + fun onClickTag(id: Int) { + _selectedFilters.update { + mutableListOf(id) + } + } +} + diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/filter/ui/FilterScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/main/FilterScreen.kt similarity index 61% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/filter/ui/FilterScreen.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/main/FilterScreen.kt index 3d7ce4c..1c25bfb 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/filter/ui/FilterScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/main/FilterScreen.kt @@ -1,4 +1,4 @@ -package org.mixdrinks.mixdrinks.features.filter.ui +package org.mixdrinks.mixdrinks.features.start.ui.filter.ui.main import android.util.Log import androidx.compose.foundation.BorderStroke @@ -13,9 +13,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.grid.GridCells -import androidx.compose.foundation.lazy.grid.LazyVerticalGrid -import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Button @@ -26,9 +23,6 @@ import androidx.compose.material.Text 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.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -40,12 +34,14 @@ import org.mixdrinks.mixdrinks.R import org.mixdrinks.mixdrinks.features.common.ui.ErrorLoadingScreen import org.mixdrinks.mixdrinks.features.common.ui.LoaderIndicatorScreen import org.mixdrinks.mixdrinks.features.data.FilterGroupFull - +import java.util.Locale @Composable fun FilterScreen( modifier: Modifier, viewModel: FilterScreenViewModel = koinViewModel(), + onNavigateToStart: () -> Unit, + onNavigateToFilterSearch: () -> Unit ) { val filters by viewModel.uiState.collectAsState() when(filters) { @@ -54,7 +50,9 @@ fun FilterScreen( FilterScreenData( modifier = modifier, filters = data.filters, - viewModel = viewModel + viewModel = viewModel, + onClickButtonApplyAction = onNavigateToStart, + onClickButtonAddAction = onNavigateToFilterSearch ) } is FilterScreenViewModel.FilterUiState.Loading -> { @@ -73,6 +71,8 @@ fun FilterScreenData( modifier: Modifier, filters: List, viewModel: FilterScreenViewModel, + onClickButtonApplyAction: () -> Unit, + onClickButtonAddAction: () -> Unit ) { Column( modifier = modifier @@ -102,39 +102,68 @@ fun FilterScreenData( } } Spacer(modifier = modifier.padding(top = 10.dp)) + Box( modifier = modifier.weight(1f) ) { LazyColumn { items( - items = filters, - itemContent = { + items = filters.sortedBy { it.filters.size }, + itemContent = { it -> Text( text = it.name, style = MaterialTheme.typography.h2 ) - FilterCategoryItems( - modifier = modifier, - items = it.filters, - viewModel = viewModel - ) + when(true) { + (it.filters.size < 10) -> { + it.filters.forEach { item -> + FilterItem(item, onClick = {id -> viewModel.checkedAction(id) }) + } + } + else -> { + it.filters.filter { it.checked }.forEach {item -> + FilterItem(item, onClick = {id -> viewModel.checkedAction(id) }) + } + AddButton(modifier = modifier, text = it.name, onClick = onClickButtonAddAction) + } + } } ) } } - ApplyButton(modifier = modifier) + ApplyButton(modifier = modifier, onClick = onClickButtonApplyAction) + } +} + +@Composable +private fun FilterItem(item: FilterGroupFull.Filter, onClick: (id: Int) -> Unit) { + OutlinedButton( + border = BorderStroke(1.dp, MaterialTheme.colors.primary), + shape = RoundedCornerShape(18.dp), + onClick = { + onClick(item.id) + }, + colors = ButtonDefaults.buttonColors( + backgroundColor = if(item.checked) MaterialTheme.colors.primary else Color.Transparent, + ) + ) { + Text( + text = item.name, + style = MaterialTheme.typography.h4, + color = if(item.checked) Color.White else MaterialTheme.colors.primary + ) } } @Composable -fun ApplyButton(modifier: Modifier) { +fun ApplyButton(modifier: Modifier, onClick: () -> Unit) { Box( modifier = modifier .background(Color.White) .fillMaxWidth() ) { Button( - onClick = { }, + onClick = { onClick() }, shape = RoundedCornerShape(16.dp), colors = ButtonDefaults.buttonColors(backgroundColor = MaterialTheme.colors.primary), modifier = Modifier @@ -152,48 +181,29 @@ fun ApplyButton(modifier: Modifier) { } } -@Suppress("MagicNumber") @Composable -fun FilterCategoryItems( - modifier: Modifier, - items: List, - viewModel: FilterScreenViewModel -) { - //val listCheckedFilter by viewModel.listCheckedFilter - - val countRow = if(items.size < 5) 1 else 2 - val heightRow = if(countRow == 1) 40 else 80 // dp - LazyVerticalGrid ( - columns = GridCells.Fixed(4), - verticalArrangement = Arrangement.spacedBy(2.dp), +fun AddButton(modifier: Modifier, text: String, onClick: () -> Unit) { + Box( modifier = modifier - .height(heightRow.dp) - .fillMaxWidth(1f), - + .background(Color.White) + .fillMaxWidth() ) { - items( - items = items, - itemContent = { item -> - var isSelected by remember { mutableStateOf(false) } - OutlinedButton( - border = BorderStroke(1.dp, MaterialTheme.colors.primary), - shape = RoundedCornerShape(18.dp), - onClick = { - isSelected = !isSelected - viewModel.checkedAction(item.id) - }, - colors = ButtonDefaults.buttonColors( - backgroundColor = if(isSelected) MaterialTheme.colors.primary else Color.Transparent, - ) - ) { - Text( - text = item.name, - style = MaterialTheme.typography.h4, - color = if(isSelected) Color.White else MaterialTheme.colors.primary - ) - } - } - ) + OutlinedButton( + onClick = { onClick() }, + border = BorderStroke(1.dp, MaterialTheme.colors.primary), + shape = RoundedCornerShape(18.dp), + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp) + .height(40.dp) + .align(Alignment.Center) + ) { + Text( + text = "${stringResource(id = R.string.add)} ${text.lowercase(Locale.ROOT)} ${stringResource(id = R.string.to_filter).lowercase()}", + style = MaterialTheme.typography.h5, + color = Color.Black + ) + } } } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/main/FilterScreenViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/main/FilterScreenViewModel.kt new file mode 100644 index 0000000..d576eba --- /dev/null +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/main/FilterScreenViewModel.kt @@ -0,0 +1,66 @@ +package org.mixdrinks.mixdrinks.features.start.ui.filter.ui.main + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import org.mixdrinks.mixdrinks.features.data.FilterGroupFull +import org.mixdrinks.mixdrinks.features.start.ui.filter.FilterRepository +import org.mixdrinks.mixdrinks.features.start.ui.filter.SelectedFilterStorage +import java.io.IOException + +@Suppress("TooGenericExceptionCaught") +class FilterScreenViewModel( + private val filterStorage: SelectedFilterStorage, + private val filterRepository: FilterRepository +) : ViewModel() { + private val _uiState = MutableStateFlow(FilterUiState.Loading) + val uiState: StateFlow = _uiState + + init { + _uiState.value = FilterUiState.Loading + + viewModelScope.launch { + filterStorage.selectedFilters.collect { + updateFilters() + } + } + viewModelScope.launch { + try { + updateFilters() + } catch (error: IOException) { + _uiState.value = FilterUiState.Error(error.toString()) + } catch (error: Exception) { + _uiState.value = FilterUiState.Error(error.toString()) + } + } + } + + private suspend fun updateFilters() { + _uiState.update { + FilterUiState.Loaded(FilterItemUiState(filterRepository.getFilters())) + } + } + + sealed class FilterUiState { + object Loading : FilterUiState() + class Loaded(val itemState: FilterItemUiState) : FilterUiState() + class Error(val message: String) : FilterUiState() + } + + fun checkedAction(id: Int) { + filterStorage.add(id) + } + + fun clearFilters() { + filterStorage.clear() + } +} + +data class FilterItemUiState( + val filters: List +) + + diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchScreen.kt new file mode 100644 index 0000000..97b1c51 --- /dev/null +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchScreen.kt @@ -0,0 +1,214 @@ +package org.mixdrinks.mixdrinks.features.start.ui.filter.ui.search + +import android.util.Log +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +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.layout.width +import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.CornerSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.MaterialTheme +import androidx.compose.material.OutlinedButton +import androidx.compose.material.Text +import androidx.compose.material.TextField +import androidx.compose.material.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.unit.dp +import coil.compose.AsyncImage +import org.koin.androidx.compose.koinViewModel +import org.mixdrinks.domain.ImageUrlCreators +import org.mixdrinks.dto.CocktailId +import org.mixdrinks.mixdrinks.features.common.ui.ErrorLoadingScreen +import org.mixdrinks.mixdrinks.features.common.ui.LoaderIndicatorScreen +import org.mixdrinks.mixdrinks.features.common.ui.widgets.IconTextFieldIcon +import org.mixdrinks.mixdrinks.features.data.FilterGroupFull +import org.mixdrinks.mixdrinks.features.start.ui.filter.ui.main.ApplyButton + +@Composable +fun FilterSearchScreen( + modifier: Modifier, + viewModel: FilterSearchViewModel = koinViewModel(), + onNavigateToFilter: () -> Unit + +) { + val filters by viewModel.uiState.collectAsState() + when (filters) { + is FilterSearchViewModel.FilterUiState.Loaded -> { + val data = (filters as FilterSearchViewModel.FilterUiState.Loaded).itemState + FilterSearchScreenData( + modifier = modifier, + filters = data.filters, + onNavigateToFilter = onNavigateToFilter + ) + } + + is FilterSearchViewModel.FilterUiState.Loading -> { + LoaderIndicatorScreen(modifier = modifier) + } + + else -> { + val error = filters as FilterSearchViewModel.FilterUiState.Error + Log.d("Exception", error.message) + ErrorLoadingScreen(modifier = modifier) + } + } +} + +@Composable +fun FilterSearchScreenData( + modifier: Modifier, + onNavigateToFilter: () -> Unit, + filters: List +) { + Box( + modifier = modifier + .background(Color.Gray) + .padding(top = 23.dp) + .clip(RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp)) + + ) { + Column( + modifier = modifier + .background(Color.White) + .fillMaxSize() + .padding(horizontal = 12.dp), + ) { + SearchTextField(modifier = modifier) + + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + + } + Box( + modifier = Modifier + .weight(1f) + .padding(vertical = 10.dp) + ) { + LazyColumn { + items( + items = filters.filter { it.id == 1 }.first().filters, + itemContent = { + FilterItem( + modifier = modifier, + filter = it, + { } + ) + } + ) + } + } + ApplyButton(modifier = modifier, onClick = { onNavigateToFilter() }) + } + } +} + + +@Composable +fun SearchTextField(modifier: Modifier) { + var textState by rememberSaveable { mutableStateOf("") } + + TextField( + colors = TextFieldDefaults.textFieldColors( + backgroundColor = Color.White, + textColor = Color.Black, + cursorColor = MaterialTheme.colors.primary, + focusedIndicatorColor = MaterialTheme.colors.primary, + unfocusedIndicatorColor = MaterialTheme.colors.primary, + focusedLabelColor = MaterialTheme.colors.primary, + ), + value = textState, + onValueChange = { textState = it }, + modifier = modifier + .fillMaxWidth() + .height(60.dp), + singleLine = true, + trailingIcon = { + IconTextFieldIcon(text = textState, onClick = { + textState = "" + }) + }, + ) +} + +@Composable +private fun FilterItem( + modifier: Modifier, filter: FilterGroupFull.Filter, onClick: (id: Int) -> Unit +) { + OutlinedButton( + modifier = modifier.fillMaxWidth(), + contentPadding = PaddingValues(0.dp), + border = BorderStroke(1.dp, MaterialTheme.colors.primary), + shape = RoundedCornerShape(8.dp), + onClick = { + onClick(filter.id) + }, + colors = ButtonDefaults.buttonColors( + backgroundColor = if (filter.checked) MaterialTheme.colors.primary else Color.Transparent, + ) + ) { + Row( + horizontalArrangement = Arrangement.Start, + verticalAlignment = Alignment.CenterVertically + ) { + AsyncImage( + model = ImageUrlCreators.createUrl( + CocktailId(filter.id), ImageUrlCreators.Size.SIZE_320 + ), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier + .padding(1.dp) + .clip(RoundedCornerShape(corner = CornerSize(8.dp))) + .size(50.dp), + ) + Spacer(modifier = modifier.width(10.dp)) + Text( + modifier = modifier.weight(1f), + text = filter.name, + style = MaterialTheme.typography.h3, + ) + Box( + modifier = modifier + .height(24.dp) + .widthIn(min = 48.dp) + .padding(end = 8.dp) + .clip(shape = RoundedCornerShape(size = 16.dp)) + .background(MaterialTheme.colors.primary), + contentAlignment = Alignment.Center + ) { + Text( + modifier = modifier.padding(horizontal = 2.dp), + text = filter.cocktailIds.size.toString(), + style = MaterialTheme.typography.h3, + color = Color.White, + ) + } + } + } +} diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchViewModel.kt new file mode 100644 index 0000000..77e6375 --- /dev/null +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchViewModel.kt @@ -0,0 +1,46 @@ +package org.mixdrinks.mixdrinks.features.start.ui.filter.ui.search + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import org.mixdrinks.mixdrinks.features.start.ui.filter.FilterRepository +import org.mixdrinks.mixdrinks.features.start.ui.filter.SelectedFilterStorage +import org.mixdrinks.mixdrinks.features.start.ui.filter.ui.main.FilterItemUiState + +class FilterSearchViewModel( + private val filterRepository: FilterRepository, + private val filterStorage: SelectedFilterStorage +) : ViewModel() { + private val _uiState = MutableStateFlow( + FilterUiState.Loading) + val uiState: StateFlow = _uiState + + + init { + viewModelScope.launch { + filterStorage.selectedFilters.collect { + updateFilters() + } + } + } + + private suspend fun updateFilters() { + _uiState.update { + FilterUiState.Loaded(FilterItemUiState(filterRepository.getFilters())) + } + } + + fun checkedAction(id: Int) { + filterStorage.add(id) + } + + sealed class FilterUiState { + object Loading : FilterUiState() + class Loaded(val itemState: FilterItemUiState) : FilterUiState() + class Error(val message: String) : FilterUiState() + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/CocktailListItem.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/CocktailListItem.kt similarity index 86% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/CocktailListItem.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/CocktailListItem.kt index 80438f9..a46b100 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/CocktailListItem.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/CocktailListItem.kt @@ -1,11 +1,10 @@ -package org.mixdrinks.mixdrinks.features.start.ui +package org.mixdrinks.mixdrinks.features.start.ui.main import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row 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.shape.CornerSize @@ -23,7 +22,7 @@ import androidx.compose.ui.unit.sp import coil.compose.AsyncImage import org.mixdrinks.domain.ImageUrlCreators import org.mixdrinks.dto.CocktailId -import org.mixdrinks.mixdrinks.database.dao.CocktailShort +import org.mixdrinks.mixdrinks.features.data.CocktailShort @Composable fun CocktailListItem(modifier: Modifier, item: CocktailShort, onClickAction: (id: Int) -> Unit) { @@ -51,7 +50,7 @@ private fun ListItemImage(id: Int) { contentScale = ContentScale.Crop, modifier = Modifier .clip(RoundedCornerShape(corner = CornerSize(16.dp))) - .size(200.dp), + .size(100.dp), ) } @@ -59,16 +58,14 @@ private fun ListItemImage(id: Int) { private fun ListItemInfo(modifier: Modifier, item: CocktailShort) { Column( modifier = modifier - .fillMaxWidth(1f) - .height(200.dp), - verticalArrangement = Arrangement.SpaceBetween + .fillMaxWidth(1f), verticalArrangement = Arrangement.SpaceBetween ) { Row( modifier = modifier .padding(start = 10.dp) ) { Text( - text = item.name, + text = item.name, fontWeight = FontWeight.W700, fontSize = 18.sp, color = MaterialTheme.colors.primary, diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/StartScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/StartScreen.kt similarity index 56% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/StartScreen.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/StartScreen.kt index 94aa641..23e7863 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/StartScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/StartScreen.kt @@ -1,4 +1,4 @@ -package org.mixdrinks.mixdrinks.features.start.ui +package org.mixdrinks.mixdrinks.features.start.ui.main import android.util.Log import androidx.compose.foundation.layout.Arrangement @@ -12,32 +12,37 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import org.koin.androidx.compose.koinViewModel -import org.mixdrinks.mixdrinks.database.dao.CocktailShort import org.mixdrinks.mixdrinks.features.common.ui.ErrorLoadingScreen import org.mixdrinks.mixdrinks.features.common.ui.LoaderIndicatorScreen -import org.mixdrinks.mixdrinks.features.header.ui.HeaderScreen +import org.mixdrinks.mixdrinks.features.common.ui.NotFoundScreen +import org.mixdrinks.mixdrinks.features.start.ui.main.header.HeaderScreen @Composable fun StartScreen( modifier: Modifier, onNavigateToDetail: (id: Int) -> Unit, onNavigateToFilter: () -> Unit, + onNavigateToStart: () -> Unit, viewModel: StartScreenViewModel = koinViewModel() ) { val cocktail by viewModel.uiState.collectAsState() - when(cocktail) { + when (cocktail) { is StartScreenViewModel.StartUiState.Loaded -> { val data = (cocktail as StartScreenViewModel.StartUiState.Loaded).itemState StartScreenData( modifier = modifier, - cocktails = data.cocktails, + data = data, onNavigateToDetail = onNavigateToDetail, onNavigateToFilter = onNavigateToFilter, + onNavigateToStart = onNavigateToStart, + viewModel = viewModel ) } + is StartScreenViewModel.StartUiState.Loading -> { LoaderIndicatorScreen(modifier = modifier) } + is StartScreenViewModel.StartUiState.Error -> { val error = cocktail as StartScreenViewModel.StartUiState.Error Log.d("Exception", error.message) @@ -45,28 +50,44 @@ fun StartScreen( } } } + @Suppress("UnusedPrivateMember") @Composable fun StartScreenData( modifier: Modifier, - cocktails: List, + data: StartItemUiState, onNavigateToDetail: (id: Int) -> Unit, onNavigateToFilter: () -> Unit, + onNavigateToStart: () -> Unit, + viewModel: StartScreenViewModel, ) { Column { - HeaderScreen(modifier = modifier, onNavigateToFilter = onNavigateToFilter) - LazyColumn( - contentPadding = PaddingValues(horizontal = 8.dp, vertical = 8.dp), - verticalArrangement = Arrangement.spacedBy(8.dp), - ) { - items( - items = cocktails, - itemContent = { - CocktailListItem(item = it, modifier = modifier, onClickAction = onNavigateToDetail ) - } - ) + HeaderScreen( + modifier = modifier, + onNavigateToFilter = onNavigateToFilter, + viewModel = viewModel, + searchText = data.searchText + ) + if (data.cocktails.isEmpty()) NotFoundScreen( + modifier = modifier, + onNavigateToStart = onNavigateToStart + ) + else { + LazyColumn( + contentPadding = PaddingValues(horizontal = 8.dp, vertical = 8.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + items( + items = data.cocktails, + itemContent = { + CocktailListItem( + item = it, + modifier = modifier, + onClickAction = onNavigateToDetail + ) + } + ) + } } } - } - diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/StartScreenViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/StartScreenViewModel.kt similarity index 63% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/StartScreenViewModel.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/StartScreenViewModel.kt index 82b5023..a0c14d7 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/StartScreenViewModel.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/StartScreenViewModel.kt @@ -1,19 +1,18 @@ -package org.mixdrinks.mixdrinks.features.start.ui +package org.mixdrinks.mixdrinks.features.start.ui.main -import android.content.res.Resources -import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import org.mixdrinks.mixdrinks.database.AppDatabase -import org.mixdrinks.mixdrinks.database.dao.CocktailShort +import org.mixdrinks.mixdrinks.features.data.CocktailShort +import org.mixdrinks.mixdrinks.features.start.StartRepository import java.io.IOException @Suppress("TooGenericExceptionCaught", "MagicNumber") class StartScreenViewModel( - private val roomDatabase: AppDatabase + private val startRepository: StartRepository, ) : ViewModel() { private val _uiState = MutableStateFlow(StartUiState.Loading) val uiState: StateFlow = _uiState @@ -27,8 +26,8 @@ class StartScreenViewModel( viewModelScope.launch { try { - val result = roomDatabase.cocktailDao().getAllShortCocktail() - _uiState.value = StartUiState.Loaded(StartItemUiState(result)) + _uiState.value = + StartUiState.Loaded(StartItemUiState("", startRepository.getCocktails())) } catch (error: IOException) { _uiState.value = StartUiState.Error(error.toString()) } catch (error: Exception) { @@ -36,6 +35,14 @@ class StartScreenViewModel( } } } + + fun searchAction(search: String) { + val result = startRepository.searchCocktail(search) + _uiState.update { + StartUiState.Loaded(StartItemUiState(search, result)) + } + } + sealed class StartUiState { object Loading : StartUiState() class Loaded(val itemState: StartItemUiState) : StartUiState() @@ -44,7 +51,7 @@ class StartScreenViewModel( } data class StartItemUiState( - var cocktails: List + val searchText: String, var cocktails: List ) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/header/ui/HeaderScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/header/HeaderScreen.kt similarity index 72% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/header/ui/HeaderScreen.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/header/HeaderScreen.kt index 64a2477..8e03aa7 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/header/ui/HeaderScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/header/HeaderScreen.kt @@ -1,6 +1,5 @@ -package org.mixdrinks.mixdrinks.features.header.ui +package org.mixdrinks.mixdrinks.features.start.ui.main.header -import android.util.Log import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -21,9 +20,15 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import org.mixdrinks.mixdrinks.R +import org.mixdrinks.mixdrinks.features.start.ui.main.StartScreenViewModel @Composable -fun HeaderScreen(modifier: Modifier, onNavigateToFilter: () -> Unit) { +fun HeaderScreen( + modifier: Modifier, + onNavigateToFilter: () -> Unit, + viewModel: StartScreenViewModel, + searchText: String +) { var isFocusedSearchTextField by remember { mutableStateOf(false) } Column { @@ -35,19 +40,20 @@ fun HeaderScreen(modifier: Modifier, onNavigateToFilter: () -> Unit) { .padding(start = 8.dp, end = 8.dp), verticalAlignment = Alignment.CenterVertically ) { - SearchTextField(modifier = modifier) { isFocusedSearchTextField = it } + SearchTextField( + modifier = modifier, + onFocusChanged = { isFocusedSearchTextField = it }, + searchAction = { viewModel.searchAction(it) }, + searchText = searchText + ) FilterAction(modifier = modifier, onNavigateToFilter = onNavigateToFilter) } - if(isFocusedSearchTextField) - SearchHintContent(modifier = modifier, onClickAction = { Log.d("MyLog", it) }) } } + @Composable private fun FilterAction(modifier: Modifier, onNavigateToFilter: () -> Unit) { - IconButton( - modifier = modifier.height(24.dp), - onClick = { onNavigateToFilter() } - ) { + IconButton(modifier = modifier.height(24.dp), onClick = { onNavigateToFilter() }) { Icon( painter = painterResource(id = R.drawable.baseline_tune_24), tint = Color.White, diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/header/ui/SearchTextField.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/header/SearchTextField.kt similarity index 63% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/header/ui/SearchTextField.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/header/SearchTextField.kt index 93ab998..0b5ed96 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/header/ui/SearchTextField.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/header/SearchTextField.kt @@ -1,4 +1,4 @@ -package org.mixdrinks.mixdrinks.features.header.ui +package org.mixdrinks.mixdrinks.features.start.ui.main.header import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height @@ -6,14 +6,10 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material.Icon -import androidx.compose.material.IconButton import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.material.TextField import androidx.compose.material.TextFieldDefaults -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Close import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -28,16 +24,23 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.unit.dp import org.mixdrinks.mixdrinks.R +import org.mixdrinks.mixdrinks.features.common.ui.widgets.IconTextFieldIcon @Suppress("MagicNumber") @OptIn(ExperimentalComposeUiApi::class) @Composable -fun SearchTextField(modifier: Modifier, onFocusChanged: (isFocused: Boolean) -> Unit) { - var textState by remember { mutableStateOf("") } +fun SearchTextField( + modifier: Modifier, + onFocusChanged: (isFocused: Boolean) -> Unit, + searchAction: (searchText: String) -> Unit, + searchText: String +) { + var textState by remember { mutableStateOf(searchText) } + var isFocused by remember { mutableStateOf(false) } val keyboardController = LocalSoftwareKeyboardController.current - TextField ( + TextField( modifier = modifier .height(50.dp) .fillMaxWidth(if (isFocused) 1.0f else 0.9f) @@ -54,39 +57,25 @@ fun SearchTextField(modifier: Modifier, onFocusChanged: (isFocused: Boolean) -> value = textState, placeholder = { Text(text = stringResource(R.string.search_hint)) }, shape = RoundedCornerShape(10.dp), - onValueChange = { textState = it }, + onValueChange = { + textState = it + searchAction(textState) + }, trailingIcon = { - IconTextFieldIcon( - text = textState, - onClick = { textState = "" } - ) + IconTextFieldIcon(text = textState, onClick = { + textState = "" + searchAction(textState) + }) }, keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), - keyboardActions = KeyboardActions( - onDone = { - keyboardController?.hide() - onFocusChanged(false) - isFocused = false - // send data to server - } - ), + keyboardActions = KeyboardActions(onDone = { + keyboardController?.hide() + onFocusChanged(false) + isFocused = false + }), ) } -@Composable -private fun IconTextFieldIcon(text: String, onClick: () -> Unit) { - if (text.isNotEmpty()) { - IconButton( - onClick = { onClick() } - ) { - Icon( - imageVector = Icons.Outlined.Close, - tint = MaterialTheme.colors.secondary, - contentDescription = null - ) - } - } -} diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 11cded6..fba11b0 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -13,4 +13,6 @@ Фільтри Опис Застосувати + Додати + До фільтра \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 461b233..9628a38 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -16,6 +16,8 @@ Filters Description Застосувати + Add + to filter From b1925a846af5f7779f6cc0d81fd4b38da448a372 Mon Sep 17 00:00:00 2001 From: yura Date: Tue, 23 May 2023 10:48:24 +0300 Subject: [PATCH 02/20] implement filters --- .../mixdrinks/mixdrinks/app/MixDrinksApp.kt | 18 ++++--- .../org/mixdrinks/mixdrinks/app/Routes.kt | 11 +++-- .../mixdrinks/mixdrinks/app/ui/theme/Color.kt | 1 + .../mixdrinks/mixdrinks/app/ui/theme/Theme.kt | 2 +- .../features/data/FilterGroupFull.kt | 2 +- .../ui/cocktail/DetailScreenCocktail.kt | 5 +- .../detail/ui/cocktail/GoodsListItem.kt | 23 +++++---- .../mixdrinks/features/fetcher/Fetcher.kt | 48 ++----------------- .../start/ui/filter/FilterRepository.kt | 14 +++--- .../start/ui/filter/ui/main/FilterScreen.kt | 39 ++++++++++----- .../ui/filter/ui/search/FilterSearchScreen.kt | 42 ++++++++-------- .../filter/ui/search/FilterSearchViewModel.kt | 17 ++++++- 12 files changed, 115 insertions(+), 107 deletions(-) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt b/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt index 8cf88e1..f4b5397 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt @@ -26,7 +26,6 @@ fun MixDrinksApp(modifier: Modifier = Modifier) { navController = navController, startDestination = Routes.start ) { composable(Routes.start) { -// FilterSearchScreen(Modifier) StartScreen(modifier = modifier, onNavigateToDetail = { navController.navigate("${Routes.cocktail}/$it") }, onNavigateToFilter = { navController.navigate(Routes.filter) }, @@ -64,14 +63,19 @@ fun MixDrinksApp(modifier: Modifier = Modifier) { composable(Routes.filter) { FilterScreen(modifier = modifier, onNavigateToStart = { navController.navigate(Routes.start) }, - onNavigateToFilterSearch = { navController.navigate(Routes.filterSearch) }) - } - composable(Routes.filterSearch) { - FilterSearchScreen( - modifier = modifier, - onNavigateToFilter = { navController.navigate(Routes.filter) }, + onNavigateToFilterSearch = { navController.navigate("${Routes.filterSearch}/${it}") } ) } + composable("${Routes.filterSearch}/{${Routes.groupFilterId}}") { backStackEntry -> + val groupId = backStackEntry.arguments?.getString(Routes.groupFilterId) + groupId?.toInt()?.let { + FilterSearchScreen( + modifier = modifier, + groupId = it, + onNavigateToFilter = { navController.navigate(Routes.filter) }, + ) + } + } composable(Routes.notFound) { NotFoundScreen(modifier = modifier, onNavigateToStart = { navController.navigate(Routes.start) }) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/app/Routes.kt b/app/src/main/java/org/mixdrinks/mixdrinks/app/Routes.kt index 092cf1b..5870185 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/app/Routes.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/app/Routes.kt @@ -3,16 +3,19 @@ package org.mixdrinks.mixdrinks.app object Routes { const val start = "start" const val filter = "filter" - const val filterSearch = "filter_search" const val notFound = "not_found" const val cocktail = "cocktail" - const val cocktailId = "cocktailId" + const val cocktailId = "cocktail_id" const val tool = "tool" - const val toolId = "toolId" + const val toolId = "tool_id" const val good = "good" - const val goodId = "goodId" + const val goodId = "good_id" + + const val filterSearch = "filter_search" + const val groupFilterId = "group_filter_id" + } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/app/ui/theme/Color.kt b/app/src/main/java/org/mixdrinks/mixdrinks/app/ui/theme/Color.kt index d74ef1c..005d8b4 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/app/ui/theme/Color.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/app/ui/theme/Color.kt @@ -7,4 +7,5 @@ import androidx.compose.ui.graphics.Color val Green700 = Color(0XFF2B4718) val Green = Color(0XFF4E6640) val Black = Color(0XFF181818) +val GreenAlfa = Color(0x322B4718) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/app/ui/theme/Theme.kt b/app/src/main/java/org/mixdrinks/mixdrinks/app/ui/theme/Theme.kt index bc6eb25..72a25a1 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/app/ui/theme/Theme.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/app/ui/theme/Theme.kt @@ -15,7 +15,7 @@ private val DarkColorPalette = darkColors( private val LightColorPalette = lightColors( primary = Green700, primaryVariant = Green, - secondary = Black + secondary = Black, /* Other default colors to override background = Color.White, diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/FilterGroupFull.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/FilterGroupFull.kt index 15ee02c..ac52230 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/FilterGroupFull.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/FilterGroupFull.kt @@ -13,7 +13,7 @@ data class FilterGroupFull( val name: String, val enabled: Boolean, val checked: Boolean, - val cocktailIds: Set + val cocktailIds: List ) } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt index 2532a37..beea135 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt @@ -135,6 +135,7 @@ fun DetailsScreenData( modifier = modifier, cocktailName = data.cocktail.name, cocktailTools = data.cocktail.tools, + glassware = data.cocktail.glassware, onClick = onNavigateToDetailTool ) } @@ -205,6 +206,7 @@ fun CocktailNeedToolsContent( modifier: Modifier, cocktailName: String, cocktailTools: List, + glassware: CocktailFull.Glassware, onClick: (id: Int) -> Unit ) { Row( @@ -221,7 +223,8 @@ fun CocktailNeedToolsContent( ToolsListItem( modifier = modifier, tools = cocktailTools, - onCLick = onClick + glassware = glassware, + onClick = onClick ) } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt index 0b3fed7..09cd1e7 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt @@ -31,12 +31,12 @@ import org.mixdrinks.mixdrinks.features.data.CocktailFull fun GoodsListItem( modifier: Modifier, data: DetailItemUiState, - onClick: (id :Int) -> Unit + onClick: (id: Int) -> Unit ) { LazyHorizontalGrid( rows = GridCells.Fixed(1), horizontalArrangement = Arrangement.spacedBy(8.dp), - modifier = modifier.height(240.dp) + modifier = modifier.height(200.dp) ) { items(data.cocktail.goods) { item -> Card( @@ -48,7 +48,8 @@ fun GoodsListItem( .fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally ) { - ImageItem(modifier = modifier, + ImageItem( + modifier = modifier, ImageUrlCreators.createUrl(item.id, ImageUrlCreators.Size.SIZE_320) ) Row( @@ -78,16 +79,21 @@ fun GoodsListItem( } @Composable -fun ToolsListItem(modifier: Modifier, tools: List, onCLick: (id: Int) -> Unit) { +fun ToolsListItem( + modifier: Modifier, + tools: List, + glassware: CocktailFull.Glassware, + onClick: (id: Int) -> Unit +) { LazyHorizontalGrid( rows = GridCells.Fixed(1), horizontalArrangement = Arrangement.spacedBy(8.dp), - modifier = modifier.height(220.dp) + modifier = modifier.height(180.dp) ) { items(tools) { item -> Card( modifier = modifier - .clickable { onCLick(item.id.id) }, + .clickable { onClick(item.id.id) }, ) { Column( modifier = modifier @@ -117,15 +123,16 @@ fun ToolsListItem(modifier: Modifier, tools: List, onCLick: ( } } + @Composable -fun ImageItem(modifier:Modifier, url: String) { +fun ImageItem(modifier: Modifier, url: String) { AsyncImage( modifier = modifier .border( BorderStroke(2.dp, MaterialTheme.colors.primary), shape = RoundedCornerShape(16.dp), ) - .size(190.dp) + .size(150.dp) .padding(5.dp), model = url, contentDescription = null, diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/fetcher/Fetcher.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/fetcher/Fetcher.kt index 80877e0..061dae7 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/fetcher/Fetcher.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/fetcher/Fetcher.kt @@ -1,6 +1,5 @@ package org.mixdrinks.mixdrinks.features.fetcher -import android.util.Log import androidx.room.Transaction import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch @@ -35,15 +34,11 @@ class Fetcher( private val scope = MainScope() init { - Log.d("init", "init") scope.launch { - if (roomDatabase.cocktailDao().getAll().isEmpty()) { - insertToDataBase(cocktailProvider.getAllCocktails()) - } - //insertToDataBase(cocktailProvider.getAllCocktails()) - - // Log.d("init", "launch") - + /* if (roomDatabase.cocktailDao().getAll().isEmpty()) { + insertToDataBase(cocktailProvider.getAllCocktails()) + }*/ + insertToDataBase(cocktailProvider.getAllCocktails()) } } @@ -160,7 +155,7 @@ class Fetcher( } } - // @Transaction + @Transaction private suspend fun insertAllFilters(filterGroup: List) { filterGroup.map { item -> roomDatabase.filterGroupDao().addFilterGroup( @@ -188,38 +183,5 @@ class Fetcher( ) } } - -// roomDatabase.filterGroupDao().addAllFilterGroups( -// filterGroup.map { -// FilterGroup( -// id = it.id.value, -// name = it.name, -// selectionType = it.selectionType -// ) -// } -// ) -// filterGroup.map { -// roomDatabase.filterGroupDao().addAllFilters( -// it.filters.map { filter -> -// Filters( -// filterId = filter.id.value, -// filterGroupId = it.id.value, -// name = filter.name -// ) -// } -// ) -// } -// filterGroup.map { -// it.filters.map { filter -> -// roomDatabase.filterGroupDao().addAllFilterWithCocktailId( -// filter.cocktailIds.map { cocktailId -> -// FilterWithCocktailIds( -// filterId = filter.id.value, -// cocktailId = cocktailId.id -// ) -// } -// ) -// } -// } } } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/FilterRepository.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/FilterRepository.kt index fae8e6e..184e3c7 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/FilterRepository.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/FilterRepository.kt @@ -11,20 +11,20 @@ class FilterRepository( ) { private var filters: List = listOf() - suspend fun getFilters(): List { + suspend fun getFilters(groupId: Int? = null): List { if (filters.isEmpty()) { filters = getFiltersFromDatabase() } - return filters.map { + return filters.map { item -> FilterGroupFull( - id = it.filterGroup.id, - name = it.filterGroup.name, - selectionType = it.filterGroup.selectionType, - filters = it.filters.map { filter -> + id = item.filterGroup.id, + name = item.filterGroup.name, + selectionType = item.filterGroup.selectionType, + filters = item.filters.map { filter -> FilterGroupFull.Filter( id = filter.filterId, name = filter.name, - cocktailIds = setOf(), + cocktailIds = item.cocktailIds.filter{ it.filterId == filter.filterId }.map { it.cocktailId }, checked = (filterStorage.selectedFilters.value.find { f -> f == filter.filterId } != null), enabled = true ) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/main/FilterScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/main/FilterScreen.kt index 1c25bfb..916ee6f 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/main/FilterScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/main/FilterScreen.kt @@ -41,10 +41,10 @@ fun FilterScreen( modifier: Modifier, viewModel: FilterScreenViewModel = koinViewModel(), onNavigateToStart: () -> Unit, - onNavigateToFilterSearch: () -> Unit + onNavigateToFilterSearch: (groupId: Int) -> Unit ) { val filters by viewModel.uiState.collectAsState() - when(filters) { + when (filters) { is FilterScreenViewModel.FilterUiState.Loaded -> { val data = (filters as FilterScreenViewModel.FilterUiState.Loaded).itemState FilterScreenData( @@ -55,9 +55,11 @@ fun FilterScreen( onClickButtonAddAction = onNavigateToFilterSearch ) } + is FilterScreenViewModel.FilterUiState.Loading -> { LoaderIndicatorScreen(modifier = modifier) } + else -> { val error = filters as FilterScreenViewModel.FilterUiState.Error Log.d("Exception", error.message) @@ -72,7 +74,7 @@ fun FilterScreenData( filters: List, viewModel: FilterScreenViewModel, onClickButtonApplyAction: () -> Unit, - onClickButtonAddAction: () -> Unit + onClickButtonAddAction: (groupId: Int) -> Unit ) { Column( modifier = modifier @@ -89,7 +91,7 @@ fun FilterScreenData( Text( modifier = modifier, text = stringResource(id = R.string.filter), - style = MaterialTheme.typography.h1.copy(fontWeight = FontWeight.W700,), + style = MaterialTheme.typography.h1.copy(fontWeight = FontWeight.W700), ) OutlinedButton( onClick = { viewModel.clearFilters() } @@ -114,17 +116,24 @@ fun FilterScreenData( text = it.name, style = MaterialTheme.typography.h2 ) - when(true) { + when (true) { (it.filters.size < 10) -> { it.filters.forEach { item -> - FilterItem(item, onClick = {id -> viewModel.checkedAction(id) }) + FilterItem( + item, + onClick = { id -> viewModel.checkedAction(id) }) } } else -> { - it.filters.filter { it.checked }.forEach {item -> - FilterItem(item, onClick = {id -> viewModel.checkedAction(id) }) + it.filters.filter { it.checked }.forEach { item -> + FilterItem( + item, + onClick = { id -> viewModel.checkedAction(id) }) } - AddButton(modifier = modifier, text = it.name, onClick = onClickButtonAddAction) + AddButton( + modifier = modifier, + text = it.name, + onClick = { onClickButtonAddAction(it.id) }) } } } @@ -144,13 +153,13 @@ private fun FilterItem(item: FilterGroupFull.Filter, onClick: (id: Int) -> Unit) onClick(item.id) }, colors = ButtonDefaults.buttonColors( - backgroundColor = if(item.checked) MaterialTheme.colors.primary else Color.Transparent, + backgroundColor = if (item.checked) MaterialTheme.colors.primary else Color.Transparent, ) ) { Text( text = item.name, style = MaterialTheme.typography.h4, - color = if(item.checked) Color.White else MaterialTheme.colors.primary + color = if (item.checked) Color.White else MaterialTheme.colors.primary ) } } @@ -189,7 +198,7 @@ fun AddButton(modifier: Modifier, text: String, onClick: () -> Unit) { .fillMaxWidth() ) { OutlinedButton( - onClick = { onClick() }, + onClick = { onClick() }, border = BorderStroke(1.dp, MaterialTheme.colors.primary), shape = RoundedCornerShape(18.dp), modifier = Modifier @@ -199,7 +208,11 @@ fun AddButton(modifier: Modifier, text: String, onClick: () -> Unit) { .align(Alignment.Center) ) { Text( - text = "${stringResource(id = R.string.add)} ${text.lowercase(Locale.ROOT)} ${stringResource(id = R.string.to_filter).lowercase()}", + text = "${stringResource(id = R.string.add)} ${text.lowercase(Locale.ROOT)} ${ + stringResource( + id = R.string.to_filter + ).lowercase() + }", style = MaterialTheme.typography.h5, color = Color.Black ) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchScreen.kt index 97b1c51..f6985e6 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchScreen.kt @@ -42,6 +42,7 @@ import coil.compose.AsyncImage import org.koin.androidx.compose.koinViewModel import org.mixdrinks.domain.ImageUrlCreators import org.mixdrinks.dto.CocktailId +import org.mixdrinks.mixdrinks.app.ui.theme.GreenAlfa import org.mixdrinks.mixdrinks.features.common.ui.ErrorLoadingScreen import org.mixdrinks.mixdrinks.features.common.ui.LoaderIndicatorScreen import org.mixdrinks.mixdrinks.features.common.ui.widgets.IconTextFieldIcon @@ -52,8 +53,8 @@ import org.mixdrinks.mixdrinks.features.start.ui.filter.ui.main.ApplyButton fun FilterSearchScreen( modifier: Modifier, viewModel: FilterSearchViewModel = koinViewModel(), + groupId: Int, onNavigateToFilter: () -> Unit - ) { val filters by viewModel.uiState.collectAsState() when (filters) { @@ -61,8 +62,9 @@ fun FilterSearchScreen( val data = (filters as FilterSearchViewModel.FilterUiState.Loaded).itemState FilterSearchScreenData( modifier = modifier, - filters = data.filters, - onNavigateToFilter = onNavigateToFilter + filters = data.filters.first { it.id == groupId }.filters, + onNavigateToFilter = onNavigateToFilter, + viewModel = viewModel ) } @@ -82,7 +84,8 @@ fun FilterSearchScreen( fun FilterSearchScreenData( modifier: Modifier, onNavigateToFilter: () -> Unit, - filters: List + filters: List, + viewModel: FilterSearchViewModel ) { Box( modifier = modifier @@ -112,15 +115,13 @@ fun FilterSearchScreenData( ) { LazyColumn { items( - items = filters.filter { it.id == 1 }.first().filters, - itemContent = { + items = filters, + itemContent = { filters -> FilterItem( - modifier = modifier, - filter = it, - { } + modifier = modifier, filter = filters, + onClick = { viewModel.checkedAction(it) } ) - } - ) + }) } } ApplyButton(modifier = modifier, onClick = { onNavigateToFilter() }) @@ -128,7 +129,6 @@ fun FilterSearchScreenData( } } - @Composable fun SearchTextField(modifier: Modifier) { var textState by rememberSaveable { mutableStateOf("") } @@ -143,10 +143,12 @@ fun SearchTextField(modifier: Modifier) { focusedLabelColor = MaterialTheme.colors.primary, ), value = textState, - onValueChange = { textState = it }, + onValueChange = { + textState = it + }, modifier = modifier .fillMaxWidth() - .height(60.dp), + .height(50.dp), singleLine = true, trailingIcon = { IconTextFieldIcon(text = textState, onClick = { @@ -161,7 +163,9 @@ private fun FilterItem( modifier: Modifier, filter: FilterGroupFull.Filter, onClick: (id: Int) -> Unit ) { OutlinedButton( - modifier = modifier.fillMaxWidth(), + modifier = modifier + .fillMaxWidth() + .padding(vertical = 5.dp), contentPadding = PaddingValues(0.dp), border = BorderStroke(1.dp, MaterialTheme.colors.primary), shape = RoundedCornerShape(8.dp), @@ -169,7 +173,7 @@ private fun FilterItem( onClick(filter.id) }, colors = ButtonDefaults.buttonColors( - backgroundColor = if (filter.checked) MaterialTheme.colors.primary else Color.Transparent, + backgroundColor = if (filter.checked) GreenAlfa else Color.Transparent, ) ) { Row( @@ -183,9 +187,8 @@ private fun FilterItem( contentDescription = null, contentScale = ContentScale.Crop, modifier = Modifier - .padding(1.dp) .clip(RoundedCornerShape(corner = CornerSize(8.dp))) - .size(50.dp), + .size(70.dp), ) Spacer(modifier = modifier.width(10.dp)) Text( @@ -199,8 +202,7 @@ private fun FilterItem( .widthIn(min = 48.dp) .padding(end = 8.dp) .clip(shape = RoundedCornerShape(size = 16.dp)) - .background(MaterialTheme.colors.primary), - contentAlignment = Alignment.Center + .background(MaterialTheme.colors.primary), contentAlignment = Alignment.Center ) { Text( modifier = modifier.padding(horizontal = 2.dp), diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchViewModel.kt index 77e6375..1d279e5 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchViewModel.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchViewModel.kt @@ -6,6 +6,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import org.mixdrinks.mixdrinks.features.data.FilterGroupFull import org.mixdrinks.mixdrinks.features.start.ui.filter.FilterRepository import org.mixdrinks.mixdrinks.features.start.ui.filter.SelectedFilterStorage import org.mixdrinks.mixdrinks.features.start.ui.filter.ui.main.FilterItemUiState @@ -14,13 +15,18 @@ class FilterSearchViewModel( private val filterRepository: FilterRepository, private val filterStorage: SelectedFilterStorage ) : ViewModel() { + private lateinit var filtersByGroup: List + private val _uiState = MutableStateFlow( - FilterUiState.Loading) + FilterUiState.Loading + ) val uiState: StateFlow = _uiState - init { viewModelScope.launch { + val data = filterRepository.getFilters() + filtersByGroup = data.first { it.id == 1 }.filters + filterStorage.selectedFilters.collect { updateFilters() } @@ -37,6 +43,13 @@ class FilterSearchViewModel( filterStorage.add(id) } +// fun searchAction(search: String) { +// val result = filterRepository.searchCocktail(search) +// _uiState.update { +// StartScreenViewModel.StartUiState.Loaded(StartItemUiState(search, result)) +// } +// } + sealed class FilterUiState { object Loading : FilterUiState() class Loaded(val itemState: FilterItemUiState) : FilterUiState() From 579d5c4b8b4ad73df44094c566d8801eb08d3c85 Mon Sep 17 00:00:00 2001 From: yura Date: Tue, 23 May 2023 11:01:43 +0300 Subject: [PATCH 03/20] code refactoring --- app/src/main/java/org/mixdrinks/mixdrinks/App.kt | 10 +++++----- .../java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt | 6 +++--- .../ui/cocktail/DetailScreenCocktailViewModel.kt | 2 +- .../mixdrinks/features/start/StartRepository.kt | 4 ++-- .../features/start/{ui => }/filter/FilterRepository.kt | 7 ++++--- .../start/{ui => }/filter/SelectedFilterStore.kt | 2 +- .../start/{ui => }/filter/ui/main/FilterScreen.kt | 2 +- .../{ui => }/filter/ui/main/FilterScreenViewModel.kt | 6 +++--- .../{ui => }/filter/ui/search/FilterSearchScreen.kt | 4 ++-- .../{ui => }/filter/ui/search/FilterSearchViewModel.kt | 8 ++++---- .../start/{ui/main => main/ui}/CocktailListItem.kt | 2 +- .../features/start/{ui/main => main/ui}/StartScreen.kt | 4 ++-- .../start/{ui/main => main/ui}/StartScreenViewModel.kt | 2 +- .../start/{ui/main => main/ui}/header/HeaderScreen.kt | 4 ++-- .../{ui/main => main/ui}/header/SearchTextField.kt | 2 +- 15 files changed, 33 insertions(+), 32 deletions(-) rename app/src/main/java/org/mixdrinks/mixdrinks/features/start/{ui => }/filter/FilterRepository.kt (91%) rename app/src/main/java/org/mixdrinks/mixdrinks/features/start/{ui => }/filter/SelectedFilterStore.kt (93%) rename app/src/main/java/org/mixdrinks/mixdrinks/features/start/{ui => }/filter/ui/main/FilterScreen.kt (99%) rename app/src/main/java/org/mixdrinks/mixdrinks/features/start/{ui => }/filter/ui/main/FilterScreenViewModel.kt (89%) rename app/src/main/java/org/mixdrinks/mixdrinks/features/start/{ui => }/filter/ui/search/FilterSearchScreen.kt (98%) rename app/src/main/java/org/mixdrinks/mixdrinks/features/start/{ui => }/filter/ui/search/FilterSearchViewModel.kt (84%) rename app/src/main/java/org/mixdrinks/mixdrinks/features/start/{ui/main => main/ui}/CocktailListItem.kt (97%) rename app/src/main/java/org/mixdrinks/mixdrinks/features/start/{ui/main => main/ui}/StartScreen.kt (96%) rename app/src/main/java/org/mixdrinks/mixdrinks/features/start/{ui/main => main/ui}/StartScreenViewModel.kt (96%) rename app/src/main/java/org/mixdrinks/mixdrinks/features/start/{ui/main => main/ui}/header/HeaderScreen.kt (94%) rename app/src/main/java/org/mixdrinks/mixdrinks/features/start/{ui/main => main/ui}/header/SearchTextField.kt (97%) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/App.kt b/app/src/main/java/org/mixdrinks/mixdrinks/App.kt index 602df20..c8a72a8 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/App.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/App.kt @@ -15,11 +15,11 @@ import org.mixdrinks.mixdrinks.features.detail.ui.good.DetailScreenGoodViewModel import org.mixdrinks.mixdrinks.features.detail.ui.tool.DetailScreenToolViewModel import org.mixdrinks.mixdrinks.features.fetcher.Fetcher import org.mixdrinks.mixdrinks.features.start.StartRepository -import org.mixdrinks.mixdrinks.features.start.ui.filter.ui.main.FilterScreenViewModel -import org.mixdrinks.mixdrinks.features.start.ui.filter.SelectedFilterStorage -import org.mixdrinks.mixdrinks.features.start.ui.main.StartScreenViewModel -import org.mixdrinks.mixdrinks.features.start.ui.filter.FilterRepository -import org.mixdrinks.mixdrinks.features.start.ui.filter.ui.search.FilterSearchViewModel +import org.mixdrinks.mixdrinks.features.start.filter.ui.main.FilterScreenViewModel +import org.mixdrinks.mixdrinks.features.start.filter.SelectedFilterStorage +import org.mixdrinks.mixdrinks.features.start.main.ui.StartScreenViewModel +import org.mixdrinks.mixdrinks.features.start.filter.FilterRepository +import org.mixdrinks.mixdrinks.features.start.filter.ui.search.FilterSearchViewModel class App : Application() { override fun onCreate() { diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt b/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt index f4b5397..63ed0b3 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt @@ -12,9 +12,9 @@ import org.mixdrinks.mixdrinks.features.detail.ui.cocktail.DetailScreen import org.mixdrinks.mixdrinks.features.detail.ui.good.DetailScreenGood import org.mixdrinks.mixdrinks.features.detail.ui.tool.DetailScreenTool import org.mixdrinks.mixdrinks.features.fetcher.Fetcher -import org.mixdrinks.mixdrinks.features.start.ui.main.StartScreen -import org.mixdrinks.mixdrinks.features.start.ui.filter.ui.main.FilterScreen -import org.mixdrinks.mixdrinks.features.start.ui.filter.ui.search.FilterSearchScreen +import org.mixdrinks.mixdrinks.features.start.main.ui.StartScreen +import org.mixdrinks.mixdrinks.features.start.filter.ui.main.FilterScreen +import org.mixdrinks.mixdrinks.features.start.filter.ui.search.FilterSearchScreen @Suppress("LongMethod") @Composable diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktailViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktailViewModel.kt index f7f0201..1f94930 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktailViewModel.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktailViewModel.kt @@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import org.mixdrinks.mixdrinks.database.AppDatabase import org.mixdrinks.mixdrinks.features.data.CocktailFull -import org.mixdrinks.mixdrinks.features.start.ui.filter.SelectedFilterStorage +import org.mixdrinks.mixdrinks.features.start.filter.SelectedFilterStorage import java.io.IOException @Suppress("TooGenericExceptionCaught") diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/StartRepository.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/StartRepository.kt index 9dad20a..b70cefc 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/StartRepository.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/StartRepository.kt @@ -1,9 +1,9 @@ -package org.mixdrinks.mixdrinks.features.start; +package org.mixdrinks.mixdrinks.features.start import org.mixdrinks.mixdrinks.database.AppDatabase import org.mixdrinks.mixdrinks.database.dao.CocktailsWithFilters import org.mixdrinks.mixdrinks.features.data.CocktailShort -import org.mixdrinks.mixdrinks.features.start.ui.filter.SelectedFilterStorage +import org.mixdrinks.mixdrinks.features.start.filter.SelectedFilterStorage class StartRepository( diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/FilterRepository.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/FilterRepository.kt similarity index 91% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/FilterRepository.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/FilterRepository.kt index 184e3c7..5d1a220 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/FilterRepository.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/FilterRepository.kt @@ -1,4 +1,4 @@ -package org.mixdrinks.mixdrinks.features.start.ui.filter +package org.mixdrinks.mixdrinks.features.start.filter import org.mixdrinks.mixdrinks.database.AppDatabase import org.mixdrinks.mixdrinks.database.dao.FilterGroups @@ -11,7 +11,7 @@ class FilterRepository( ) { private var filters: List = listOf() - suspend fun getFilters(groupId: Int? = null): List { + suspend fun getFilters(): List { if (filters.isEmpty()) { filters = getFiltersFromDatabase() } @@ -37,4 +37,5 @@ class FilterRepository( return roomDatabase.filterGroupDao().getAllFilterGroups() } -} \ No newline at end of file +} + diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/SelectedFilterStore.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/SelectedFilterStore.kt similarity index 93% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/SelectedFilterStore.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/SelectedFilterStore.kt index 7a10a7d..3c3c956 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/SelectedFilterStore.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/SelectedFilterStore.kt @@ -1,4 +1,4 @@ -package org.mixdrinks.mixdrinks.features.start.ui.filter +package org.mixdrinks.mixdrinks.features.start.filter import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/main/FilterScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt similarity index 99% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/main/FilterScreen.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt index 916ee6f..1b1d25b 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/main/FilterScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt @@ -1,4 +1,4 @@ -package org.mixdrinks.mixdrinks.features.start.ui.filter.ui.main +package org.mixdrinks.mixdrinks.features.start.filter.ui.main import android.util.Log import androidx.compose.foundation.BorderStroke diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/main/FilterScreenViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreenViewModel.kt similarity index 89% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/main/FilterScreenViewModel.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreenViewModel.kt index d576eba..9f67b43 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/main/FilterScreenViewModel.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreenViewModel.kt @@ -1,4 +1,4 @@ -package org.mixdrinks.mixdrinks.features.start.ui.filter.ui.main +package org.mixdrinks.mixdrinks.features.start.filter.ui.main import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -7,8 +7,8 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.mixdrinks.mixdrinks.features.data.FilterGroupFull -import org.mixdrinks.mixdrinks.features.start.ui.filter.FilterRepository -import org.mixdrinks.mixdrinks.features.start.ui.filter.SelectedFilterStorage +import org.mixdrinks.mixdrinks.features.start.filter.FilterRepository +import org.mixdrinks.mixdrinks.features.start.filter.SelectedFilterStorage import java.io.IOException @Suppress("TooGenericExceptionCaught") diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchScreen.kt similarity index 98% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchScreen.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchScreen.kt index f6985e6..af2c70c 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchScreen.kt @@ -1,4 +1,4 @@ -package org.mixdrinks.mixdrinks.features.start.ui.filter.ui.search +package org.mixdrinks.mixdrinks.features.start.filter.ui.search import android.util.Log import androidx.compose.foundation.BorderStroke @@ -47,7 +47,7 @@ import org.mixdrinks.mixdrinks.features.common.ui.ErrorLoadingScreen import org.mixdrinks.mixdrinks.features.common.ui.LoaderIndicatorScreen import org.mixdrinks.mixdrinks.features.common.ui.widgets.IconTextFieldIcon import org.mixdrinks.mixdrinks.features.data.FilterGroupFull -import org.mixdrinks.mixdrinks.features.start.ui.filter.ui.main.ApplyButton +import org.mixdrinks.mixdrinks.features.start.filter.ui.main.ApplyButton @Composable fun FilterSearchScreen( diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchViewModel.kt similarity index 84% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchViewModel.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchViewModel.kt index 1d279e5..f58ab5f 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/filter/ui/search/FilterSearchViewModel.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchViewModel.kt @@ -1,4 +1,4 @@ -package org.mixdrinks.mixdrinks.features.start.ui.filter.ui.search +package org.mixdrinks.mixdrinks.features.start.filter.ui.search import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -7,9 +7,9 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.mixdrinks.mixdrinks.features.data.FilterGroupFull -import org.mixdrinks.mixdrinks.features.start.ui.filter.FilterRepository -import org.mixdrinks.mixdrinks.features.start.ui.filter.SelectedFilterStorage -import org.mixdrinks.mixdrinks.features.start.ui.filter.ui.main.FilterItemUiState +import org.mixdrinks.mixdrinks.features.start.filter.FilterRepository +import org.mixdrinks.mixdrinks.features.start.filter.SelectedFilterStorage +import org.mixdrinks.mixdrinks.features.start.filter.ui.main.FilterItemUiState class FilterSearchViewModel( private val filterRepository: FilterRepository, diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/CocktailListItem.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/CocktailListItem.kt similarity index 97% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/CocktailListItem.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/CocktailListItem.kt index a46b100..130b10c 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/CocktailListItem.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/CocktailListItem.kt @@ -1,4 +1,4 @@ -package org.mixdrinks.mixdrinks.features.start.ui.main +package org.mixdrinks.mixdrinks.features.start.main.ui import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/StartScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreen.kt similarity index 96% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/StartScreen.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreen.kt index 23e7863..fd18829 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/StartScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreen.kt @@ -1,4 +1,4 @@ -package org.mixdrinks.mixdrinks.features.start.ui.main +package org.mixdrinks.mixdrinks.features.start.main.ui import android.util.Log import androidx.compose.foundation.layout.Arrangement @@ -15,7 +15,7 @@ import org.koin.androidx.compose.koinViewModel import org.mixdrinks.mixdrinks.features.common.ui.ErrorLoadingScreen import org.mixdrinks.mixdrinks.features.common.ui.LoaderIndicatorScreen import org.mixdrinks.mixdrinks.features.common.ui.NotFoundScreen -import org.mixdrinks.mixdrinks.features.start.ui.main.header.HeaderScreen +import org.mixdrinks.mixdrinks.features.start.main.ui.header.HeaderScreen @Composable fun StartScreen( diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/StartScreenViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreenViewModel.kt similarity index 96% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/StartScreenViewModel.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreenViewModel.kt index a0c14d7..9825b35 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/StartScreenViewModel.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreenViewModel.kt @@ -1,4 +1,4 @@ -package org.mixdrinks.mixdrinks.features.start.ui.main +package org.mixdrinks.mixdrinks.features.start.main.ui import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/header/HeaderScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/header/HeaderScreen.kt similarity index 94% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/header/HeaderScreen.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/header/HeaderScreen.kt index 8e03aa7..dac85a0 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/header/HeaderScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/header/HeaderScreen.kt @@ -1,4 +1,4 @@ -package org.mixdrinks.mixdrinks.features.start.ui.main.header +package org.mixdrinks.mixdrinks.features.start.main.ui.header import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column @@ -20,7 +20,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import org.mixdrinks.mixdrinks.R -import org.mixdrinks.mixdrinks.features.start.ui.main.StartScreenViewModel +import org.mixdrinks.mixdrinks.features.start.main.ui.StartScreenViewModel @Composable fun HeaderScreen( diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/header/SearchTextField.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/header/SearchTextField.kt similarity index 97% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/header/SearchTextField.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/header/SearchTextField.kt index 0b5ed96..366e7d0 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/ui/main/header/SearchTextField.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/header/SearchTextField.kt @@ -1,4 +1,4 @@ -package org.mixdrinks.mixdrinks.features.start.ui.main.header +package org.mixdrinks.mixdrinks.features.start.main.ui.header import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height From 9a905af4ced031bdcfcbc1311c121a401909d838 Mon Sep 17 00:00:00 2001 From: yura Date: Tue, 23 May 2023 11:11:25 +0300 Subject: [PATCH 04/20] code refactoring --- .../mixdrinks/features/common/ui/widgets/IconTextFieldIcon.kt | 3 ++- .../{SelectedFilterStore.kt => SelectedFilterStorage.kt} | 0 .../mixdrinks/features/start/filter/ui/main/FilterScreen.kt | 2 ++ .../mixdrinks/mixdrinks/features/start/main/ui/StartScreen.kt | 2 -- 4 files changed, 4 insertions(+), 3 deletions(-) rename app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/{SelectedFilterStore.kt => SelectedFilterStorage.kt} (100%) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/common/ui/widgets/IconTextFieldIcon.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/common/ui/widgets/IconTextFieldIcon.kt index fa5dc14..890a655 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/common/ui/widgets/IconTextFieldIcon.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/common/ui/widgets/IconTextFieldIcon.kt @@ -19,4 +19,5 @@ fun IconTextFieldIcon(text: String, onClick: () -> Unit) { ) } } -} \ No newline at end of file +} + diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/SelectedFilterStore.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/SelectedFilterStorage.kt similarity index 100% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/SelectedFilterStore.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/SelectedFilterStorage.kt diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt index 1b1d25b..5a6db67 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt @@ -36,6 +36,7 @@ import org.mixdrinks.mixdrinks.features.common.ui.LoaderIndicatorScreen import org.mixdrinks.mixdrinks.features.data.FilterGroupFull import java.util.Locale +@Suppress("LongMethod") @Composable fun FilterScreen( modifier: Modifier, @@ -68,6 +69,7 @@ fun FilterScreen( } } + @Composable fun FilterScreenData( modifier: Modifier, diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreen.kt index fd18829..b533381 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreen.kt @@ -50,8 +50,6 @@ fun StartScreen( } } } - -@Suppress("UnusedPrivateMember") @Composable fun StartScreenData( modifier: Modifier, From 127588baff429ae6fc82e727d5d8ac28ae018327 Mon Sep 17 00:00:00 2001 From: yura Date: Tue, 23 May 2023 11:16:58 +0300 Subject: [PATCH 05/20] code refactoring --- .../features/detail/ui/cocktail/GoodsListItem.kt | 1 + .../features/start/filter/ui/main/FilterScreen.kt | 6 +++--- .../start/filter/ui/search/FilterSearchViewModel.kt | 11 ++--------- .../mixdrinks/features/start/main/ui/StartScreen.kt | 1 + 4 files changed, 7 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt index 09cd1e7..54eada6 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt @@ -78,6 +78,7 @@ fun GoodsListItem( } } +@Suppress("UnusedPrivateMember") @Composable fun ToolsListItem( modifier: Modifier, diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt index 5a6db67..dcbe425 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt @@ -36,7 +36,6 @@ import org.mixdrinks.mixdrinks.features.common.ui.LoaderIndicatorScreen import org.mixdrinks.mixdrinks.features.data.FilterGroupFull import java.util.Locale -@Suppress("LongMethod") @Composable fun FilterScreen( modifier: Modifier, @@ -69,7 +68,7 @@ fun FilterScreen( } } - +@Suppress("LongMethod", "MagicNumber") @Composable fun FilterScreenData( modifier: Modifier, @@ -113,7 +112,7 @@ fun FilterScreenData( LazyColumn { items( items = filters.sortedBy { it.filters.size }, - itemContent = { it -> + itemContent = { Text( text = it.name, style = MaterialTheme.typography.h2 @@ -126,6 +125,7 @@ fun FilterScreenData( onClick = { id -> viewModel.checkedAction(id) }) } } + else -> { it.filters.filter { it.checked }.forEach { item -> FilterItem( diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchViewModel.kt index f58ab5f..639f323 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchViewModel.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchViewModel.kt @@ -42,18 +42,11 @@ class FilterSearchViewModel( fun checkedAction(id: Int) { filterStorage.add(id) } - -// fun searchAction(search: String) { -// val result = filterRepository.searchCocktail(search) -// _uiState.update { -// StartScreenViewModel.StartUiState.Loaded(StartItemUiState(search, result)) -// } -// } - sealed class FilterUiState { object Loading : FilterUiState() class Loaded(val itemState: FilterItemUiState) : FilterUiState() class Error(val message: String) : FilterUiState() } -} \ No newline at end of file +} + diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreen.kt index b533381..b42581b 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreen.kt @@ -50,6 +50,7 @@ fun StartScreen( } } } +@Suppress("LongParameterList") @Composable fun StartScreenData( modifier: Modifier, From 533eb32ed58f98f19c339178df99b590683421d8 Mon Sep 17 00:00:00 2001 From: yura Date: Wed, 31 May 2023 11:07:00 +0300 Subject: [PATCH 06/20] code refactoring --- .../org/mixdrinks/mixdrinks/features/fetcher/Fetcher.kt | 7 +++---- .../mixdrinks/features/start/filter/FilterRepository.kt | 2 +- .../features/start/filter/ui/main/FilterScreen.kt | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/fetcher/Fetcher.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/fetcher/Fetcher.kt index 061dae7..5fbd4e7 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/fetcher/Fetcher.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/fetcher/Fetcher.kt @@ -35,10 +35,9 @@ class Fetcher( init { scope.launch { - /* if (roomDatabase.cocktailDao().getAll().isEmpty()) { - insertToDataBase(cocktailProvider.getAllCocktails()) - }*/ - insertToDataBase(cocktailProvider.getAllCocktails()) + if (roomDatabase.cocktailDao().getAll().isEmpty()) { + insertToDataBase(cocktailProvider.getAllCocktails()) + } } } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/FilterRepository.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/FilterRepository.kt index 5d1a220..fd02af4 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/FilterRepository.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/FilterRepository.kt @@ -25,7 +25,7 @@ class FilterRepository( id = filter.filterId, name = filter.name, cocktailIds = item.cocktailIds.filter{ it.filterId == filter.filterId }.map { it.cocktailId }, - checked = (filterStorage.selectedFilters.value.find { f -> f == filter.filterId } != null), + checked = (filterStorage.selectedFilters.value.find { id -> id == filter.filterId } != null), enabled = true ) } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt index dcbe425..3e37416 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt @@ -117,7 +117,7 @@ fun FilterScreenData( text = it.name, style = MaterialTheme.typography.h2 ) - when (true) { + when { (it.filters.size < 10) -> { it.filters.forEach { item -> FilterItem( From cc9635852d46674f7548c13ea6b4e9765d391b49 Mon Sep 17 00:00:00 2001 From: yura Date: Thu, 8 Jun 2023 16:28:31 +0300 Subject: [PATCH 07/20] fixed bugs insert filters to database, fixed first run app implementation filters search --- app/src/main/AndroidManifest.xml | 1 - .../main/java/org/mixdrinks/mixdrinks/App.kt | 76 ++++++++++--------- .../mixdrinks/mixdrinks/app/MixDrinksApp.kt | 5 +- .../mixdrinks/database/dao/CocktailDao.kt | 29 ++++--- .../mixdrinks/database/dao/FilterGroupDao.kt | 14 +--- .../database/entities/FilterGroup.kt | 13 +++- .../mixdrinks/features/data/CocktailFull.kt | 2 - .../features/data/FilterGroupFull.kt | 6 ++ .../cocktail/DetailScreenCocktailViewModel.kt | 5 +- .../mixdrinks/features/fetcher/Fetcher.kt | 16 ++-- .../features/start/StartRepository.kt | 31 ++++---- .../features/start/filter/FilterRepository.kt | 22 ++++-- .../start/filter/SelectedFilterStorage.kt | 25 +++--- .../start/filter/ui/main/FilterScreen.kt | 33 +++++--- .../filter/ui/main/FilterScreenViewModel.kt | 5 +- .../filter/ui/search/FilterSearchScreen.kt | 39 +++++++--- ...odel.kt => FilterSearchScreenViewModel.kt} | 37 +++++---- .../start/main/ui/StartScreenViewModel.kt | 7 +- app/src/main/res/values/strings.xml | 2 - 19 files changed, 213 insertions(+), 155 deletions(-) rename app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/{FilterSearchViewModel.kt => FilterSearchScreenViewModel.kt} (59%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 85a3a2a..3d3464e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -19,7 +19,6 @@ diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/App.kt b/app/src/main/java/org/mixdrinks/mixdrinks/App.kt index c8a72a8..bab5fc9 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/App.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/App.kt @@ -19,44 +19,50 @@ import org.mixdrinks.mixdrinks.features.start.filter.ui.main.FilterScreenViewMod import org.mixdrinks.mixdrinks.features.start.filter.SelectedFilterStorage import org.mixdrinks.mixdrinks.features.start.main.ui.StartScreenViewModel import org.mixdrinks.mixdrinks.features.start.filter.FilterRepository -import org.mixdrinks.mixdrinks.features.start.filter.ui.search.FilterSearchViewModel +import org.mixdrinks.mixdrinks.features.start.filter.ui.search.FilterSearchScreenViewModel class App : Application() { - override fun onCreate() { - super.onCreate() - - val appModule = module { - single { - Room.databaseBuilder( - androidContext(), - AppDatabase::class.java, - "mix-drinks-database" - ).build() - } - single { RetrofitClient.retrofit.create(MixDrinkService::class.java) } - - single { Fetcher (get(), get()) } - - // Repository - single { StartRepository(get(), get()) } - single { FilterRepository (get(), get()) } - - single { SelectedFilterStorage() } - - viewModel { StartScreenViewModel(get()) } - viewModel { (id: Int) -> DetailScreenCocktailViewModel(cocktailId = id, get(), get()) } - viewModel { (id: Int) -> DetailScreenGoodViewModel(goodId = id, get())} - viewModel { (id: Int) -> DetailScreenToolViewModel(toolId = id, get()) } - - viewModel { FilterScreenViewModel(get(), get()) } - viewModel { FilterSearchViewModel(get(), get()) } - } + override fun onCreate() { + super.onCreate() + + val appModule = module { + single { + Room.databaseBuilder( + androidContext(), + AppDatabase::class.java, + "mix-drinks-database" + ).build() + } + single { RetrofitClient.retrofit.create(MixDrinkService::class.java) } + + single { Fetcher(get(), get()) } + + // Repository + single { StartRepository(get(), get()) } + single { FilterRepository(get(), get()) } + + single { SelectedFilterStorage() } + + viewModel { StartScreenViewModel(get(), get()) } + viewModel { (id: Int) -> DetailScreenCocktailViewModel(cocktailId = id, get(), get()) } + viewModel { (id: Int) -> DetailScreenGoodViewModel(goodId = id, get()) } + viewModel { (id: Int) -> DetailScreenToolViewModel(toolId = id, get()) } + + viewModel { FilterScreenViewModel(get(), get()) } + viewModel { (groupId: Int) -> + FilterSearchScreenViewModel( + groupId = groupId, + get(), + get() + ) + } + } - startKoin { - androidLogger() - androidContext(applicationContext) - modules(appModule) + startKoin { + androidLogger() + androidContext(applicationContext) + modules(appModule) + } } - } } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt b/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt index 63ed0b3..cf0c8a1 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt @@ -5,21 +5,18 @@ import androidx.compose.ui.Modifier import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController -import org.koin.androidx.compose.get import org.mixdrinks.mixdrinks.app.ui.theme.MixDrinksTheme import org.mixdrinks.mixdrinks.features.common.ui.NotFoundScreen import org.mixdrinks.mixdrinks.features.detail.ui.cocktail.DetailScreen import org.mixdrinks.mixdrinks.features.detail.ui.good.DetailScreenGood import org.mixdrinks.mixdrinks.features.detail.ui.tool.DetailScreenTool -import org.mixdrinks.mixdrinks.features.fetcher.Fetcher -import org.mixdrinks.mixdrinks.features.start.main.ui.StartScreen import org.mixdrinks.mixdrinks.features.start.filter.ui.main.FilterScreen import org.mixdrinks.mixdrinks.features.start.filter.ui.search.FilterSearchScreen +import org.mixdrinks.mixdrinks.features.start.main.ui.StartScreen @Suppress("LongMethod") @Composable fun MixDrinksApp(modifier: Modifier = Modifier) { - Fetcher(get(), get()) MixDrinksTheme { val navController = rememberNavController() NavHost( diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/database/dao/CocktailDao.kt b/app/src/main/java/org/mixdrinks/mixdrinks/database/dao/CocktailDao.kt index fd7f1f1..3b87312 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/database/dao/CocktailDao.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/database/dao/CocktailDao.kt @@ -28,7 +28,7 @@ import org.mixdrinks.mixdrinks.database.entities.Tag import org.mixdrinks.mixdrinks.database.entities.Taste import org.mixdrinks.mixdrinks.database.entities.Tool import org.mixdrinks.mixdrinks.features.data.CocktailFull -import org.mixdrinks.mixdrinks.features.data.CocktailShort +import org.mixdrinks.mixdrinks.features.data.SelectedFilter @Dao interface CocktailDao { @@ -59,16 +59,8 @@ interface CocktailDao { @Query("SELECT * FROM cocktails WHERE cocktail_id = :id") suspend fun getById(id: Int): CocktailSnapshotDatabase - @Query("SELECT co.cocktail_id, co.name FROM cocktails AS co " + - "JOIN filter_with_cocktail_ids AS fi " + - "ON co.cocktail_id = fi.cocktail_id WHERE fi.filter_id IN (:filtersId) ") - suspend fun getCocktailWithFiltersShort(filtersId: List): List - @Query("SELECT cocktail_id, name FROM cocktails") - suspend fun getAllCocktailShort(): List - - @Query("SELECT * FROM cocktails") - suspend fun getAllCocktailShort2(): List + suspend fun getAllCocktailShort(): List } @@ -131,9 +123,11 @@ data class CocktailSnapshotDatabase( id = GoodId(good.goodId), name = good.name, amount = goodsUnit.filter { - it.goodId == good.goodId }.first().amount, + it.goodId == good.goodId + }.first().amount, unit = goodsUnit.filter { - it.goodId == good.goodId }.first().unit, + it.goodId == good.goodId + }.first().unit, ) }, tools = tools.map { tool -> @@ -154,12 +148,15 @@ data class CocktailSnapshotDatabase( name = taste.name ) }, - glassware = CocktailFull.Glassware(id = GlasswareId(glassware.glasswareId), name = glassware.name) + glassware = CocktailFull.Glassware( + id = GlasswareId(glassware.glasswareId), + name = glassware.name + ) ) } } -data class CocktailShort2( +data class Cocktails( @ColumnInfo(name = "cocktail_id") val cocktailId: Int, val name: String, @@ -173,7 +170,7 @@ data class CocktailShort2( return CocktailsWithFilters( cocktailId = cocktailId, name = name, - filters = filters.map { it.filterId } + filters = filters.map { SelectedFilter(it.filterId, it.filterGroupId) } ) } } @@ -181,5 +178,5 @@ data class CocktailShort2( data class CocktailsWithFilters( val cocktailId: Int, val name: String, - val filters: List + val filters: List ) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/database/dao/FilterGroupDao.kt b/app/src/main/java/org/mixdrinks/mixdrinks/database/dao/FilterGroupDao.kt index 4a343f3..9163d24 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/database/dao/FilterGroupDao.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/database/dao/FilterGroupDao.kt @@ -11,22 +11,16 @@ import org.mixdrinks.mixdrinks.database.entities.FilterGroup import org.mixdrinks.mixdrinks.database.entities.FilterWithCocktailIds import org.mixdrinks.mixdrinks.database.entities.Filters - @Dao interface FilterGroupDao { - @Insert(onConflict = OnConflictStrategy.REPLACE) - @Transaction - suspend fun addAllFilterGroups(filterGroup: List) @Insert(onConflict = OnConflictStrategy.REPLACE) @Transaction suspend fun addFilterGroup(filterGroup: FilterGroup) - @Insert(onConflict = OnConflictStrategy.REPLACE) - @Transaction - suspend fun addAllFilters(filterGroup: List) @Insert(onConflict = OnConflictStrategy.REPLACE) @Transaction suspend fun addFilter(filterGroup: Filters) + @Insert(onConflict = OnConflictStrategy.REPLACE) @Transaction suspend fun addAllFilterWithCocktailId(filterWithCocktailId: List) @@ -40,13 +34,13 @@ data class FilterGroups( @Embedded val filterGroup: FilterGroup, @Relation( - parentColumn = "id", + parentColumn = "filter_group_id", entityColumn = "filter_group_id", ) val filters: List, @Relation( - parentColumn = "id", - entityColumn = "filter_id", + parentColumn = "filter_group_id", + entityColumn = "filter_group_id", ) val cocktailIds: List, diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/database/entities/FilterGroup.kt b/app/src/main/java/org/mixdrinks/mixdrinks/database/entities/FilterGroup.kt index 9c0b961..8a9b2ac 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/database/entities/FilterGroup.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/database/entities/FilterGroup.kt @@ -9,14 +9,17 @@ import org.mixdrinks.dto.SelectionType @Entity(tableName = "filter_groups") data class FilterGroup( @PrimaryKey + @ColumnInfo(name = "filter_group_id") val id: Int, val name: String, val selectionType: SelectionType, ) -@Entity(tableName = "filters") +@Entity( + tableName = "filters", + primaryKeys = ["filter_id", "filter_group_id"], + ) data class Filters( - @PrimaryKey @ColumnInfo(name = "filter_id") val filterId : Int, @ColumnInfo(name = "filter_group_id") @@ -30,8 +33,8 @@ data class Filters( foreignKeys = [ ForeignKey( entity = Filters::class, - parentColumns = arrayOf("filter_id"), - childColumns = arrayOf("filter_id"), + parentColumns = arrayOf("filter_id", "filter_group_id"), + childColumns = arrayOf("filter_id", "filter_group_id"), onDelete = ForeignKey.CASCADE, onUpdate = ForeignKey.CASCADE ), @@ -47,6 +50,8 @@ data class Filters( data class FilterWithCocktailIds( @ColumnInfo(name = "filter_id") val filterId : Int, + @ColumnInfo(name = "filter_group_id") + val filterGroupId: Int, @ColumnInfo(name = "cocktail_id") val cocktailId: Int, ) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/CocktailFull.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/CocktailFull.kt index 6973254..aaa587d 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/CocktailFull.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/CocktailFull.kt @@ -44,8 +44,6 @@ data class CocktailFull( ) } - - data class CocktailShort( @ColumnInfo(name = "cocktail_id") val cocktailId: Int, diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/FilterGroupFull.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/FilterGroupFull.kt index ac52230..2309d81 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/FilterGroupFull.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/FilterGroupFull.kt @@ -17,3 +17,9 @@ data class FilterGroupFull( ) } +data class SelectedFilter( + val filterId: Int, + val filterGroupId: Int +) + + diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktailViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktailViewModel.kt index 1f94930..0d30b42 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktailViewModel.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktailViewModel.kt @@ -7,6 +7,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import org.mixdrinks.mixdrinks.database.AppDatabase import org.mixdrinks.mixdrinks.features.data.CocktailFull +import org.mixdrinks.mixdrinks.features.data.SelectedFilter import org.mixdrinks.mixdrinks.features.start.filter.SelectedFilterStorage import java.io.IOException @@ -48,7 +49,9 @@ class DetailScreenCocktailViewModel( } fun onClickTag(id: Int) { - filterStorage.onClickTag(id) + // Filter group for tags is 0 in Database + val filterGroupId = 0 + filterStorage.onClickTag(SelectedFilter(filterId = id, filterGroupId = filterGroupId)) } sealed class DetailUiState { diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/fetcher/Fetcher.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/fetcher/Fetcher.kt index 5fbd4e7..8b44669 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/fetcher/Fetcher.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/fetcher/Fetcher.kt @@ -1,8 +1,6 @@ package org.mixdrinks.mixdrinks.features.fetcher import androidx.room.Transaction -import kotlinx.coroutines.MainScope -import kotlinx.coroutines.launch import org.mixdrinks.dto.CocktailDto import org.mixdrinks.dto.FilterGroupDto import org.mixdrinks.dto.GlasswareDto @@ -31,16 +29,11 @@ class Fetcher( private val cocktailProvider: MixDrinkService, private val roomDatabase: AppDatabase, ) { - private val scope = MainScope() - - init { - scope.launch { - if (roomDatabase.cocktailDao().getAll().isEmpty()) { - insertToDataBase(cocktailProvider.getAllCocktails()) - } + suspend fun startFetch() { + if (roomDatabase.cocktailDao().getAll().isEmpty()) { + insertToDataBase(cocktailProvider.getAllCocktails()) } } - private suspend fun insertToDataBase(snapshot: SnapshotDto) { insertAllGlasswares(snapshot.glassware) insertAllGoods(snapshot.goods) @@ -176,7 +169,8 @@ class Fetcher( it.cocktailIds.map { cocktailId -> FilterWithCocktailIds( filterId = it.id.value, - cocktailId = cocktailId.id + cocktailId = cocktailId.id, + filterGroupId = item.id.value ) } ) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/StartRepository.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/StartRepository.kt index b70cefc..a56e936 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/StartRepository.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/StartRepository.kt @@ -10,38 +10,37 @@ class StartRepository( private val roomDatabase: AppDatabase, private val filterStorage: SelectedFilterStorage, ) { - private var cocktails: List = listOf() - + private var cocktailsFromDatabase: List = listOf() + private var cocktails: List = listOf() suspend fun getCocktails(): List { - if (cocktails.isEmpty()) { - cocktails = getCocktailFromDatabase() + if (cocktailsFromDatabase.isEmpty()) { + cocktailsFromDatabase = getCocktailFromDatabase() } - if (filterStorage.selectedFilters.value.isNotEmpty()) { - return filterCocktail(cocktails).map { CocktailShort(it.cocktailId, it.name) } + cocktails = if (filterStorage.selectedFilters.value.isNotEmpty()) { + filterCocktail(cocktailsFromDatabase).map { CocktailShort(it.cocktailId, it.name) } + } else { + cocktailsFromDatabase.map { CocktailShort(it.cocktailId, it.name) } } - return cocktails.map { CocktailShort(it.cocktailId, it.name) } + return cocktails } fun searchCocktail(search: String): List { - return cocktails - .filter { it.name.lowercase().contains(search.lowercase()) } - .map { CocktailShort(it.cocktailId, it.name) } + return cocktails.filter { it.name.lowercase().contains(search.lowercase()) } } - private fun filterCocktail(cocktails: List): List { return cocktails.filter { cocktail -> - cocktail.filters.find { filterId -> - filterStorage.selectedFilters.value.find { it == filterId } != null + cocktail.filters.find { filters -> + filterStorage.selectedFilters.value.find { + it.filterId == filters.filterId && it.filterGroupId == filters.filterGroupId + } != null } != null } } private suspend fun getCocktailFromDatabase(): List { - return roomDatabase.cocktailDao().getAllCocktailShort2().map { it.toCocktailsWithFilters() } + return roomDatabase.cocktailDao().getAllCocktailShort().map { it.toCocktailsWithFilters() } } - - } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/FilterRepository.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/FilterRepository.kt index fd02af4..23933c5 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/FilterRepository.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/FilterRepository.kt @@ -9,13 +9,19 @@ class FilterRepository( private val filterStorage: SelectedFilterStorage ) { - private var filters: List = listOf() + private var filterGroups: List = listOf() + + suspend fun getFiltersByGroupId(groupId: Int, search: String): List { + return getFilters().first { it.id == groupId }.filters.filter { + it.name.lowercase().contains(search.lowercase()) + } + } suspend fun getFilters(): List { - if (filters.isEmpty()) { - filters = getFiltersFromDatabase() + if (filterGroups.isEmpty()) { + filterGroups = getFiltersFromDatabase() } - return filters.map { item -> + return filterGroups.map { item -> FilterGroupFull( id = item.filterGroup.id, name = item.filterGroup.name, @@ -24,8 +30,12 @@ class FilterRepository( FilterGroupFull.Filter( id = filter.filterId, name = filter.name, - cocktailIds = item.cocktailIds.filter{ it.filterId == filter.filterId }.map { it.cocktailId }, - checked = (filterStorage.selectedFilters.value.find { id -> id == filter.filterId } != null), + cocktailIds = item.cocktailIds.filter { + it.filterId == filter.filterId && it.filterGroupId == filter.filterGroupId + }.map { it.cocktailId }, + checked = (filterStorage.selectedFilters.value.find { item -> + item.filterId == filter.filterId && item.filterGroupId == filter.filterGroupId + } != null), enabled = true ) } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/SelectedFilterStorage.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/SelectedFilterStorage.kt index 3c3c956..1cbca0e 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/SelectedFilterStorage.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/SelectedFilterStorage.kt @@ -3,18 +3,22 @@ package org.mixdrinks.mixdrinks.features.start.filter import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update +import org.mixdrinks.mixdrinks.features.data.SelectedFilter -class SelectedFilterStorage { - private val _selectedFilters = MutableStateFlow(mutableListOf()) - val selectedFilters: StateFlow> = _selectedFilters +class SelectedFilterStorage() { + private val _selectedFilters = MutableStateFlow(mutableListOf()) + val selectedFilters: StateFlow> = _selectedFilters - fun add(id: Int) { - val list = mutableListOf() + fun add(selectedFilter: SelectedFilter) { + val list = mutableListOf() list.addAll((_selectedFilters.value)) - if(list.find { it == id } == null) { - list.add(id) + if (list.find { + it.filterId == selectedFilter.filterId && it.filterGroupId == selectedFilter.filterGroupId + } == null + ) { + list.add(selectedFilter) } else { - list.remove(id) + list.remove(selectedFilter) } _selectedFilters.update { @@ -28,10 +32,11 @@ class SelectedFilterStorage { } } - fun onClickTag(id: Int) { + fun onClickTag(selectedFilter: SelectedFilter) { _selectedFilters.update { - mutableListOf(id) + mutableListOf(selectedFilter) } } + } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt index 3e37416..34c08c7 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt @@ -34,6 +34,7 @@ import org.mixdrinks.mixdrinks.R import org.mixdrinks.mixdrinks.features.common.ui.ErrorLoadingScreen import org.mixdrinks.mixdrinks.features.common.ui.LoaderIndicatorScreen import org.mixdrinks.mixdrinks.features.data.FilterGroupFull +import org.mixdrinks.mixdrinks.features.data.SelectedFilter import java.util.Locale @Composable @@ -112,30 +113,44 @@ fun FilterScreenData( LazyColumn { items( items = filters.sortedBy { it.filters.size }, - itemContent = { + itemContent = { filterGroup -> Text( - text = it.name, + text = filterGroup.name, style = MaterialTheme.typography.h2 ) when { - (it.filters.size < 10) -> { - it.filters.forEach { item -> + (filterGroup.filters.size < 10) -> { + filterGroup.filters.forEach { item -> FilterItem( item, - onClick = { id -> viewModel.checkedAction(id) }) + onClick = { filterId -> + viewModel.checkedAction( + SelectedFilter( + filterId = filterId, + filterGroupId = filterGroup.id, + ) + ) + }) } } else -> { - it.filters.filter { it.checked }.forEach { item -> + filterGroup.filters.filter { it.checked }.forEach { item -> FilterItem( item, - onClick = { id -> viewModel.checkedAction(id) }) + onClick = { filterId -> + viewModel.checkedAction( + SelectedFilter( + filterId = filterId, + filterGroupId = filterGroup.id, + ) + ) + }) } AddButton( modifier = modifier, - text = it.name, - onClick = { onClickButtonAddAction(it.id) }) + text = filterGroup.name, + onClick = { onClickButtonAddAction(filterGroup.id) }) } } } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreenViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreenViewModel.kt index 9f67b43..b4e1bcb 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreenViewModel.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreenViewModel.kt @@ -7,6 +7,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.mixdrinks.mixdrinks.features.data.FilterGroupFull +import org.mixdrinks.mixdrinks.features.data.SelectedFilter import org.mixdrinks.mixdrinks.features.start.filter.FilterRepository import org.mixdrinks.mixdrinks.features.start.filter.SelectedFilterStorage import java.io.IOException @@ -50,8 +51,8 @@ class FilterScreenViewModel( class Error(val message: String) : FilterUiState() } - fun checkedAction(id: Int) { - filterStorage.add(id) + fun checkedAction(selectedFilter: SelectedFilter) { + filterStorage.add(selectedFilter) } fun clearFilters() { diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchScreen.kt index af2c70c..84fbcf9 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchScreen.kt @@ -40,6 +40,7 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.dp import coil.compose.AsyncImage import org.koin.androidx.compose.koinViewModel +import org.koin.core.parameter.parametersOf import org.mixdrinks.domain.ImageUrlCreators import org.mixdrinks.dto.CocktailId import org.mixdrinks.mixdrinks.app.ui.theme.GreenAlfa @@ -47,33 +48,36 @@ import org.mixdrinks.mixdrinks.features.common.ui.ErrorLoadingScreen import org.mixdrinks.mixdrinks.features.common.ui.LoaderIndicatorScreen import org.mixdrinks.mixdrinks.features.common.ui.widgets.IconTextFieldIcon import org.mixdrinks.mixdrinks.features.data.FilterGroupFull +import org.mixdrinks.mixdrinks.features.data.SelectedFilter import org.mixdrinks.mixdrinks.features.start.filter.ui.main.ApplyButton @Composable fun FilterSearchScreen( modifier: Modifier, - viewModel: FilterSearchViewModel = koinViewModel(), groupId: Int, + viewModel: FilterSearchScreenViewModel = koinViewModel { parametersOf(groupId) }, onNavigateToFilter: () -> Unit ) { val filters by viewModel.uiState.collectAsState() when (filters) { - is FilterSearchViewModel.FilterUiState.Loaded -> { - val data = (filters as FilterSearchViewModel.FilterUiState.Loaded).itemState + is FilterSearchScreenViewModel.FilterUiState.Loaded -> { + val data = (filters as FilterSearchScreenViewModel.FilterUiState.Loaded).itemState + FilterSearchScreenData( modifier = modifier, - filters = data.filters.first { it.id == groupId }.filters, + filters = data.filters, + filterGroupId = groupId, onNavigateToFilter = onNavigateToFilter, viewModel = viewModel ) } - is FilterSearchViewModel.FilterUiState.Loading -> { + is FilterSearchScreenViewModel.FilterUiState.Loading -> { LoaderIndicatorScreen(modifier = modifier) } else -> { - val error = filters as FilterSearchViewModel.FilterUiState.Error + val error = filters as FilterSearchScreenViewModel.FilterUiState.Error Log.d("Exception", error.message) ErrorLoadingScreen(modifier = modifier) } @@ -85,7 +89,8 @@ fun FilterSearchScreenData( modifier: Modifier, onNavigateToFilter: () -> Unit, filters: List, - viewModel: FilterSearchViewModel + filterGroupId: Int, + viewModel: FilterSearchScreenViewModel ) { Box( modifier = modifier @@ -100,7 +105,9 @@ fun FilterSearchScreenData( .fillMaxSize() .padding(horizontal = 12.dp), ) { - SearchTextField(modifier = modifier) + SearchTextField(modifier = modifier, + searchAction = { viewModel.searchAction(it) } + ) Row( verticalAlignment = Alignment.CenterVertically, @@ -119,7 +126,14 @@ fun FilterSearchScreenData( itemContent = { filters -> FilterItem( modifier = modifier, filter = filters, - onClick = { viewModel.checkedAction(it) } + onClick = { + viewModel.checkedAction( + SelectedFilter( + filterId = it, + filterGroupId = filterGroupId + ) + ) + } ) }) } @@ -130,7 +144,10 @@ fun FilterSearchScreenData( } @Composable -fun SearchTextField(modifier: Modifier) { +fun SearchTextField( + modifier: Modifier, + searchAction: (searchText: String) -> Unit, +) { var textState by rememberSaveable { mutableStateOf("") } TextField( @@ -145,6 +162,7 @@ fun SearchTextField(modifier: Modifier) { value = textState, onValueChange = { textState = it + searchAction(textState) }, modifier = modifier .fillMaxWidth() @@ -153,6 +171,7 @@ fun SearchTextField(modifier: Modifier) { trailingIcon = { IconTextFieldIcon(text = textState, onClick = { textState = "" + searchAction(textState) }) }, ) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchScreenViewModel.kt similarity index 59% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchViewModel.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchScreenViewModel.kt index 639f323..295853a 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchViewModel.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchScreenViewModel.kt @@ -7,46 +7,55 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.mixdrinks.mixdrinks.features.data.FilterGroupFull +import org.mixdrinks.mixdrinks.features.data.SelectedFilter import org.mixdrinks.mixdrinks.features.start.filter.FilterRepository import org.mixdrinks.mixdrinks.features.start.filter.SelectedFilterStorage -import org.mixdrinks.mixdrinks.features.start.filter.ui.main.FilterItemUiState -class FilterSearchViewModel( +class FilterSearchScreenViewModel( + private val groupId: Int, private val filterRepository: FilterRepository, private val filterStorage: SelectedFilterStorage ) : ViewModel() { - private lateinit var filtersByGroup: List - private val _uiState = MutableStateFlow( FilterUiState.Loading ) val uiState: StateFlow = _uiState + private var searchText = "" init { viewModelScope.launch { - val data = filterRepository.getFilters() - filtersByGroup = data.first { it.id == 1 }.filters - filterStorage.selectedFilters.collect { updateFilters() } } } - private suspend fun updateFilters() { - _uiState.update { - FilterUiState.Loaded(FilterItemUiState(filterRepository.getFilters())) + private fun updateFilters() { + viewModelScope.launch { + _uiState.update { + FilterUiState.Loaded(FilterSearchItemUiState(filterRepository.getFiltersByGroupId(groupId,searchText))) + } } } - fun checkedAction(id: Int) { - filterStorage.add(id) + fun searchAction(search: String) { + searchText = search + updateFilters() + } + + + fun checkedAction(selectedFilter: SelectedFilter) { + filterStorage.add(selectedFilter) } + sealed class FilterUiState { object Loading : FilterUiState() - class Loaded(val itemState: FilterItemUiState) : FilterUiState() + class Loaded(val itemState: FilterSearchItemUiState) : FilterUiState() class Error(val message: String) : FilterUiState() } - } +data class FilterSearchItemUiState( + val filters: List +) + diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreenViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreenViewModel.kt index 9825b35..183738b 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreenViewModel.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreenViewModel.kt @@ -7,25 +7,28 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.mixdrinks.mixdrinks.features.data.CocktailShort +import org.mixdrinks.mixdrinks.features.fetcher.Fetcher import org.mixdrinks.mixdrinks.features.start.StartRepository import java.io.IOException @Suppress("TooGenericExceptionCaught", "MagicNumber") class StartScreenViewModel( private val startRepository: StartRepository, + private val fetcher: Fetcher ) : ViewModel() { private val _uiState = MutableStateFlow(StartUiState.Loading) val uiState: StateFlow = _uiState init { - getCocktail() + getCocktails() } - private fun getCocktail() { + private fun getCocktails() { _uiState.value = StartUiState.Loading viewModelScope.launch { try { + fetcher.startFetch() _uiState.value = StartUiState.Loaded(StartItemUiState("", startRepository.getCocktails())) } catch (error: IOException) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9628a38..a067fdd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2,8 +2,6 @@ MixDrinks Failure connecting - MainActivity - Cocktail recipe Ingredients of the cocktail Need tools for cooking cocktail From a9f7d44c349d8b964d3e51cd8ae11835b79a706a Mon Sep 17 00:00:00 2001 From: yura Date: Thu, 8 Jun 2023 17:41:34 +0300 Subject: [PATCH 08/20] fixed detekt error --- .../mixdrinks/features/start/filter/SelectedFilterStorage.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/SelectedFilterStorage.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/SelectedFilterStorage.kt index 1cbca0e..b04207e 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/SelectedFilterStorage.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/SelectedFilterStorage.kt @@ -5,7 +5,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import org.mixdrinks.mixdrinks.features.data.SelectedFilter -class SelectedFilterStorage() { +class SelectedFilterStorage { private val _selectedFilters = MutableStateFlow(mutableListOf()) val selectedFilters: StateFlow> = _selectedFilters From a345d1f93e583fa53b302389e1d9e74ffff47bc6 Mon Sep 17 00:00:00 2001 From: yura Date: Fri, 9 Jun 2023 11:59:44 +0300 Subject: [PATCH 09/20] fixed ui --- .../ui/cocktail/DetailScreenCocktail.kt | 15 ++-- .../detail/ui/cocktail/GoodsListItem.kt | 70 +++++++++++-------- .../detail/ui/cocktail/RecipeContent.kt | 4 +- app/src/main/res/values-uk/strings.xml | 6 +- app/src/main/res/values/strings.xml | 6 +- 5 files changed, 56 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt index beea135..7c9a08f 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt @@ -118,7 +118,6 @@ fun DetailsScreenData( CocktailRecipeContent( modifier = modifier, - cocktailName = data.cocktail.name, cocktailReceipt = data.cocktail.receipt ) Spacer(modifier = modifier.padding(top = 10.dp)) @@ -131,9 +130,8 @@ fun DetailsScreenData( ) Spacer(modifier = modifier.padding(top = 15.dp)) - CocktailNeedToolsContent( + CocktailToolsContent( modifier = modifier, - cocktailName = data.cocktail.name, cocktailTools = data.cocktail.tools, glassware = data.cocktail.glassware, onClick = onNavigateToDetailTool @@ -155,14 +153,14 @@ private fun CocktailIngredientsContent( ) { Text( style = MaterialTheme.typography.h2, - text = "${stringResource(R.string.cocktail_ingredients)} ${data.cocktail.name}" + text = stringResource(R.string.cocktail_ingredients) ) } Spacer(modifier = modifier.padding(top = 15.dp)) CocktailPortions(modifier = modifier, viewModel = viewModel, data = data ) Spacer(modifier = modifier.padding(bottom = 15.dp)) - GoodsListItem( + GoodsListItems( modifier = modifier, onClick = onClick, data = data @@ -202,9 +200,8 @@ private fun CocktailPortions( } @Composable -fun CocktailNeedToolsContent( +fun CocktailToolsContent( modifier: Modifier, - cocktailName: String, cocktailTools: List, glassware: CocktailFull.Glassware, onClick: (id: Int) -> Unit @@ -216,11 +213,11 @@ fun CocktailNeedToolsContent( ) { Text( style = MaterialTheme.typography.h2, - text = "${stringResource(R.string.need_tools)} $cocktailName" + text = stringResource(R.string.need_tools) ) } Spacer(modifier = modifier.padding(bottom = 15.dp)) - ToolsListItem( + ToolsListItems( modifier = modifier, tools = cocktailTools, glassware = glassware, diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt index 54eada6..e6a0be6 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt @@ -24,11 +24,12 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.dp import coil.compose.AsyncImage import org.mixdrinks.domain.ImageUrlCreators +import org.mixdrinks.dto.GoodId import org.mixdrinks.mixdrinks.features.data.CocktailFull @Suppress("MagicNumber") @Composable -fun GoodsListItem( +fun GoodsListItems( modifier: Modifier, data: DetailItemUiState, onClick: (id: Int) -> Unit @@ -78,9 +79,8 @@ fun GoodsListItem( } } -@Suppress("UnusedPrivateMember") @Composable -fun ToolsListItem( +fun ToolsListItems( modifier: Modifier, tools: List, glassware: CocktailFull.Glassware, @@ -91,34 +91,48 @@ fun ToolsListItem( horizontalArrangement = Arrangement.spacedBy(8.dp), modifier = modifier.height(180.dp) ) { + item { + ToolsListItem(modifier = modifier, id = glassware.id.value, name = glassware.name, onClick = onClick) + + } items(tools) { item -> - Card( + ToolsListItem(modifier = modifier, id = item.id.id, name = item.name, onClick = onClick) + } + } +} + +@Composable +fun ToolsListItem( + modifier: Modifier, + id: Int, + name: String, + onClick: (id: Int) -> Unit +) { + Card( + modifier = modifier + .clickable { onClick(id) }, + ) { + Column( + modifier = modifier + .fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + ImageItem( + modifier = modifier, + ImageUrlCreators.createUrl( + GoodId(id), + ImageUrlCreators.Size.SIZE_320 + ) + ) + Row( modifier = modifier - .clickable { onClick(item.id.id) }, + .fillMaxWidth(1f), + horizontalArrangement = Arrangement.Start ) { - Column( - modifier = modifier - .fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - ImageItem( - modifier = modifier, - ImageUrlCreators.createUrl( - item.id, - ImageUrlCreators.Size.SIZE_320 - ) - ) - Row( - modifier = modifier - .fillMaxWidth(1f), - horizontalArrangement = Arrangement.Start - ) { - Text( - style = MaterialTheme.typography.body1, - text = item.name, - ) - } - } + Text( + style = MaterialTheme.typography.body1, + text = name, + ) } } } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/RecipeContent.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/RecipeContent.kt index 077f211..6a0102f 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/RecipeContent.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/RecipeContent.kt @@ -26,7 +26,7 @@ import org.mixdrinks.mixdrinks.R import org.mixdrinks.mixdrinks.app.ui.theme.Green700 @Composable -fun CocktailRecipeContent(modifier: Modifier, cocktailName: String, cocktailReceipt: List) { +fun CocktailRecipeContent(modifier: Modifier, cocktailReceipt: List) { Row( modifier = modifier .fillMaxWidth(1f), @@ -34,7 +34,7 @@ fun CocktailRecipeContent(modifier: Modifier, cocktailName: String, cocktailRece ) { Text( style = MaterialTheme.typography.h2, - text = "${stringResource(R.string.cocktail_recipe)} $cocktailName", + text = stringResource(R.string.cocktail_recipe), ) } Spacer(modifier = modifier.padding(top = 5.dp)) diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index fba11b0..867085e 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -1,9 +1,9 @@ Помилка підключення - Рецепт Коктейлю - Склад коктейлю - Потрібні штучки для пригоування + Рецепт + Склад + Інструменти Перегляди Пошук Помилка завантаження. Перевірте підключення до Інтернету diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a067fdd..99dc90b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -2,9 +2,9 @@ MixDrinks Failure connecting - Cocktail recipe - Ingredients of the cocktail - Need tools for cooking cocktail + Recipe + Ingredients + Tools Visit count Search Error loading. Please check internet connection From 10b6305673ab5cecf8c166d348e306266f432535 Mon Sep 17 00:00:00 2001 From: yura Date: Fri, 9 Jun 2023 12:08:57 +0300 Subject: [PATCH 10/20] code refactoring --- .../detail/ui/cocktail/DetailScreenCocktail.kt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt index 7c9a08f..09cc6e3 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt @@ -44,7 +44,7 @@ fun DetailScreen( ) { val cocktail by viewModel.uiState.collectAsState() - when(cocktail) { + when (cocktail) { is DetailScreenCocktailViewModel.DetailUiState.Loaded -> { val data = (cocktail as DetailScreenCocktailViewModel.DetailUiState.Loaded).itemState DetailsScreenData( @@ -57,9 +57,11 @@ fun DetailScreen( onClickTagAction = onNavigateToStart ) } + is DetailScreenCocktailViewModel.DetailUiState.Loading -> { LoaderIndicatorScreen(modifier = modifier) } + else -> { val error = cocktail as DetailScreenCocktailViewModel.DetailUiState.Error Log.d("Exception", error.message) @@ -78,7 +80,7 @@ fun DetailsScreenData( onBack: () -> Unit, viewModel: DetailScreenCocktailViewModel, onClickTagAction: () -> Unit, - ) { +) { Column( modifier = modifier .verticalScroll(rememberScrollState()) @@ -96,7 +98,7 @@ fun DetailsScreenData( TagListItem( modifier = modifier, listTags = data.cocktail.tags, - onClickAction = {tagId -> + onClickAction = { tagId -> viewModel.onClickTag(tagId) onClickTagAction() } @@ -158,7 +160,7 @@ private fun CocktailIngredientsContent( } Spacer(modifier = modifier.padding(top = 15.dp)) - CocktailPortions(modifier = modifier, viewModel = viewModel, data = data ) + CocktailPortions(modifier = modifier, viewModel = viewModel, data = data) Spacer(modifier = modifier.padding(bottom = 15.dp)) GoodsListItems( modifier = modifier, @@ -175,10 +177,10 @@ private fun CocktailPortions( ) { Row { SquareMarker( - modifier = modifier - .clickable { - viewModel.decPortion() - }, + modifier = modifier + .clickable { + viewModel.decPortion() + }, text = "-", ) Spacer(modifier = modifier.padding(5.dp)) From aa5b30b8c96c46dfbeee6b616114869d59424af7 Mon Sep 17 00:00:00 2001 From: yura Date: Fri, 9 Jun 2023 16:44:34 +0300 Subject: [PATCH 11/20] implementation detailing screen for goods --- .../main/java/org/mixdrinks/mixdrinks/App.kt | 5 +- .../mixdrinks/mixdrinks/app/MixDrinksApp.kt | 29 ++--- .../org/mixdrinks/mixdrinks/app/Routes.kt | 4 +- .../mixdrinks/features/data/DetailGood.kt | 22 ++-- .../ui/cocktail/DetailScreenCocktail.kt | 14 +-- .../detail/ui/cocktail/GoodsListItem.kt | 28 +++-- .../detail/ui/good/DetailScreenGood.kt | 8 +- .../ui/good/DetailScreenGoodViewModel.kt | 29 +++-- .../detail/ui/tool/DetailScreenTool.kt | 110 ------------------ .../ui/tool/DetailScreenToolViewModel.kt | 55 --------- 10 files changed, 76 insertions(+), 228 deletions(-) delete mode 100644 app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/tool/DetailScreenTool.kt delete mode 100644 app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/tool/DetailScreenToolViewModel.kt diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/App.kt b/app/src/main/java/org/mixdrinks/mixdrinks/App.kt index bab5fc9..d27ad9a 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/App.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/App.kt @@ -9,10 +9,10 @@ import org.koin.core.context.GlobalContext.startKoin import org.koin.dsl.module import org.mixdrinks.mixdrinks.app.RetrofitClient import org.mixdrinks.mixdrinks.database.AppDatabase +import org.mixdrinks.mixdrinks.features.data.GoodType import org.mixdrinks.mixdrinks.features.data.MixDrinkService import org.mixdrinks.mixdrinks.features.detail.ui.cocktail.DetailScreenCocktailViewModel import org.mixdrinks.mixdrinks.features.detail.ui.good.DetailScreenGoodViewModel -import org.mixdrinks.mixdrinks.features.detail.ui.tool.DetailScreenToolViewModel import org.mixdrinks.mixdrinks.features.fetcher.Fetcher import org.mixdrinks.mixdrinks.features.start.StartRepository import org.mixdrinks.mixdrinks.features.start.filter.ui.main.FilterScreenViewModel @@ -45,8 +45,7 @@ class App : Application() { viewModel { StartScreenViewModel(get(), get()) } viewModel { (id: Int) -> DetailScreenCocktailViewModel(cocktailId = id, get(), get()) } - viewModel { (id: Int) -> DetailScreenGoodViewModel(goodId = id, get()) } - viewModel { (id: Int) -> DetailScreenToolViewModel(toolId = id, get()) } + viewModel { (goodType: GoodType) -> DetailScreenGoodViewModel(goodType = goodType, get()) } viewModel { FilterScreenViewModel(get(), get()) } viewModel { (groupId: Int) -> diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt b/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt index cf0c8a1..4b0c2cd 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt @@ -7,9 +7,9 @@ import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import org.mixdrinks.mixdrinks.app.ui.theme.MixDrinksTheme import org.mixdrinks.mixdrinks.features.common.ui.NotFoundScreen +import org.mixdrinks.mixdrinks.features.data.GoodType import org.mixdrinks.mixdrinks.features.detail.ui.cocktail.DetailScreen import org.mixdrinks.mixdrinks.features.detail.ui.good.DetailScreenGood -import org.mixdrinks.mixdrinks.features.detail.ui.tool.DetailScreenTool import org.mixdrinks.mixdrinks.features.start.filter.ui.main.FilterScreen import org.mixdrinks.mixdrinks.features.start.filter.ui.search.FilterSearchScreen import org.mixdrinks.mixdrinks.features.start.main.ui.StartScreen @@ -30,32 +30,25 @@ fun MixDrinksApp(modifier: Modifier = Modifier) { } composable("${Routes.cocktail}/{${Routes.cocktailId}}") { backStackEntry -> val cocktailId = backStackEntry.arguments?.getString(Routes.cocktailId) - cocktailId?.toInt()?.let { + cocktailId?.toInt()?.let { id -> DetailScreen(modifier = modifier, - cocktailId = it, + cocktailId = id, onNavigateToStart = { navController.navigate(Routes.start) }, - onNavigateToDetailGood = { navController.navigate("${Routes.good}/$it") }, - onNavigateToDetailTool = { navController.navigate("${Routes.tool}/$it") }, + onNavigateToDetailGood = { goodType -> + navController.navigate("${Routes.good}/${goodType.id}/${goodType.type}") + }, onBack = { navController.popBackStack() }) } } - composable("${Routes.good}/{${Routes.goodId}}") { backStackEntry -> + composable("${Routes.good}/{${Routes.goodId}}/{${Routes.goodType}}") { backStackEntry -> val goodId = backStackEntry.arguments?.getString(Routes.goodId) - goodId?.toInt()?.let { + val goodType = backStackEntry.arguments?.getString(Routes.goodType) + + if (goodId != null && goodType != null) DetailScreenGood( modifier = modifier, - goodId = it, - onBack = { navController.popBackStack() }) - } - } - composable("${Routes.tool}/{${Routes.toolId}}") { backStackEntry -> - val toolId = backStackEntry.arguments?.getString(Routes.toolId) - toolId?.toInt()?.let { - DetailScreenTool( - modifier = modifier, - toolId = it, + goodType = GoodType(id = goodId.toInt(), GoodType.Type.fromString(goodType)), onBack = { navController.popBackStack() }) - } } composable(Routes.filter) { FilterScreen(modifier = modifier, diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/app/Routes.kt b/app/src/main/java/org/mixdrinks/mixdrinks/app/Routes.kt index 5870185..1dbbf4c 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/app/Routes.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/app/Routes.kt @@ -8,11 +8,9 @@ object Routes { const val cocktail = "cocktail" const val cocktailId = "cocktail_id" - const val tool = "tool" - const val toolId = "tool_id" - const val good = "good" const val goodId = "good_id" + const val goodType = "good_type" const val filterSearch = "filter_search" const val groupFilterId = "group_filter_id" diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/DetailGood.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/DetailGood.kt index 36c4532..7491f1b 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/DetailGood.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/DetailGood.kt @@ -1,17 +1,19 @@ package org.mixdrinks.mixdrinks.features.data -import org.mixdrinks.dto.GoodId -import org.mixdrinks.dto.ToolId - data class DetailGood( - val id: GoodId, - val name: String, - val about: String -) - -data class DetailTool( - val id: ToolId, + val id: Int, val name: String, val about: String ) +data class GoodType( + val id: Int, + val type: Type +) { + enum class Type { + GOOD, GLASSWARE, TOOL; + companion object { + fun fromString(value: String) = Type.values().first() { it.toString() == value } + } + } +} diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt index 09cc6e3..2a7aeb0 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt @@ -29,6 +29,7 @@ import org.mixdrinks.mixdrinks.R import org.mixdrinks.mixdrinks.features.common.ui.ErrorLoadingScreen import org.mixdrinks.mixdrinks.features.common.ui.LoaderIndicatorScreen import org.mixdrinks.mixdrinks.features.data.CocktailFull +import org.mixdrinks.mixdrinks.features.data.GoodType import org.mixdrinks.mixdrinks.features.detail.ui.Header @Suppress("LongParameterList") @@ -36,8 +37,7 @@ import org.mixdrinks.mixdrinks.features.detail.ui.Header fun DetailScreen( modifier: Modifier, cocktailId: Int, - onNavigateToDetailGood: (id: Int) -> Unit, - onNavigateToDetailTool: (id: Int) -> Unit, + onNavigateToDetailGood: (goodType: GoodType) -> Unit, onBack: () -> Unit, onNavigateToStart: () -> Unit, viewModel: DetailScreenCocktailViewModel = koinViewModel { parametersOf(cocktailId) }, @@ -50,7 +50,6 @@ fun DetailScreen( DetailsScreenData( modifier = modifier, data = data, - onNavigateToDetailTool = onNavigateToDetailTool, onNavigateToDetailGood = onNavigateToDetailGood, onBack = onBack, viewModel = viewModel, @@ -75,8 +74,7 @@ fun DetailScreen( fun DetailsScreenData( modifier: Modifier, data: DetailItemUiState, - onNavigateToDetailGood: (id: Int) -> Unit, - onNavigateToDetailTool: (id: Int) -> Unit, + onNavigateToDetailGood: (goodType: GoodType) -> Unit, onBack: () -> Unit, viewModel: DetailScreenCocktailViewModel, onClickTagAction: () -> Unit, @@ -136,7 +134,7 @@ fun DetailsScreenData( modifier = modifier, cocktailTools = data.cocktail.tools, glassware = data.cocktail.glassware, - onClick = onNavigateToDetailTool + onClick = onNavigateToDetailGood ) } } @@ -144,7 +142,7 @@ fun DetailsScreenData( @Composable private fun CocktailIngredientsContent( modifier: Modifier, - onClick: (id: Int) -> Unit, + onClick: (goodType: GoodType) -> Unit, viewModel: DetailScreenCocktailViewModel, data: DetailItemUiState ) { @@ -206,7 +204,7 @@ fun CocktailToolsContent( modifier: Modifier, cocktailTools: List, glassware: CocktailFull.Glassware, - onClick: (id: Int) -> Unit + onClick: (goodType: GoodType) -> Unit ) { Row( modifier = modifier diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt index e6a0be6..5817990 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt @@ -26,13 +26,14 @@ import coil.compose.AsyncImage import org.mixdrinks.domain.ImageUrlCreators import org.mixdrinks.dto.GoodId import org.mixdrinks.mixdrinks.features.data.CocktailFull +import org.mixdrinks.mixdrinks.features.data.GoodType @Suppress("MagicNumber") @Composable fun GoodsListItems( modifier: Modifier, data: DetailItemUiState, - onClick: (id: Int) -> Unit + onClick: (goodType: GoodType) -> Unit ) { LazyHorizontalGrid( rows = GridCells.Fixed(1), @@ -42,7 +43,7 @@ fun GoodsListItems( items(data.cocktail.goods) { item -> Card( modifier = modifier - .clickable { onClick(item.id.id) }, + .clickable { onClick(GoodType(id = item.id.id, type = GoodType.Type.GOOD)) }, ) { Column( modifier = modifier @@ -84,7 +85,7 @@ fun ToolsListItems( modifier: Modifier, tools: List, glassware: CocktailFull.Glassware, - onClick: (id: Int) -> Unit + onClick: (goodType: GoodType) -> Unit ) { LazyHorizontalGrid( rows = GridCells.Fixed(1), @@ -92,11 +93,19 @@ fun ToolsListItems( modifier = modifier.height(180.dp) ) { item { - ToolsListItem(modifier = modifier, id = glassware.id.value, name = glassware.name, onClick = onClick) - + ToolsListItem( + modifier = modifier, + id = glassware.id.value, + name = glassware.name, + type = GoodType.Type.GLASSWARE, + onClick = onClick + ) } items(tools) { item -> - ToolsListItem(modifier = modifier, id = item.id.id, name = item.name, onClick = onClick) + ToolsListItem( + modifier = modifier, id = item.id.id, + name = item.name, type = GoodType.Type.TOOL, onClick = onClick + ) } } } @@ -106,11 +115,14 @@ fun ToolsListItem( modifier: Modifier, id: Int, name: String, - onClick: (id: Int) -> Unit + type: GoodType.Type, + onClick: (goodType: GoodType) -> Unit ) { Card( modifier = modifier - .clickable { onClick(id) }, + .clickable { + onClick(GoodType(id = id, type)) + }, ) { Column( modifier = modifier diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGood.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGood.kt index 83f0664..189f1b5 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGood.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGood.kt @@ -24,18 +24,20 @@ import coil.compose.AsyncImage import org.koin.androidx.compose.koinViewModel import org.koin.core.parameter.parametersOf import org.mixdrinks.domain.ImageUrlCreators +import org.mixdrinks.dto.GoodId import org.mixdrinks.mixdrinks.R import org.mixdrinks.mixdrinks.features.common.ui.ErrorLoadingScreen import org.mixdrinks.mixdrinks.features.common.ui.LoaderIndicatorScreen import org.mixdrinks.mixdrinks.features.data.DetailGood +import org.mixdrinks.mixdrinks.features.data.GoodType import org.mixdrinks.mixdrinks.features.detail.ui.Header @Composable fun DetailScreenGood( modifier: Modifier, - goodId: Int, + goodType: GoodType, onBack: () -> Unit, - viewModel: DetailScreenGoodViewModel = koinViewModel { parametersOf(goodId) }, + viewModel: DetailScreenGoodViewModel = koinViewModel { parametersOf(goodType) }, ) { val cocktail by viewModel.uiState.collectAsState() @@ -74,7 +76,7 @@ fun DetailScreenGoodData(modifier: Modifier, good: DetailGood, onBack: () -> Uni AsyncImage( model = ImageUrlCreators.createUrl( - good.id, + GoodId(good.id), ImageUrlCreators.Size.SIZE_320 ), contentDescription = null, diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGoodViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGoodViewModel.kt index 95dfda8..60e9c21 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGoodViewModel.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGoodViewModel.kt @@ -5,14 +5,14 @@ import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch -import org.mixdrinks.dto.GoodId import org.mixdrinks.mixdrinks.database.AppDatabase import org.mixdrinks.mixdrinks.features.data.DetailGood +import org.mixdrinks.mixdrinks.features.data.GoodType import java.io.IOException @Suppress("TooGenericExceptionCaught") class DetailScreenGoodViewModel( - private val goodId: Int, + private val goodType: GoodType, private val roomDatabase: AppDatabase, ) : ViewModel() { @@ -24,17 +24,26 @@ class DetailScreenGoodViewModel( viewModelScope.launch { try { - val result = roomDatabase.goodDao().getGoodById(goodId) + val result = when (goodType.type) { + GoodType.Type.GOOD -> { + val good = roomDatabase.goodDao().getGoodById(goodType.id) + DetailGood(id = good.goodId, name = good.name, about = good.about) + } - _uiState.value = DetailGoodUiState.Loaded( - DetailGoodItemUiState( + GoodType.Type.TOOL -> { + val tool = roomDatabase.toolDao().getToolById(goodType.id) + DetailGood(id = tool.toolId, name = tool.name, about = tool.about) + } + + GoodType.Type.GLASSWARE -> { + val glassware = roomDatabase.glasswareDao().getById(goodType.id) DetailGood( - id = GoodId(result.goodId), - name = result.name, - about = result.about + id = glassware.glasswareId, name = glassware.name, + about = glassware.about ) - ) - ) + } + } + _uiState.value = DetailGoodUiState.Loaded(DetailGoodItemUiState(result)) } catch (error: IOException) { _uiState.value = DetailGoodUiState.Error(error.toString()) } catch (error: Exception) { diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/tool/DetailScreenTool.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/tool/DetailScreenTool.kt deleted file mode 100644 index 2c08a3c..0000000 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/tool/DetailScreenTool.kt +++ /dev/null @@ -1,110 +0,0 @@ -package org.mixdrinks.mixdrinks.features.detail.ui.tool - -import android.util.Log -import androidx.compose.foundation.layout.Arrangement -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.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import coil.compose.AsyncImage -import org.koin.androidx.compose.koinViewModel -import org.koin.core.parameter.parametersOf -import org.mixdrinks.domain.ImageUrlCreators -import org.mixdrinks.mixdrinks.R -import org.mixdrinks.mixdrinks.features.common.ui.ErrorLoadingScreen -import org.mixdrinks.mixdrinks.features.common.ui.LoaderIndicatorScreen -import org.mixdrinks.mixdrinks.features.data.DetailTool -import org.mixdrinks.mixdrinks.features.detail.ui.Header - -@Composable -fun DetailScreenTool( - modifier: Modifier, - toolId: Int, - onBack: () -> Unit, - viewModel: DetailScreenToolViewModel = koinViewModel { parametersOf(toolId) }, -) { - val cocktail by viewModel.uiState.collectAsState() - - when(cocktail) { - is DetailScreenToolViewModel.DetailToolUiState.Loaded -> { - val data = (cocktail as DetailScreenToolViewModel.DetailToolUiState.Loaded).itemState - DetailScreenToolData(modifier = modifier, data.tool, onBack = onBack) - } - is DetailScreenToolViewModel.DetailToolUiState.Loading -> { - LoaderIndicatorScreen(modifier = modifier) - } - else -> { - val error = cocktail as DetailScreenToolViewModel.DetailToolUiState.Error - Log.d("Exception", error.message) - ErrorLoadingScreen(modifier = modifier) - } - } -} -@Suppress("MagicNumber") -@Composable -fun DetailScreenToolData(modifier: Modifier, tool: DetailTool, onBack: () -> Unit) { - Column( - modifier = modifier - .verticalScroll(rememberScrollState()) - .fillMaxWidth(1f) - .fillMaxHeight(1f) - .padding(10.dp) - ) { - Header( - modifier = modifier, - text = tool.name, - onClick = onBack - ) - Spacer(modifier = modifier.padding(5.dp)) - - AsyncImage( - model = ImageUrlCreators.createUrl( - toolId = tool.id, - ImageUrlCreators.Size.SIZE_320 - ), - contentDescription = null, - contentScale = ContentScale.FillHeight, - modifier = Modifier - .fillMaxWidth(1f) - .height(300.dp), - ) - Spacer(modifier = modifier.padding(top = 20.dp)) - - Row( - modifier = modifier - .fillMaxWidth(1f), - horizontalArrangement = Arrangement.Start - ) { - Text( - style = MaterialTheme.typography.h2, - text = "${stringResource(R.string.description)} ${tool.name}", - ) - } - Spacer(modifier = modifier.padding(15.dp)) - - Row( - modifier = modifier - .fillMaxWidth(1f), - horizontalArrangement = Arrangement.Start - ) { - Text( - style = MaterialTheme.typography.h3, - text = tool.about, - ) - } - } -} diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/tool/DetailScreenToolViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/tool/DetailScreenToolViewModel.kt deleted file mode 100644 index 6468b09..0000000 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/tool/DetailScreenToolViewModel.kt +++ /dev/null @@ -1,55 +0,0 @@ -package org.mixdrinks.mixdrinks.features.detail.ui.tool - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch -import org.mixdrinks.dto.ToolId -import org.mixdrinks.mixdrinks.database.AppDatabase -import org.mixdrinks.mixdrinks.features.data.DetailTool -import java.io.IOException - -@Suppress("TooGenericExceptionCaught") -class DetailScreenToolViewModel( - private val toolId: Int, - private val roomDatabase: AppDatabase, -) : ViewModel() { - - private val _uiState = MutableStateFlow(DetailToolUiState.Loading) - val uiState: StateFlow = _uiState - - init { - _uiState.value = DetailToolUiState.Loading - - viewModelScope.launch { - try { - val result = roomDatabase.toolDao().getToolById(toolId) - - _uiState.value = DetailToolUiState.Loaded( - DetailToolItemUiState( - DetailTool( - id = ToolId(result.toolId), - name = result.name, - about = result.about - ) - ) - ) - } catch (error: IOException) { - _uiState.value = DetailToolUiState.Error(error.toString()) - } catch (error: Exception) { - _uiState.value = DetailToolUiState.Error(error.toString()) - } - } - } - - sealed class DetailToolUiState { - object Loading : DetailToolUiState() - class Loaded(val itemState: DetailToolItemUiState) : DetailToolUiState() - class Error(val message: String) : DetailToolUiState() - } -} - -data class DetailToolItemUiState( - val tool: DetailTool -) From c48f264b3a9f415d5df86c6719bac334bae5df5d Mon Sep 17 00:00:00 2001 From: yura Date: Fri, 9 Jun 2023 16:49:03 +0300 Subject: [PATCH 12/20] code refactoring --- .../mixdrinks/features/detail/ui/good/DetailScreenGood.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGood.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGood.kt index 189f1b5..dd85fce 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGood.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGood.kt @@ -39,18 +39,18 @@ fun DetailScreenGood( onBack: () -> Unit, viewModel: DetailScreenGoodViewModel = koinViewModel { parametersOf(goodType) }, ) { - val cocktail by viewModel.uiState.collectAsState() + val good by viewModel.uiState.collectAsState() - when(cocktail) { + when(good) { is DetailScreenGoodViewModel.DetailGoodUiState.Loaded -> { - val data = (cocktail as DetailScreenGoodViewModel.DetailGoodUiState.Loaded).itemState + val data = (good as DetailScreenGoodViewModel.DetailGoodUiState.Loaded).itemState DetailScreenGoodData(modifier = modifier, data.good, onBack = onBack) } is DetailScreenGoodViewModel.DetailGoodUiState.Loading -> { LoaderIndicatorScreen(modifier = modifier) } else -> { - val error = cocktail as DetailScreenGoodViewModel.DetailGoodUiState.Error + val error = good as DetailScreenGoodViewModel.DetailGoodUiState.Error Log.d("Exception", error.message) ErrorLoadingScreen(modifier = modifier) } From 5ec9c3e82fba410a85f0b8ae276e59e7fd5a2671 Mon Sep 17 00:00:00 2001 From: yura Date: Tue, 13 Jun 2023 15:02:50 +0300 Subject: [PATCH 13/20] code refactoring --- .../main/java/org/mixdrinks/mixdrinks/App.kt | 4 ++-- .../mixdrinks/mixdrinks/app/MixDrinksApp.kt | 4 ++-- .../DetailScreenGoods.kt} | 18 +++++++++--------- .../DetailScreenGoodsViewModel.kt} | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) rename app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/{good/DetailScreenGood.kt => goods/DetailScreenGoods.kt} (83%) rename app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/{good/DetailScreenGoodViewModel.kt => goods/DetailScreenGoodsViewModel.kt} (96%) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/App.kt b/app/src/main/java/org/mixdrinks/mixdrinks/App.kt index d27ad9a..ebc7421 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/App.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/App.kt @@ -12,7 +12,7 @@ import org.mixdrinks.mixdrinks.database.AppDatabase import org.mixdrinks.mixdrinks.features.data.GoodType import org.mixdrinks.mixdrinks.features.data.MixDrinkService import org.mixdrinks.mixdrinks.features.detail.ui.cocktail.DetailScreenCocktailViewModel -import org.mixdrinks.mixdrinks.features.detail.ui.good.DetailScreenGoodViewModel +import org.mixdrinks.mixdrinks.features.detail.ui.goods.DetailScreenGoodsViewModel import org.mixdrinks.mixdrinks.features.fetcher.Fetcher import org.mixdrinks.mixdrinks.features.start.StartRepository import org.mixdrinks.mixdrinks.features.start.filter.ui.main.FilterScreenViewModel @@ -45,7 +45,7 @@ class App : Application() { viewModel { StartScreenViewModel(get(), get()) } viewModel { (id: Int) -> DetailScreenCocktailViewModel(cocktailId = id, get(), get()) } - viewModel { (goodType: GoodType) -> DetailScreenGoodViewModel(goodType = goodType, get()) } + viewModel { (goodType: GoodType) -> DetailScreenGoodsViewModel(goodType = goodType, get()) } viewModel { FilterScreenViewModel(get(), get()) } viewModel { (groupId: Int) -> diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt b/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt index 4b0c2cd..9b2320a 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/app/MixDrinksApp.kt @@ -9,7 +9,7 @@ import org.mixdrinks.mixdrinks.app.ui.theme.MixDrinksTheme import org.mixdrinks.mixdrinks.features.common.ui.NotFoundScreen import org.mixdrinks.mixdrinks.features.data.GoodType import org.mixdrinks.mixdrinks.features.detail.ui.cocktail.DetailScreen -import org.mixdrinks.mixdrinks.features.detail.ui.good.DetailScreenGood +import org.mixdrinks.mixdrinks.features.detail.ui.goods.DetailScreenGoods import org.mixdrinks.mixdrinks.features.start.filter.ui.main.FilterScreen import org.mixdrinks.mixdrinks.features.start.filter.ui.search.FilterSearchScreen import org.mixdrinks.mixdrinks.features.start.main.ui.StartScreen @@ -45,7 +45,7 @@ fun MixDrinksApp(modifier: Modifier = Modifier) { val goodType = backStackEntry.arguments?.getString(Routes.goodType) if (goodId != null && goodType != null) - DetailScreenGood( + DetailScreenGoods( modifier = modifier, goodType = GoodType(id = goodId.toInt(), GoodType.Type.fromString(goodType)), onBack = { navController.popBackStack() }) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGood.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/goods/DetailScreenGoods.kt similarity index 83% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGood.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/goods/DetailScreenGoods.kt index dd85fce..d1fe2fc 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGood.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/goods/DetailScreenGoods.kt @@ -1,4 +1,4 @@ -package org.mixdrinks.mixdrinks.features.detail.ui.good +package org.mixdrinks.mixdrinks.features.detail.ui.goods import android.util.Log import androidx.compose.foundation.layout.Arrangement @@ -33,24 +33,24 @@ import org.mixdrinks.mixdrinks.features.data.GoodType import org.mixdrinks.mixdrinks.features.detail.ui.Header @Composable -fun DetailScreenGood( +fun DetailScreenGoods( modifier: Modifier, goodType: GoodType, onBack: () -> Unit, - viewModel: DetailScreenGoodViewModel = koinViewModel { parametersOf(goodType) }, + viewModel: DetailScreenGoodsViewModel = koinViewModel { parametersOf(goodType) }, ) { val good by viewModel.uiState.collectAsState() when(good) { - is DetailScreenGoodViewModel.DetailGoodUiState.Loaded -> { - val data = (good as DetailScreenGoodViewModel.DetailGoodUiState.Loaded).itemState - DetailScreenGoodData(modifier = modifier, data.good, onBack = onBack) + is DetailScreenGoodsViewModel.DetailGoodUiState.Loaded -> { + val data = (good as DetailScreenGoodsViewModel.DetailGoodUiState.Loaded).itemState + DetailScreenGoodsData(modifier = modifier, data.good, onBack = onBack) } - is DetailScreenGoodViewModel.DetailGoodUiState.Loading -> { + is DetailScreenGoodsViewModel.DetailGoodUiState.Loading -> { LoaderIndicatorScreen(modifier = modifier) } else -> { - val error = good as DetailScreenGoodViewModel.DetailGoodUiState.Error + val error = good as DetailScreenGoodsViewModel.DetailGoodUiState.Error Log.d("Exception", error.message) ErrorLoadingScreen(modifier = modifier) } @@ -59,7 +59,7 @@ fun DetailScreenGood( @Suppress("MagicNumber") @Composable -fun DetailScreenGoodData(modifier: Modifier, good: DetailGood, onBack: () -> Unit) { +fun DetailScreenGoodsData(modifier: Modifier, good: DetailGood, onBack: () -> Unit) { Column( modifier = modifier .verticalScroll(rememberScrollState()) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGoodViewModel.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/goods/DetailScreenGoodsViewModel.kt similarity index 96% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGoodViewModel.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/goods/DetailScreenGoodsViewModel.kt index 60e9c21..4e19a02 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/good/DetailScreenGoodViewModel.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/goods/DetailScreenGoodsViewModel.kt @@ -1,4 +1,4 @@ -package org.mixdrinks.mixdrinks.features.detail.ui.good +package org.mixdrinks.mixdrinks.features.detail.ui.goods import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -11,7 +11,7 @@ import org.mixdrinks.mixdrinks.features.data.GoodType import java.io.IOException @Suppress("TooGenericExceptionCaught") -class DetailScreenGoodViewModel( +class DetailScreenGoodsViewModel( private val goodType: GoodType, private val roomDatabase: AppDatabase, ) : ViewModel() { From fd0ab2db04c7a0ced9967af95f522eae0599600d Mon Sep 17 00:00:00 2001 From: yura Date: Wed, 14 Jun 2023 15:01:30 +0300 Subject: [PATCH 14/20] code refactoring --- app/src/main/java/org/mixdrinks/mixdrinks/app/MainActivity.kt | 1 + .../mixdrinks/features/start/filter/ui/main/FilterScreen.kt | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/app/MainActivity.kt b/app/src/main/java/org/mixdrinks/mixdrinks/app/MainActivity.kt index 51fdc3d..dcf9311 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/app/MainActivity.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/app/MainActivity.kt @@ -14,3 +14,4 @@ class MainActivity : ComponentActivity() { } + diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt index 34c08c7..f1c6ab0 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt @@ -150,7 +150,8 @@ fun FilterScreenData( AddButton( modifier = modifier, text = filterGroup.name, - onClick = { onClickButtonAddAction(filterGroup.id) }) + onClick = { onClickButtonAddAction(filterGroup.id) } + ) } } } From 90507390dc77eb97955f0f85b97b67e6eade3349 Mon Sep 17 00:00:00 2001 From: yura Date: Wed, 14 Jun 2023 16:57:46 +0300 Subject: [PATCH 15/20] implementation FlowRow in filter screen --- .../start/filter/ui/main/FilterScreen.kt | 92 +++++++++++-------- 1 file changed, 55 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt index f1c6ab0..f15b772 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt @@ -6,6 +6,8 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -69,6 +71,7 @@ fun FilterScreen( } } +@OptIn(ExperimentalLayoutApi::class) @Suppress("LongMethod", "MagicNumber") @Composable fun FilterScreenData( @@ -107,7 +110,7 @@ fun FilterScreenData( } Spacer(modifier = modifier.padding(top = 10.dp)) - Box( + Row( modifier = modifier.weight(1f) ) { LazyColumn { @@ -118,42 +121,7 @@ fun FilterScreenData( text = filterGroup.name, style = MaterialTheme.typography.h2 ) - when { - (filterGroup.filters.size < 10) -> { - filterGroup.filters.forEach { item -> - FilterItem( - item, - onClick = { filterId -> - viewModel.checkedAction( - SelectedFilter( - filterId = filterId, - filterGroupId = filterGroup.id, - ) - ) - }) - } - } - - else -> { - filterGroup.filters.filter { it.checked }.forEach { item -> - FilterItem( - item, - onClick = { filterId -> - viewModel.checkedAction( - SelectedFilter( - filterId = filterId, - filterGroupId = filterGroup.id, - ) - ) - }) - } - AddButton( - modifier = modifier, - text = filterGroup.name, - onClick = { onClickButtonAddAction(filterGroup.id) } - ) - } - } + FilterItems(modifier = modifier, filtersGroup = filterGroup, viewModel = viewModel, onClickButtonAddAction = onClickButtonAddAction) } ) } @@ -162,6 +130,56 @@ fun FilterScreenData( } } +@OptIn(ExperimentalLayoutApi::class) +@Composable +private fun FilterItems( + modifier: Modifier, + filtersGroup: FilterGroupFull, + viewModel: FilterScreenViewModel, + onClickButtonAddAction: (groupId: Int) -> Unit +) { + FlowRow(modifier = modifier) { + when { + (filtersGroup.filters.size < 20) -> { + filtersGroup.filters.forEach { item -> + FilterItem( + item, + onClick = { filterId -> + viewModel.checkedAction( + SelectedFilter( + filterId = filterId, + filterGroupId = filtersGroup.id, + ) + ) + }) + } + + } + + else -> { + filtersGroup.filters.filter { it.checked }.forEach { item -> + FilterItem( + item, + onClick = { filterId -> + viewModel.checkedAction( + SelectedFilter( + filterId = filterId, + filterGroupId = filtersGroup.id, + ) + ) + }) + } + AddButton( + modifier = modifier, + text = filtersGroup.name, + onClick = { onClickButtonAddAction(filtersGroup.id) } + ) + } + } + } +} + + @Composable private fun FilterItem(item: FilterGroupFull.Filter, onClick: (id: Int) -> Unit) { OutlinedButton( From 1b24dcd41716b250a0e5e2800e8a4f6b3fde323b Mon Sep 17 00:00:00 2001 From: yura Date: Wed, 14 Jun 2023 17:12:49 +0300 Subject: [PATCH 16/20] implementation FlowRow in filter screen --- .../start/filter/ui/main/FilterScreen.kt | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt index f15b772..e617ee8 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt @@ -121,7 +121,12 @@ fun FilterScreenData( text = filterGroup.name, style = MaterialTheme.typography.h2 ) - FilterItems(modifier = modifier, filtersGroup = filterGroup, viewModel = viewModel, onClickButtonAddAction = onClickButtonAddAction) + FiltersItem( + modifier = modifier, + filtersGroup = filterGroup, + viewModel = viewModel, + onClickButtonAddAction = onClickButtonAddAction + ) } ) } @@ -132,7 +137,7 @@ fun FilterScreenData( @OptIn(ExperimentalLayoutApi::class) @Composable -private fun FilterItems( +private fun FiltersItem( modifier: Modifier, filtersGroup: FilterGroupFull, viewModel: FilterScreenViewModel, @@ -142,7 +147,7 @@ private fun FilterItems( when { (filtersGroup.filters.size < 20) -> { filtersGroup.filters.forEach { item -> - FilterItem( + ItemFlowRow( item, onClick = { filterId -> viewModel.checkedAction( @@ -151,14 +156,14 @@ private fun FilterItems( filterGroupId = filtersGroup.id, ) ) - }) + } + ) } - } else -> { filtersGroup.filters.filter { it.checked }.forEach { item -> - FilterItem( + ItemFlowRow( item, onClick = { filterId -> viewModel.checkedAction( @@ -167,7 +172,8 @@ private fun FilterItems( filterGroupId = filtersGroup.id, ) ) - }) + } + ) } AddButton( modifier = modifier, @@ -181,7 +187,7 @@ private fun FilterItems( @Composable -private fun FilterItem(item: FilterGroupFull.Filter, onClick: (id: Int) -> Unit) { +private fun ItemFlowRow(item: FilterGroupFull.Filter, onClick: (id: Int) -> Unit) { OutlinedButton( border = BorderStroke(1.dp, MaterialTheme.colors.primary), shape = RoundedCornerShape(18.dp), From 4a46d9aeb794c83c2c09fb83dcd3bde7c80c7d59 Mon Sep 17 00:00:00 2001 From: yura Date: Wed, 14 Jun 2023 17:14:07 +0300 Subject: [PATCH 17/20] code refactoring --- .../mixdrinks/features/start/filter/ui/main/FilterScreen.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt index e617ee8..1a90a24 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt @@ -70,9 +70,6 @@ fun FilterScreen( } } } - -@OptIn(ExperimentalLayoutApi::class) -@Suppress("LongMethod", "MagicNumber") @Composable fun FilterScreenData( modifier: Modifier, From 0486d5018b007ba80428fb62f002a47a3b687d8c Mon Sep 17 00:00:00 2001 From: yura Date: Wed, 14 Jun 2023 17:19:13 +0300 Subject: [PATCH 18/20] code refactoring --- .../mixdrinks/features/start/filter/ui/main/FilterScreen.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt index 1a90a24..c1b4136 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/main/FilterScreen.kt @@ -133,6 +133,7 @@ fun FilterScreenData( } @OptIn(ExperimentalLayoutApi::class) +@Suppress("MagicNumber") @Composable private fun FiltersItem( modifier: Modifier, From 603cf14840154ff3dabd28c195ca94a2c83c485f Mon Sep 17 00:00:00 2001 From: yura Date: Thu, 15 Jun 2023 14:24:01 +0300 Subject: [PATCH 19/20] added header --- .../mixdrinks/features/data/DetailGood.kt | 3 +- .../features/detail/ui/UiComponent.kt | 59 +++++++---- .../ui/cocktail/DetailScreenCocktail.kt | 99 ++++++++++--------- .../detail/ui/cocktail/GoodsListItem.kt | 13 ++- .../detail/ui/goods/DetailScreenGoods.kt | 84 ++++++++-------- .../features/start/StartRepository.kt | 8 +- .../filter/ui/search/FilterSearchScreen.kt | 2 +- .../start/main/ui/CocktailListItem.kt | 76 -------------- .../features/start/main/ui/StartScreen.kt | 61 +++++++++++- .../ui/header/{HeaderScreen.kt => Header.kt} | 2 +- .../drawable/baseline_arrow_back_ios_24.xml | 2 +- 11 files changed, 209 insertions(+), 200 deletions(-) delete mode 100644 app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/CocktailListItem.kt rename app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/header/{HeaderScreen.kt => Header.kt} (99%) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/DetailGood.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/DetailGood.kt index 7491f1b..26c8e6a 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/DetailGood.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/DetailGood.kt @@ -3,7 +3,8 @@ package org.mixdrinks.mixdrinks.features.data data class DetailGood( val id: Int, val name: String, - val about: String + val about: String, + ) data class GoodType( val id: Int, diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/UiComponent.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/UiComponent.kt index a92fb92..4323865 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/UiComponent.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/UiComponent.kt @@ -1,16 +1,19 @@ package org.mixdrinks.mixdrinks.features.detail.ui -import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +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.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.material.Icon -import androidx.compose.material.IconButton +import androidx.compose.foundation.layout.size import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource @@ -19,26 +22,40 @@ import org.mixdrinks.mixdrinks.R @Composable fun Header(modifier: Modifier, text: String, onClick: () -> Unit) { - Row( - modifier = modifier - .fillMaxWidth(1f), - horizontalArrangement = Arrangement.Start - ) { - IconButton( - modifier = modifier.height(24.dp), - onClick = { onClick() } + Column { + Row( + modifier = modifier + .background(MaterialTheme.colors.primary) + .fillMaxWidth() + .height(52.dp), ) { - Icon( - painter = painterResource(id = R.drawable.baseline_arrow_back_ios_24), - tint = Color.Black, - contentDescription = null + Box( + modifier = modifier.size(52.dp) + .clickable { + onClick() + } + ) { + Image( + modifier = modifier + .align(Alignment.Center) + .size(32.dp) + .padding(start = 12.dp), + painter = painterResource(R.drawable.baseline_arrow_back_ios_24), + contentDescription = "Test" + ) + } + Text( + modifier = modifier.padding(start = 4.dp) + .align(Alignment.CenterVertically), + color = Color.White, + text = text, + style = MaterialTheme.typography.h2, + softWrap = false, + maxLines = 1, ) } - Spacer(modifier = modifier.padding(start = 15.dp)) - Text( - text = text, - style = MaterialTheme.typography.h1 - ) } } + + diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt index 2a7aeb0..ca7d62b 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt @@ -79,64 +79,67 @@ fun DetailsScreenData( viewModel: DetailScreenCocktailViewModel, onClickTagAction: () -> Unit, ) { - Column( - modifier = modifier - .verticalScroll(rememberScrollState()) - .fillMaxWidth(1f) - .fillMaxHeight(1f) - .padding(10.dp) - ) { + Column { Header( modifier = modifier, text = data.cocktail.name, onClick = onBack ) - Spacer(modifier = modifier.padding(5.dp)) - - TagListItem( - modifier = modifier, - listTags = data.cocktail.tags, - onClickAction = { tagId -> - viewModel.onClickTag(tagId) - onClickTagAction() - } - ) - Spacer(modifier = modifier.padding(5.dp)) - - AsyncImage( - model = ImageUrlCreators.createUrl( - data.cocktail.id, - ImageUrlCreators.Size.SIZE_320 - ), - contentDescription = null, - contentScale = ContentScale.Crop, - modifier = Modifier + Column( + modifier = modifier + .verticalScroll(rememberScrollState()) .fillMaxWidth(1f) - .size(width = 300.dp, height = 200.dp), - ) - Spacer(modifier = modifier.padding(top = 20.dp)) + .fillMaxHeight(1f) + .padding(10.dp) + ) { + Spacer(modifier = modifier.padding(5.dp)) - CocktailRecipeContent( - modifier = modifier, - cocktailReceipt = data.cocktail.receipt - ) - Spacer(modifier = modifier.padding(top = 10.dp)) + TagListItem( + modifier = modifier, + listTags = data.cocktail.tags, + onClickAction = { tagId -> + viewModel.onClickTag(tagId) + onClickTagAction() + } + ) + Spacer(modifier = modifier.padding(5.dp)) + + AsyncImage( + model = ImageUrlCreators.createUrl( + data.cocktail.id, ImageUrlCreators.Size.SIZE_320 + ), + contentDescription = data.cocktail.name, + contentScale = ContentScale.Crop, + modifier = Modifier + .fillMaxWidth(1f) + .size(width = 300.dp, height = 200.dp), + ) + Spacer(modifier = modifier.padding(top = 20.dp)) - CocktailIngredientsContent( - modifier = modifier, - onClick = onNavigateToDetailGood, - viewModel = viewModel, - data = data - ) - Spacer(modifier = modifier.padding(top = 15.dp)) + CocktailRecipeContent( + modifier = modifier, + cocktailReceipt = data.cocktail.receipt + ) + Spacer(modifier = modifier.padding(top = 10.dp)) - CocktailToolsContent( - modifier = modifier, - cocktailTools = data.cocktail.tools, - glassware = data.cocktail.glassware, - onClick = onNavigateToDetailGood - ) + CocktailIngredientsContent( + modifier = modifier, + onClick = onNavigateToDetailGood, + viewModel = viewModel, + data = data + ) + Spacer(modifier = modifier.padding(top = 15.dp)) + + CocktailToolsContent( + modifier = modifier, + cocktailTools = data.cocktail.tools, + glassware = data.cocktail.glassware, + onClick = onNavigateToDetailGood + ) + } } + + } @Composable diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt index 5817990..1b71754 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt @@ -52,7 +52,8 @@ fun GoodsListItems( ) { ImageItem( modifier = modifier, - ImageUrlCreators.createUrl(item.id, ImageUrlCreators.Size.SIZE_320) + ImageUrlCreators.createUrl(item.id, ImageUrlCreators.Size.SIZE_320), + description = item.name ) Row( modifier = modifier @@ -131,10 +132,8 @@ fun ToolsListItem( ) { ImageItem( modifier = modifier, - ImageUrlCreators.createUrl( - GoodId(id), - ImageUrlCreators.Size.SIZE_320 - ) + ImageUrlCreators.createUrl(GoodId(id), ImageUrlCreators.Size.SIZE_320 ), + description = name ) Row( modifier = modifier @@ -152,7 +151,7 @@ fun ToolsListItem( @Composable -fun ImageItem(modifier: Modifier, url: String) { +private fun ImageItem(modifier: Modifier, url: String, description: String) { AsyncImage( modifier = modifier .border( @@ -162,7 +161,7 @@ fun ImageItem(modifier: Modifier, url: String) { .size(150.dp) .padding(5.dp), model = url, - contentDescription = null, + contentDescription = description, contentScale = ContentScale.Inside, ) } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/goods/DetailScreenGoods.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/goods/DetailScreenGoods.kt index d1fe2fc..4181811 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/goods/DetailScreenGoods.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/goods/DetailScreenGoods.kt @@ -41,14 +41,16 @@ fun DetailScreenGoods( ) { val good by viewModel.uiState.collectAsState() - when(good) { + when (good) { is DetailScreenGoodsViewModel.DetailGoodUiState.Loaded -> { val data = (good as DetailScreenGoodsViewModel.DetailGoodUiState.Loaded).itemState DetailScreenGoodsData(modifier = modifier, data.good, onBack = onBack) } + is DetailScreenGoodsViewModel.DetailGoodUiState.Loading -> { LoaderIndicatorScreen(modifier = modifier) } + else -> { val error = good as DetailScreenGoodsViewModel.DetailGoodUiState.Error Log.d("Exception", error.message) @@ -60,54 +62,56 @@ fun DetailScreenGoods( @Suppress("MagicNumber") @Composable fun DetailScreenGoodsData(modifier: Modifier, good: DetailGood, onBack: () -> Unit) { - Column( - modifier = modifier - .verticalScroll(rememberScrollState()) - .fillMaxWidth(1f) - .fillMaxHeight(1f) - .padding(10.dp) - ) { + Column { Header( modifier = modifier, text = good.name, onClick = onBack ) - Spacer(modifier = modifier.padding(5.dp)) - - AsyncImage( - model = ImageUrlCreators.createUrl( - GoodId(good.id), - ImageUrlCreators.Size.SIZE_320 - ), - contentDescription = null, - contentScale = ContentScale.FillHeight, - modifier = Modifier - .fillMaxWidth(1f) - .height(300.dp), - ) - Spacer(modifier = modifier.padding(top = 20.dp)) - - Row( + Column( modifier = modifier - .fillMaxWidth(1f), - horizontalArrangement = Arrangement.Start + .verticalScroll(rememberScrollState()) + .fillMaxWidth(1f) + .fillMaxHeight(1f) + .padding(10.dp) ) { - Text( - style = MaterialTheme.typography.h2, - text = "${stringResource(R.string.description)} ${good.name}" - ) - } - Spacer(modifier = modifier.padding(15.dp)) + Spacer(modifier = modifier.padding(5.dp)) - Row( - modifier = modifier - .fillMaxWidth(1f), - horizontalArrangement = Arrangement.Start - ) { - Text( - style = MaterialTheme.typography.h3, - text = good.about, + AsyncImage( + model = ImageUrlCreators.createUrl( + GoodId(good.id), + ImageUrlCreators.Size.SIZE_320 + ), + contentDescription = null, + contentScale = ContentScale.FillHeight, + modifier = Modifier + .fillMaxWidth(1f) + .height(300.dp), ) + Spacer(modifier = modifier.padding(top = 20.dp)) + + Row( + modifier = modifier + .fillMaxWidth(1f), + horizontalArrangement = Arrangement.Start + ) { + Text( + style = MaterialTheme.typography.h2, + text = "${stringResource(R.string.description)} ${good.name}" + ) + } + Spacer(modifier = modifier.padding(15.dp)) + + Row( + modifier = modifier + .fillMaxWidth(1f), + horizontalArrangement = Arrangement.Start + ) { + Text( + style = MaterialTheme.typography.h3, + text = good.about, + ) + } } } } diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/StartRepository.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/StartRepository.kt index a56e936..4b5d83b 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/StartRepository.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/StartRepository.kt @@ -17,9 +17,13 @@ class StartRepository( cocktailsFromDatabase = getCocktailFromDatabase() } cocktails = if (filterStorage.selectedFilters.value.isNotEmpty()) { - filterCocktail(cocktailsFromDatabase).map { CocktailShort(it.cocktailId, it.name) } + filterCocktail(cocktailsFromDatabase).map { + CocktailShort(it.cocktailId, it.name) + } } else { - cocktailsFromDatabase.map { CocktailShort(it.cocktailId, it.name) } + cocktailsFromDatabase.map { + CocktailShort(it.cocktailId, it.name) + } } return cocktails diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchScreen.kt index 84fbcf9..26fb9f1 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/filter/ui/search/FilterSearchScreen.kt @@ -203,7 +203,7 @@ private fun FilterItem( model = ImageUrlCreators.createUrl( CocktailId(filter.id), ImageUrlCreators.Size.SIZE_320 ), - contentDescription = null, + contentDescription = filter.name, contentScale = ContentScale.Crop, modifier = Modifier .clip(RoundedCornerShape(corner = CornerSize(8.dp))) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/CocktailListItem.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/CocktailListItem.kt deleted file mode 100644 index 130b10c..0000000 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/CocktailListItem.kt +++ /dev/null @@ -1,76 +0,0 @@ -package org.mixdrinks.mixdrinks.features.start.main.ui - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CornerSize -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Card -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import coil.compose.AsyncImage -import org.mixdrinks.domain.ImageUrlCreators -import org.mixdrinks.dto.CocktailId -import org.mixdrinks.mixdrinks.features.data.CocktailShort - -@Composable -fun CocktailListItem(modifier: Modifier, item: CocktailShort, onClickAction: (id: Int) -> Unit) { - Card( - modifier = modifier - .clickable { onClickAction(item.cocktailId) } - ) { - Row( - modifier = modifier.padding(10.dp), - ) { - ListItemImage(item.cocktailId) - ListItemInfo(modifier = modifier, item = item) - } - } -} - -@Composable -private fun ListItemImage(id: Int) { - AsyncImage( - model = ImageUrlCreators.createUrl( - CocktailId(id), - ImageUrlCreators.Size.SIZE_320 - ), - contentDescription = null, - contentScale = ContentScale.Crop, - modifier = Modifier - .clip(RoundedCornerShape(corner = CornerSize(16.dp))) - .size(100.dp), - ) -} - -@Composable -private fun ListItemInfo(modifier: Modifier, item: CocktailShort) { - Column( - modifier = modifier - .fillMaxWidth(1f), verticalArrangement = Arrangement.SpaceBetween - ) { - Row( - modifier = modifier - .padding(start = 10.dp) - ) { - Text( - text = item.name, - fontWeight = FontWeight.W700, - fontSize = 18.sp, - color = MaterialTheme.colors.primary, - ) - } - } -} - diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreen.kt index b42581b..554bcb8 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/StartScreen.kt @@ -1,21 +1,39 @@ package org.mixdrinks.mixdrinks.features.start.main.ui import android.util.Log +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +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.CornerSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Card +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import coil.compose.AsyncImage import org.koin.androidx.compose.koinViewModel +import org.mixdrinks.domain.ImageUrlCreators +import org.mixdrinks.dto.CocktailId import org.mixdrinks.mixdrinks.features.common.ui.ErrorLoadingScreen import org.mixdrinks.mixdrinks.features.common.ui.LoaderIndicatorScreen import org.mixdrinks.mixdrinks.features.common.ui.NotFoundScreen -import org.mixdrinks.mixdrinks.features.start.main.ui.header.HeaderScreen +import org.mixdrinks.mixdrinks.features.data.CocktailShort +import org.mixdrinks.mixdrinks.features.start.main.ui.header.Header @Composable fun StartScreen( @@ -61,7 +79,7 @@ fun StartScreenData( viewModel: StartScreenViewModel, ) { Column { - HeaderScreen( + Header( modifier = modifier, onNavigateToFilter = onNavigateToFilter, viewModel = viewModel, @@ -90,3 +108,42 @@ fun StartScreenData( } } } + +@Composable +fun CocktailListItem(modifier: Modifier, item: CocktailShort, onClickAction: (id: Int) -> Unit) { + Card( + modifier = modifier + .clickable { onClickAction(item.cocktailId) } + ) { + Row( + modifier = modifier.padding(10.dp), + ) { + AsyncImage( + model = ImageUrlCreators.createUrl( + CocktailId(item.cocktailId), ImageUrlCreators.Size.SIZE_320 + ), + contentDescription = item.name, + contentScale = ContentScale.Crop, + modifier = Modifier + .clip(RoundedCornerShape(corner = CornerSize(16.dp))) + .size(100.dp), + ) + Column( + modifier = modifier + .fillMaxWidth(1f), verticalArrangement = Arrangement.SpaceBetween + ) { + Row( + modifier = modifier + .padding(start = 10.dp) + ) { + Text( + text = item.name, + fontWeight = FontWeight.W700, + fontSize = 18.sp, + color = MaterialTheme.colors.primary, + ) + } + } + } + } +} diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/header/HeaderScreen.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/header/Header.kt similarity index 99% rename from app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/header/HeaderScreen.kt rename to app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/header/Header.kt index dac85a0..9a9a62d 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/header/HeaderScreen.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/start/main/ui/header/Header.kt @@ -23,7 +23,7 @@ import org.mixdrinks.mixdrinks.R import org.mixdrinks.mixdrinks.features.start.main.ui.StartScreenViewModel @Composable -fun HeaderScreen( +fun Header( modifier: Modifier, onNavigateToFilter: () -> Unit, viewModel: StartScreenViewModel, diff --git a/app/src/main/res/drawable/baseline_arrow_back_ios_24.xml b/app/src/main/res/drawable/baseline_arrow_back_ios_24.xml index 117a141..6c3197a 100644 --- a/app/src/main/res/drawable/baseline_arrow_back_ios_24.xml +++ b/app/src/main/res/drawable/baseline_arrow_back_ios_24.xml @@ -1,5 +1,5 @@ From a4419d90c32c66fb5d236fc33efb5ca04a2b4d01 Mon Sep 17 00:00:00 2001 From: yura Date: Fri, 16 Jun 2023 13:04:28 +0300 Subject: [PATCH 20/20] fixed ui --- .../features/data/FilterGroupFull.kt | 2 +- .../ui/cocktail/DetailScreenCocktail.kt | 60 +++++++++---------- .../detail/ui/cocktail/GoodsListItem.kt | 2 +- app/src/main/res/values-uk/strings.xml | 2 +- 4 files changed, 31 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/FilterGroupFull.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/FilterGroupFull.kt index 2309d81..c265d87 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/data/FilterGroupFull.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/data/FilterGroupFull.kt @@ -19,7 +19,7 @@ data class FilterGroupFull( data class SelectedFilter( val filterId: Int, - val filterGroupId: Int + val filterGroupId: Int, ) diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt index ca7d62b..e0d5049 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/DetailScreenCocktail.kt @@ -90,19 +90,15 @@ fun DetailsScreenData( .verticalScroll(rememberScrollState()) .fillMaxWidth(1f) .fillMaxHeight(1f) - .padding(10.dp) ) { - Spacer(modifier = modifier.padding(5.dp)) - TagListItem( - modifier = modifier, + modifier = modifier.padding(5.dp), listTags = data.cocktail.tags, onClickAction = { tagId -> viewModel.onClickTag(tagId) onClickTagAction() } ) - Spacer(modifier = modifier.padding(5.dp)) AsyncImage( model = ImageUrlCreators.createUrl( @@ -114,28 +110,28 @@ fun DetailsScreenData( .fillMaxWidth(1f) .size(width = 300.dp, height = 200.dp), ) - Spacer(modifier = modifier.padding(top = 20.dp)) - - CocktailRecipeContent( - modifier = modifier, - cocktailReceipt = data.cocktail.receipt - ) - Spacer(modifier = modifier.padding(top = 10.dp)) - - CocktailIngredientsContent( - modifier = modifier, - onClick = onNavigateToDetailGood, - viewModel = viewModel, - data = data - ) - Spacer(modifier = modifier.padding(top = 15.dp)) - - CocktailToolsContent( - modifier = modifier, - cocktailTools = data.cocktail.tools, - glassware = data.cocktail.glassware, - onClick = onNavigateToDetailGood - ) + Column(modifier = modifier.padding(5.dp)) { + CocktailRecipeContent( + modifier = modifier, + cocktailReceipt = data.cocktail.receipt + ) + Spacer(modifier = modifier.padding(top = 10.dp)) + + CocktailIngredientsContent( + modifier = modifier, + onClick = onNavigateToDetailGood, + viewModel = viewModel, + data = data + ) + Spacer(modifier = modifier.padding(top = 15.dp)) + + CocktailToolsContent( + modifier = modifier, + cocktailTools = data.cocktail.tools, + glassware = data.cocktail.glassware, + onClick = onNavigateToDetailGood + ) + } } } @@ -151,18 +147,18 @@ private fun CocktailIngredientsContent( ) { Row( modifier = modifier - .fillMaxWidth(1f), + .fillMaxWidth(1f) + .padding(bottom = 15.dp, top = 10.dp), horizontalArrangement = Arrangement.Start ) { Text( style = MaterialTheme.typography.h2, text = stringResource(R.string.cocktail_ingredients) ) - } + Spacer(modifier.weight(1f)) + CocktailPortions(modifier = modifier, viewModel = viewModel, data = data) - Spacer(modifier = modifier.padding(top = 15.dp)) - CocktailPortions(modifier = modifier, viewModel = viewModel, data = data) - Spacer(modifier = modifier.padding(bottom = 15.dp)) + } GoodsListItems( modifier = modifier, onClick = onClick, diff --git a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt index 1b71754..53e2198 100644 --- a/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt +++ b/app/src/main/java/org/mixdrinks/mixdrinks/features/detail/ui/cocktail/GoodsListItem.kt @@ -132,7 +132,7 @@ fun ToolsListItem( ) { ImageItem( modifier = modifier, - ImageUrlCreators.createUrl(GoodId(id), ImageUrlCreators.Size.SIZE_320 ), + ImageUrlCreators.createUrl(GoodId(id), ImageUrlCreators.Size.SIZE_320), description = name ) Row( diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 867085e..4ffbd08 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -2,7 +2,7 @@ Помилка підключення Рецепт - Склад + Інградієнти Інструменти Перегляди Пошук