diff --git a/app/src/main/java/com/android/trisolarispms/ui/common/ScreenChrome.kt b/app/src/main/java/com/android/trisolarispms/ui/common/ScreenChrome.kt new file mode 100644 index 0000000..5dfbf18 --- /dev/null +++ b/app/src/main/java/com/android/trisolarispms/ui/common/ScreenChrome.kt @@ -0,0 +1,117 @@ +package com.android.trisolarispms.ui.common + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.Done +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun BackTopBarScaffold( + title: String, + onBack: () -> Unit, + showBack: Boolean = true, + actions: @Composable RowScope.() -> Unit = {}, + bottomBar: @Composable (() -> Unit)? = null, + floatingActionButton: @Composable (() -> Unit)? = null, + content: @Composable (PaddingValues) -> Unit +) { + Scaffold( + topBar = { + TopAppBar( + title = { Text(title) }, + navigationIcon = { + if (showBack) { + IconButton(onClick = onBack) { + Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back") + } + } + }, + actions = actions, + colors = TopAppBarDefaults.topAppBarColors() + ) + }, + bottomBar = { bottomBar?.invoke() }, + floatingActionButton = { floatingActionButton?.invoke() }, + content = content + ) +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SaveTopBarScaffold( + title: String, + onBack: () -> Unit, + onSave: () -> Unit, + saveEnabled: Boolean = true, + actions: @Composable RowScope.() -> Unit = {}, + bottomBar: @Composable (() -> Unit)? = null, + floatingActionButton: @Composable (() -> Unit)? = null, + content: @Composable (PaddingValues) -> Unit +) { + BackTopBarScaffold( + title = title, + onBack = onBack, + actions = { + IconButton(onClick = onSave, enabled = saveEnabled) { + Icon(Icons.Default.Done, contentDescription = "Save") + } + actions() + }, + bottomBar = bottomBar, + floatingActionButton = floatingActionButton, + content = content + ) +} + +@Composable +fun PaddedScreenColumn( + padding: PaddingValues, + contentPadding: Dp = 24.dp, + content: @Composable ColumnScope.() -> Unit +) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(padding) + .padding(contentPadding), + verticalArrangement = Arrangement.Top, + content = content + ) +} + +@Composable +fun LoadingAndError( + isLoading: Boolean, + error: String? +) { + if (isLoading) { + CircularProgressIndicator() + Spacer(modifier = Modifier.height(8.dp)) + } + error?.let { + Text(text = it, color = MaterialTheme.colorScheme.error) + Spacer(modifier = Modifier.height(8.dp)) + } +}