From 323fac3f016bd8ccec57bb47da250d797eb7b37e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marlon=20L=C3=B3pez?= Date: Sat, 30 Mar 2024 17:49:24 -0500 Subject: [PATCH 1/3] feat(mobile-app): Added catalog details compact tabletop ui composables --- ...ctTableTopFoundCatalogDetailHeadingSlot.kt | 67 +++++++++++++++++++ .../slots/FoundCatalogDetailHeadingSlot.kt | 3 +- .../slots/FoundCatalogDetailPointsSlot.kt | 23 +++++-- 3 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/slots/CompactTableTopFoundCatalogDetailHeadingSlot.kt diff --git a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/slots/CompactTableTopFoundCatalogDetailHeadingSlot.kt b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/slots/CompactTableTopFoundCatalogDetailHeadingSlot.kt new file mode 100644 index 0000000..4518a19 --- /dev/null +++ b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/slots/CompactTableTopFoundCatalogDetailHeadingSlot.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2024 Marlonlom + * SPDX-License-Identifier: Apache-2.0 + */ + +package dev.marlonlom.apps.cappajv.features.catalog_detail.slots + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import dev.marlonlom.apps.cappajv.core.database.entities.CatalogItem +import dev.marlonlom.apps.cappajv.features.catalog_detail.parts.CatalogDetailButtonsBar +import dev.marlonlom.apps.cappajv.features.catalog_detail.parts.CatalogDetailImage +import dev.marlonlom.apps.cappajv.features.catalog_detail.parts.CatalogDetailProductCategoryText +import dev.marlonlom.apps.cappajv.features.catalog_detail.parts.CatalogDetailProductTitle +import dev.marlonlom.apps.cappajv.ui.main.AppContentCallbacks +import dev.marlonlom.apps.cappajv.ui.main.CappajvAppState + +/** + * CompactTabletopCatalogDetailHeadingSlot + * + * @author marlonlom + * + * @param appState Application ui state. + * @param appContentCallbacks Application content callbacks. + * @param product Catalog detailed information. + * @param isFavorite True/False if catalog detail item is favorite. + * @param onCatalogItemFavoriteChanged Action for catalog detail item favorite state changed. + * @param hingeRatio Hinge ratio for column height separation. + * @param contentHorizontalPadding Content horizontal padding. + * @param modifier Modifier for this composable. + */ +@Composable +internal fun CompactTableTopFoundCatalogDetailHeadingSlot( + appState: CappajvAppState, + appContentCallbacks: AppContentCallbacks, + product: CatalogItem, + isFavorite: Boolean, + onCatalogItemFavoriteChanged: (CatalogItem, Boolean) -> Unit, + hingeRatio: Float, + contentHorizontalPadding: Dp, + modifier: Modifier = Modifier +) = Column( + modifier = modifier + .fillMaxHeight(hingeRatio) + .padding(horizontal = contentHorizontalPadding), + verticalArrangement = Arrangement.spacedBy(10.dp), + horizontalAlignment = Alignment.CenterHorizontally, +) { + CatalogDetailImage(appState, product.title, product.picture) + CatalogDetailProductTitle(product, 30.dp, MaterialTheme.typography.titleLarge) + CatalogDetailProductCategoryText(product) + CatalogDetailButtonsBar( + appState = appState, + appContentCallbacks = appContentCallbacks, + product = product, + isFavorite = isFavorite, + onCatalogItemFavoriteChanged = onCatalogItemFavoriteChanged, + ) +} diff --git a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/slots/FoundCatalogDetailHeadingSlot.kt b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/slots/FoundCatalogDetailHeadingSlot.kt index 8cdc283..9f92c94 100644 --- a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/slots/FoundCatalogDetailHeadingSlot.kt +++ b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/slots/FoundCatalogDetailHeadingSlot.kt @@ -39,10 +39,11 @@ fun FoundCatalogDetailHeadingSlot( horizontalAlignment = Alignment.CenterHorizontally, ) { CatalogDetailImage( + appState = appState, title = product.title, picture = product.picture ) - CatalogDetailProductTitle(product) + CatalogDetailProductTitle(product = product) CatalogDetailProductCategoryText(product) CatalogDetailButtonsBar( appState = appState, diff --git a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/slots/FoundCatalogDetailPointsSlot.kt b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/slots/FoundCatalogDetailPointsSlot.kt index c7525ff..86cf6c5 100644 --- a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/slots/FoundCatalogDetailPointsSlot.kt +++ b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/slots/FoundCatalogDetailPointsSlot.kt @@ -38,14 +38,14 @@ import dev.marlonlom.apps.cappajv.ui.main.CappajvAppState * @author marlonlom * * @param appState Application ui state. - * @param points Catalog item points information + * @param punctuations Catalog item points information * @param modifier Modifier for this composable. */ @ExperimentalFoundationApi @Composable fun FoundCatalogDetailPointsSlot( appState: CappajvAppState, - points: List, + punctuations: List, modifier: Modifier = Modifier, ) { Text( @@ -59,19 +59,28 @@ fun FoundCatalogDetailPointsSlot( textAlign = TextAlign.Center, style = MaterialTheme.typography.bodyMedium, ) - points.forEach { catalogPunctuation -> + punctuations.forEach { catalogPunctuation -> CatalogPunctuationItemCard( appState = appState, - catalogPunctuation = catalogPunctuation, + punctuation = catalogPunctuation, ) } Spacer(Modifier.height(20.dp)) } +/** + * Catalog punctuation item card composable ui. + * + * @author marlonlom + * + * @param appState Application ui state. + * @param punctuation Catalog item points information + * @param modifier Modifier for this composable. + */ @Composable fun CatalogPunctuationItemCard( appState: CappajvAppState, - catalogPunctuation: CatalogPunctuation, + punctuation: CatalogPunctuation, modifier: Modifier = Modifier, ) { Row( @@ -89,12 +98,12 @@ fun CatalogPunctuationItemCard( ) Column { Text( - text = "${catalogPunctuation.points} pts", + text = "${punctuation.points} pts", color = MaterialTheme.colorScheme.primary, fontWeight = FontWeight.Bold, style = MaterialTheme.typography.titleLarge ) - Text(text = catalogPunctuation.label) + Text(text = punctuation.label) } } } From 1062ebc774b41e9562e02bb373156043a4546e61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marlon=20L=C3=B3pez?= Date: Sat, 30 Mar 2024 17:50:40 -0500 Subject: [PATCH 2/3] feat(mobile-app): Update catalog details compact tabletop ui composable parts --- .../parts/CatalogDetailButtonsBar.kt | 2 +- .../parts/CatalogDetailImage.kt | 20 ++++++++++++++++++- .../parts/CatalogDetailTexts.kt | 12 ++++++++--- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/parts/CatalogDetailButtonsBar.kt b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/parts/CatalogDetailButtonsBar.kt index 73f145a..5cd63d6 100644 --- a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/parts/CatalogDetailButtonsBar.kt +++ b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/parts/CatalogDetailButtonsBar.kt @@ -50,7 +50,7 @@ fun CatalogDetailButtonsBar( ) { Row( modifier = Modifier - .padding(top = 20.dp, bottom = 10.dp), + .padding(vertical = 5.dp), horizontalArrangement = Arrangement.spacedBy(16.dp), verticalAlignment = Alignment.CenterVertically, ) { diff --git a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/parts/CatalogDetailImage.kt b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/parts/CatalogDetailImage.kt index 75af4a3..cbcc728 100644 --- a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/parts/CatalogDetailImage.kt +++ b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/parts/CatalogDetailImage.kt @@ -19,18 +19,23 @@ import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import coil.compose.AsyncImage import coil.request.ImageRequest +import dev.marlonlom.apps.cappajv.ui.layout.DevicePosture +import dev.marlonlom.apps.cappajv.ui.main.CappajvAppState +import dev.marlonlom.apps.cappajv.ui.main.scaffold.ScaffoldContentType /** * Catalog favorite item card image composable. * * @author marlonlom * + * @param appState Application ui state. * @param title Title for content description. * @param picture Image picture url. * @param modifier Modifier for this composable. */ @Composable fun CatalogDetailImage( + appState: CappajvAppState, title: String, picture: String, modifier: Modifier = Modifier, @@ -44,7 +49,7 @@ fun CatalogDetailImage( shape = MaterialTheme.shapes.medium, ) .clip(MaterialTheme.shapes.medium) - .size(DpSize(184.dp, 240.dp)) + .size(catalogDetailImageDpSize(appState)) .background(Color.White) AsyncImage( @@ -54,3 +59,16 @@ fun CatalogDetailImage( modifier = imageModifier, ) } + +@Composable +private fun catalogDetailImageDpSize( + appState: CappajvAppState +) = when { + appState.isCompactWidth + .and(appState.scaffoldContentType == ScaffoldContentType.SinglePane) + .and(appState.isLandscape.not()).and( + appState.devicePosture is DevicePosture.Separating.TableTop + ) -> DpSize(112.dp, 160.dp) + + else -> DpSize(184.dp, 240.dp) +} diff --git a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/parts/CatalogDetailTexts.kt b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/parts/CatalogDetailTexts.kt index daaba7e..ad39a26 100644 --- a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/parts/CatalogDetailTexts.kt +++ b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/parts/CatalogDetailTexts.kt @@ -12,8 +12,10 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import dev.marlonlom.apps.cappajv.core.database.entities.CatalogItem @@ -39,15 +41,19 @@ internal fun CatalogDetailProductCategoryText(product: CatalogItem) { } @Composable -internal fun CatalogDetailProductTitle(product: CatalogItem) { +internal fun CatalogDetailProductTitle( + product: CatalogItem, + topBaselinePadding: Dp = 60.dp, + titleTextStyle: TextStyle = MaterialTheme.typography.headlineLarge +) { Text( modifier = Modifier .fillMaxWidth() - .paddingFromBaseline(60.dp, 10.dp), + .paddingFromBaseline(topBaselinePadding, 10.dp), textAlign = TextAlign.Center, text = product.title, fontWeight = FontWeight.Bold, - style = MaterialTheme.typography.headlineLarge + style = titleTextStyle ) } From a30c24a8ad7512d8ba0c71471a851137ff11b90e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marlon=20L=C3=B3pez?= Date: Sat, 30 Mar 2024 17:51:27 -0500 Subject: [PATCH 3/3] feat(mobile-app): Add catalog details compact tabletop ui composable screens --- .../screens/CatalogDetailRouteScreen.kt | 17 ++++ .../CompactTableTopCatalogDetailScreen.kt | 61 +++++++++++++ ...CompactTableTopFoundCatalogDetailScreen.kt | 85 +++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/screens/CompactTableTopCatalogDetailScreen.kt create mode 100644 apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/screens/CompactTableTopFoundCatalogDetailScreen.kt diff --git a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/screens/CatalogDetailRouteScreen.kt b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/screens/CatalogDetailRouteScreen.kt index 88c0540..1f8a289 100644 --- a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/screens/CatalogDetailRouteScreen.kt +++ b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/screens/CatalogDetailRouteScreen.kt @@ -9,8 +9,10 @@ import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.runtime.Composable import dev.marlonlom.apps.cappajv.core.database.entities.CatalogItem import dev.marlonlom.apps.cappajv.features.catalog_detail.CatalogDetailUiState +import dev.marlonlom.apps.cappajv.ui.layout.DevicePosture import dev.marlonlom.apps.cappajv.ui.main.AppContentCallbacks import dev.marlonlom.apps.cappajv.ui.main.CappajvAppState +import dev.marlonlom.apps.cappajv.ui.main.scaffold.ScaffoldContentType /** * Catalog detail route screen content composable ui. @@ -32,6 +34,21 @@ fun CatalogDetailRouteScreen( isRouting: Boolean, onCatalogItemFavoriteChanged: (CatalogItem, Boolean) -> Unit, ) = when { + + appState.isCompactWidth + .and(appState.scaffoldContentType == ScaffoldContentType.SinglePane) + .and(appState.isLandscape.not()).and( + appState.devicePosture is DevicePosture.Separating.TableTop + ) -> { + CompactTableTopCatalogDetailScreen( + appState = appState, + appContentCallbacks = appContentCallbacks, + detailUiState = detailUiState, + isRouting = isRouting, + onCatalogItemFavoriteChanged = onCatalogItemFavoriteChanged + ) + } + else -> DefaultPortraitCatalogDetailScreen( appState = appState, appContentCallbacks = appContentCallbacks, diff --git a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/screens/CompactTableTopCatalogDetailScreen.kt b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/screens/CompactTableTopCatalogDetailScreen.kt new file mode 100644 index 0000000..6b7aa8a --- /dev/null +++ b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/screens/CompactTableTopCatalogDetailScreen.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2024 Marlonlom + * SPDX-License-Identifier: Apache-2.0 + */ + +package dev.marlonlom.apps.cappajv.features.catalog_detail.screens + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.unit.dp +import dev.marlonlom.apps.cappajv.core.database.entities.CatalogItem +import dev.marlonlom.apps.cappajv.features.catalog_detail.CatalogDetailUiState +import dev.marlonlom.apps.cappajv.ui.layout.DevicePosture +import dev.marlonlom.apps.cappajv.ui.main.AppContentCallbacks +import dev.marlonlom.apps.cappajv.ui.main.CappajvAppState + +/** + * TableTop catalog detail screen composable ui. + * + * @author marlonlom + * + * @param appState Application ui state. + * @param appContentCallbacks Application content callbacks. + * @param detailUiState Catalog detail ui state. + * @param isRouting True/False if should navigate through routing. + * @param onCatalogItemFavoriteChanged Action for catalog detail item favorite state changed. + */ +@ExperimentalFoundationApi +@Composable +fun CompactTableTopCatalogDetailScreen( + appState: CappajvAppState, + appContentCallbacks: AppContentCallbacks, + detailUiState: CatalogDetailUiState, + isRouting: Boolean, + onCatalogItemFavoriteChanged: (CatalogItem, Boolean) -> Unit, +) { + val contentHorizontalPadding = when { + appState.isLandscape.not().and(appState.isMediumWidth) -> 40.dp + appState.isLandscape.not().and(appState.isExpandedWidth) -> 80.dp + else -> 20.dp + } + + val hingeRatio = (appState.devicePosture as DevicePosture.Separating.TableTop).hingeRatio + + when (detailUiState) { + is CatalogDetailUiState.Found -> { + CompactTableTopFoundCatalogDetailScreen( + appState = appState, + appContentCallbacks = appContentCallbacks, + foundDetail = detailUiState, + isRouting = isRouting, + onCatalogItemFavoriteChanged = onCatalogItemFavoriteChanged, + contentHorizontalPadding = contentHorizontalPadding, + hingeRatio = hingeRatio + ) + } + + CatalogDetailUiState.NotFound -> Text("Select from list for view its detailed information.") + } +} diff --git a/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/screens/CompactTableTopFoundCatalogDetailScreen.kt b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/screens/CompactTableTopFoundCatalogDetailScreen.kt new file mode 100644 index 0000000..bcfd360 --- /dev/null +++ b/apps/mobile-app/src/main/kotlin/dev/marlonlom/apps/cappajv/features/catalog_detail/screens/CompactTableTopFoundCatalogDetailScreen.kt @@ -0,0 +1,85 @@ +/* + * Copyright 2024 Marlonlom + * SPDX-License-Identifier: Apache-2.0 + */ + +package dev.marlonlom.apps.cappajv.features.catalog_detail.screens + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.Dp +import dev.marlonlom.apps.cappajv.core.database.entities.CatalogItem +import dev.marlonlom.apps.cappajv.features.catalog_detail.CatalogDetailUiState +import dev.marlonlom.apps.cappajv.features.catalog_detail.parts.CatalogDetailProductDescriptionText +import dev.marlonlom.apps.cappajv.features.catalog_detail.parts.CatalogDetailTopBar +import dev.marlonlom.apps.cappajv.features.catalog_detail.slots.CompactTableTopFoundCatalogDetailHeadingSlot +import dev.marlonlom.apps.cappajv.features.catalog_detail.slots.FoundCatalogDetailPointsSlot +import dev.marlonlom.apps.cappajv.ui.main.AppContentCallbacks +import dev.marlonlom.apps.cappajv.ui.main.CappajvAppState + +/** + * Compact tabletop found catalog detail screen composable. + * + * @author marlonlom + * + * @param appState Application ui state. + * @param appContentCallbacks Application content callbacks. + * @param foundDetail Found details ui state. + * @param isRouting True/False if should navigate through routing. + * @param onCatalogItemFavoriteChanged Action for catalog detail item favorite state changed. + * @param contentHorizontalPadding Content horizontal padding. + * @param hingeRatio Hinge ratio for column height separation. + * @param modifier Modifier for this composable. + */ +@ExperimentalFoundationApi +@Composable +fun CompactTableTopFoundCatalogDetailScreen( + appState: CappajvAppState, + appContentCallbacks: AppContentCallbacks, + foundDetail: CatalogDetailUiState.Found, + isRouting: Boolean, + onCatalogItemFavoriteChanged: (CatalogItem, Boolean) -> Unit, + contentHorizontalPadding: Dp, + hingeRatio: Float, + modifier: Modifier = Modifier +) { + val (product, isFavorite, points) = foundDetail.detail + + Column( + modifier = modifier + .fillMaxWidth() + .padding(horizontal = contentHorizontalPadding) + ) { + CatalogDetailTopBar(appState, isRouting) + + CompactTableTopFoundCatalogDetailHeadingSlot( + appState = appState, + appContentCallbacks = appContentCallbacks, + product = product, + isFavorite = isFavorite, + onCatalogItemFavoriteChanged = onCatalogItemFavoriteChanged, + hingeRatio = hingeRatio, + contentHorizontalPadding = contentHorizontalPadding + ) + + Column( + modifier = modifier + .verticalScroll(rememberScrollState()) + .fillMaxSize() + .background(MaterialTheme.colorScheme.surface) + .padding(horizontal = contentHorizontalPadding) + ) { + CatalogDetailProductDescriptionText(product) + FoundCatalogDetailPointsSlot(appState, points) + } + } +}