diff --git a/README.md b/README.md index ae1ae2e..205382e 100644 --- a/README.md +++ b/README.md @@ -5,15 +5,12 @@ This app contains an order flow for cupcakes with options for quantity, flavor, The order details get displayed on an order summary screen and can be shared to another app to send the order. -TODO - Pre-requisites -------------- * Experience with Kotlin syntax. * How to create and run a project in Android Studio. * How to create composable functions -* TODO Getting Started diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 924a7ac..28abb3d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -20,12 +20,12 @@ plugins { android { namespace = "com.example.cupcake" - compileSdk = 33 + compileSdk = 34 defaultConfig { applicationId = "com.example.cupcake" minSdk = 24 - targetSdk = 33 + targetSdk = 34 versionCode = 1 versionName = "1.0" @@ -56,7 +56,7 @@ android { compose = true } composeOptions { - kotlinCompilerExtensionVersion = "1.4.7" + kotlinCompilerExtensionVersion = "1.5.3" } packaging { resources { @@ -67,24 +67,24 @@ android { dependencies { - implementation(platform("androidx.compose:compose-bom:2023.05.01")) - implementation("androidx.activity:activity-compose:1.7.2") + implementation(platform("androidx.compose:compose-bom:2023.10.01")) + implementation("androidx.activity:activity-compose:1.8.0") implementation("androidx.compose.material3:material3") implementation("androidx.compose.runtime:runtime") implementation("androidx.compose.runtime:runtime-livedata") implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-tooling-preview") - implementation("androidx.core:core-ktx:1.10.1") + implementation("androidx.core:core-ktx:1.12.0") implementation("androidx.lifecycle:lifecycle-livedata-ktx:${rootProject.extra["lifecycle_version"]}") implementation("androidx.lifecycle:lifecycle-runtime-ktx:${rootProject.extra["lifecycle_version"]}") implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:${rootProject.extra["lifecycle_version"]}") implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:${rootProject.extra["lifecycle_version"]}") - implementation("androidx.navigation:navigation-compose:2.6.0") + implementation("androidx.navigation:navigation-compose:2.7.4") - androidTestImplementation(platform("androidx.compose:compose-bom:2023.05.01")) + androidTestImplementation(platform("androidx.compose:compose-bom:2023.10.01")) androidTestImplementation("androidx.compose.ui:ui-test-junit4") - androidTestImplementation("androidx.navigation:navigation-testing:2.6.0") + androidTestImplementation("androidx.navigation:navigation-testing:2.7.4") androidTestImplementation("androidx.test.espresso:espresso-intents:3.5.1") androidTestImplementation("androidx.test.ext:junit:1.1.5") diff --git a/app/src/main/java/com/example/cupcake/CupcakeScreen.kt b/app/src/main/java/com/example/cupcake/CupcakeScreen.kt index dbb1e8c..86e8eaf 100644 --- a/app/src/main/java/com/example/cupcake/CupcakeScreen.kt +++ b/app/src/main/java/com/example/cupcake/CupcakeScreen.kt @@ -21,6 +21,8 @@ import androidx.annotation.StringRes import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material3.Icon @@ -115,7 +117,10 @@ fun CupcakeApp( NavHost( navController = navController, startDestination = CupcakeScreen.Start.name, - modifier = Modifier.padding(innerPadding) + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .padding(innerPadding) ) { composable(route = CupcakeScreen.Start.name) { StartOrderScreen( diff --git a/app/src/main/java/com/example/cupcake/MainActivity.kt b/app/src/main/java/com/example/cupcake/MainActivity.kt index 22b231a..e71fc31 100644 --- a/app/src/main/java/com/example/cupcake/MainActivity.kt +++ b/app/src/main/java/com/example/cupcake/MainActivity.kt @@ -18,13 +18,13 @@ package com.example.cupcake import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.core.view.WindowCompat +import androidx.activity.enableEdgeToEdge import com.example.cupcake.ui.theme.CupcakeTheme class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { + enableEdgeToEdge() super.onCreate(savedInstanceState) - WindowCompat.setDecorFitsSystemWindows(window, false) setContent { CupcakeTheme { CupcakeApp() diff --git a/app/src/main/java/com/example/cupcake/ui/SelectOptionScreen.kt b/app/src/main/java/com/example/cupcake/ui/SelectOptionScreen.kt index a5d7df1..4420efd 100644 --- a/app/src/main/java/com/example/cupcake/ui/SelectOptionScreen.kt +++ b/app/src/main/java/com/example/cupcake/ui/SelectOptionScreen.kt @@ -39,6 +39,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import com.example.cupcake.R import com.example.cupcake.ui.components.FormattedPriceLabel +import com.example.cupcake.ui.theme.CupcakeTheme /** * Composable that displays the list of items as [RadioButton] options, @@ -54,14 +55,14 @@ fun SelectOptionScreen( onCancelButtonClicked: () -> Unit = {}, onNextButtonClicked: () -> Unit = {}, modifier: Modifier = Modifier -){ +) { var selectedValue by rememberSaveable { mutableStateOf("") } Column( modifier = modifier, verticalArrangement = Arrangement.SpaceBetween ) { - Column(modifier = Modifier.padding(dimensionResource(R.dimen.padding_medium))){ + Column(modifier = Modifier.padding(dimensionResource(R.dimen.padding_medium))) { options.forEach { item -> Row( modifier = Modifier.selectable( @@ -72,7 +73,7 @@ fun SelectOptionScreen( } ), verticalAlignment = Alignment.CenterVertically - ){ + ) { RadioButton( selected = selectedValue == item, onClick = { @@ -100,12 +101,14 @@ fun SelectOptionScreen( Row( modifier = Modifier .fillMaxWidth() - .padding(dimensionResource(R.dimen.padding_medium)) - .weight(1f, false), + .padding(dimensionResource(R.dimen.padding_medium)), horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.padding_medium)), verticalAlignment = Alignment.Bottom - ){ - OutlinedButton(modifier = Modifier.weight(1f), onClick = onCancelButtonClicked) { + ) { + OutlinedButton( + modifier = Modifier.weight(1f), + onClick = onCancelButtonClicked + ) { Text(stringResource(R.string.cancel)) } Button( @@ -123,10 +126,12 @@ fun SelectOptionScreen( @Preview @Composable -fun SelectOptionPreview(){ - SelectOptionScreen( - subtotal = "299.99", - options = listOf("Option 1", "Option 2", "Option 3", "Option 4"), - modifier = Modifier.fillMaxHeight() - ) +fun SelectOptionPreview() { + CupcakeTheme { + SelectOptionScreen( + subtotal = "299.99", + options = listOf("Option 1", "Option 2", "Option 3", "Option 4"), + modifier = Modifier.fillMaxHeight() + ) + } } diff --git a/app/src/main/java/com/example/cupcake/ui/StartOrderScreen.kt b/app/src/main/java/com/example/cupcake/ui/StartOrderScreen.kt index 036b29d..6b9c833 100644 --- a/app/src/main/java/com/example/cupcake/ui/StartOrderScreen.kt +++ b/app/src/main/java/com/example/cupcake/ui/StartOrderScreen.kt @@ -19,9 +19,7 @@ import androidx.annotation.StringRes import androidx.compose.foundation.Image 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.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height @@ -41,6 +39,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.example.cupcake.R import com.example.cupcake.data.DataSource +import com.example.cupcake.ui.theme.CupcakeTheme /** * Composable that allows the user to select the desired cupcake quantity and expects @@ -52,7 +51,7 @@ fun StartOrderScreen( quantityOptions: List>, onNextButtonClicked: (Int) -> Unit, modifier: Modifier = Modifier -){ +) { Column( modifier = modifier, verticalArrangement = Arrangement.SpaceBetween @@ -75,20 +74,19 @@ fun StartOrderScreen( ) Spacer(modifier = Modifier.height(dimensionResource(R.dimen.padding_small))) } - Row(modifier = Modifier.weight(1f, false)) { - Column( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy( - dimensionResource(id = R.dimen.padding_medium) + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy( + dimensionResource(id = R.dimen.padding_medium) + ) + ) { + quantityOptions.forEach { item -> + SelectQuantityButton( + labelResourceId = item.first, + onClick = { onNextButtonClicked(item.second) }, + modifier = Modifier.fillMaxWidth(), ) - ) { - quantityOptions.forEach { item -> - SelectQuantityButton( - labelResourceId = item.first, - onClick = { onNextButtonClicked(item.second) } - ) - } } } } @@ -103,7 +101,7 @@ fun SelectQuantityButton( @StringRes labelResourceId: Int, onClick: () -> Unit, modifier: Modifier = Modifier -){ +) { Button( onClick = onClick, modifier = modifier.widthIn(min = 250.dp) @@ -114,10 +112,14 @@ fun SelectQuantityButton( @Preview @Composable -fun StartOrderPreview(){ - StartOrderScreen( - quantityOptions = DataSource.quantityOptions, - onNextButtonClicked = {}, - modifier = Modifier.fillMaxSize().padding(dimensionResource(R.dimen.padding_medium)) - ) +fun StartOrderPreview() { + CupcakeTheme { + StartOrderScreen( + quantityOptions = DataSource.quantityOptions, + onNextButtonClicked = {}, + modifier = Modifier + .fillMaxSize() + .padding(dimensionResource(R.dimen.padding_medium)) + ) + } } diff --git a/app/src/main/java/com/example/cupcake/ui/SummaryScreen.kt b/app/src/main/java/com/example/cupcake/ui/SummaryScreen.kt index cd8c75a..1fae196 100644 --- a/app/src/main/java/com/example/cupcake/ui/SummaryScreen.kt +++ b/app/src/main/java/com/example/cupcake/ui/SummaryScreen.kt @@ -38,6 +38,7 @@ import androidx.compose.ui.tooling.preview.Preview import com.example.cupcake.R import com.example.cupcake.data.OrderUiState import com.example.cupcake.ui.components.FormattedPriceLabel +import com.example.cupcake.ui.theme.CupcakeTheme /** * This composable expects [orderUiState] that represents the order state, [onCancelButtonClicked] @@ -50,7 +51,7 @@ fun OrderSummaryScreen( onCancelButtonClicked: () -> Unit, onSendButtonClicked: (String, String) -> Unit, modifier: Modifier = Modifier -){ +) { val resources = LocalContext.current.resources val numberOfCupcakes = resources.getQuantityString( @@ -97,9 +98,7 @@ fun OrderSummaryScreen( ) } Row( - modifier = Modifier - .weight(1f, false) - .padding(dimensionResource(R.dimen.padding_medium)) + modifier = Modifier.padding(dimensionResource(R.dimen.padding_medium)) ) { Column( verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.padding_small)) @@ -123,11 +122,13 @@ fun OrderSummaryScreen( @Preview @Composable -fun OrderSummaryPreview(){ - OrderSummaryScreen( - orderUiState = OrderUiState(0, "Test", "Test", "$300.00"), - onSendButtonClicked = { subject: String, summary: String -> }, - onCancelButtonClicked = {}, - modifier = Modifier.fillMaxHeight() - ) +fun OrderSummaryPreview() { + CupcakeTheme { + OrderSummaryScreen( + orderUiState = OrderUiState(0, "Test", "Test", "$300.00"), + onSendButtonClicked = { subject: String, summary: String -> }, + onCancelButtonClicked = {}, + modifier = Modifier.fillMaxHeight() + ) + } } diff --git a/build.gradle.kts b/build.gradle.kts index 3a8f034..02c3cc7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,11 +16,11 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { extra.apply { - set("lifecycle_version", "2.6.1") + set("lifecycle_version", "2.6.2") } } plugins { - id("com.android.application") version "8.0.2" apply false - id("com.android.library") version "8.0.2" apply false - id("org.jetbrains.kotlin.android") version "1.8.21" apply false + id("com.android.application") version "8.1.2" apply false + id("com.android.library") version "8.1.2" apply false + id("org.jetbrains.kotlin.android") version "1.9.10" apply false } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3148757..d626975 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Sun Mar 19 17:30:22 PDT 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists