Successfully created and wrote to new file: /home/Messier82/projects/service-book/app/src/main/java/com/servicebook/ui/components/PaywallInfoSheet.kt. Here is the updated code: package com.servicebook.ui.components import androidx.compose.foundation.layout.Column 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.foundation.layout.size import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.HourglassTop import androidx.compose.material.icons.outlined.Lock import androidx.compose.material3.Button import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.servicebook.R /** * A modal bottom sheet that explains the paywall and offers an upgrade path. * This is the single source of upgrade routing. * * @param isPending Whether a purchase is currently pending. * @param onUpgradeClick Called when the user taps the primary upgrade button. * @param onDismissRequest Called when the sheet should be dismissed. */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun PaywallInfoSheet( isPending: Boolean, onUpgradeClick: () -> Unit, onDismissRequest: () -> Unit, ) { val sheetState = rememberModalBottomSheetState() ModalBottomSheet( onDismissRequest = onDismissRequest, sheetState = sheetState, dragHandle = { androidx.compose.material3.BottomSheetDefaults.DragHandle() }, modifier = Modifier.testTag("paywall-info-sheet"), ) { Column( modifier = Modifier .fillMaxWidth() .padding(24.dp) .padding(bottom = 24.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { Icon( imageVector = if (isPending) Icons.Outlined.HourglassTop else Icons.Outlined.Lock, contentDescription = null, modifier = Modifier.size(32.dp), tint = MaterialTheme.colorScheme.primary, ) Spacer(Modifier.height(16.dp)) Text( text = stringResource( if (isPending) R.string.paywall_pending_headline else R.string.paywall_card_headline, ), style = MaterialTheme.typography.headlineSmall, textAlign = TextAlign.Center, ) Spacer(Modifier.height(12.dp)) Text( text = stringResource( if (isPending) R.string.paywall_pending_body else R.string.paywall_sheet_body, ), style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, textAlign = TextAlign.Center, ) Spacer(Modifier.height(32.dp)) if (isPending) { Button( onClick = onDismissRequest, modifier = Modifier.fillMaxWidth(), ) { Text(stringResource(R.string.action_ok)) } } else { Button( onClick = { onDismissRequest() onUpgradeClick() }, modifier = Modifier.fillMaxWidth(), ) { Text(stringResource(R.string.action_upgrade_premium)) } Spacer(Modifier.height(8.dp)) TextButton( onClick = onDismissRequest, modifier = Modifier.fillMaxWidth(), ) { Text(stringResource(R.string.action_maybe_later)) } } } } }