package net.tinsae.clocked.settings 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.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.selection.selectableGroup import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ChevronRight import androidx.compose.material3.AlertDialog import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.RadioButton import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import net.tinsae.clocked.AuthViewModel import net.tinsae.clocked.R import net.tinsae.clocked.data.Locale import net.tinsae.clocked.data.Theme import net.tinsae.clocked.ui.theme.ClockedTheme @Composable fun SettingsScreen( modifier: Modifier = Modifier, viewModel: SettingsViewModel = viewModel(), authViewModel: AuthViewModel ) { val uiState by viewModel.uiState.collectAsState() if (uiState.showThemeDialog) { ThemeSelectionDialog( currentTheme = uiState.theme, onThemeSelected = viewModel::onThemeSelected, onDismiss = viewModel::onDismissThemeDialog ) } if (uiState.showLocaleDialog) { LocaleSelectionDialog( currentLocale = uiState.locale, onLocaleSelected = viewModel::onLocaleSelected, onDismiss = viewModel::onDismissLocaleDialog ) } Column( modifier = modifier .padding(16.dp) ) { SettingsSection(title = stringResource(R.string.settings_section_data)) { SettingsItem( title = stringResource(R.string.settings_item_export_csv), onClick = viewModel::onExportClicked, trailingContent = { Icon( Icons.Filled.ChevronRight, contentDescription = stringResource(R.string.settings_item_navigate) ) } ) } Spacer(modifier = Modifier.height(24.dp)) SettingsSection(title = stringResource(R.string.settings_section_preferences)) { SettingsItem(title = stringResource(R.string.settings_item_default_duration), value = uiState.defaultDuration, onClick = { /* TODO: Handle duration change */ }) SettingsItem(title = stringResource(R.string.settings_item_time_rounding), value = uiState.timeRounding, onClick = { /* TODO: Handle rounding change */ }) SettingsItem(title = stringResource(R.string.settings_item_week_starts_on), value = uiState.weekStartsOn, onClick = { /* TODO: Handle week start change */ }) } Spacer(modifier = Modifier.height(24.dp)) SettingsSection(title = stringResource(R.string.settings_section_appearance)) { SettingsItem(title = stringResource(R.string.theme), value = uiState.theme.title, onClick = viewModel::onThemeClicked) SettingsItem(title = stringResource(R.string.language), value = uiState.locale.title, onClick = viewModel::onLocaleClicked) } Spacer(modifier = Modifier.height(24.dp)) SettingsSection(title = stringResource(R.string.about)) { SettingsItem(title = stringResource(R.string.settings_item_app_version), value = uiState.appVersion) } } } @Composable fun SettingsSection(title: String, content: @Composable () -> Unit) { Column { Text(text = title, style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.SemiBold) HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp)) content() } } @Composable fun SettingsItem( title: String, modifier: Modifier = Modifier, value: String? = null, onClick: (() -> Unit)? = null, trailingContent: @Composable (() -> Unit)? = null ) { val itemModifier = if (onClick != null) { modifier.clickable(onClick = onClick) } else { modifier } Row( modifier = itemModifier .fillMaxWidth() .padding(vertical = 16.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { Text(text = title, style = MaterialTheme.typography.bodyLarge) if (value != null) { Text( text = value, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant ) } if (trailingContent != null) { trailingContent() } } } @Composable fun ThemeSelectionDialog( currentTheme: Theme, onThemeSelected: (Theme) -> Unit, onDismiss: () -> Unit ) { AlertDialog( onDismissRequest = onDismiss, title = { Text(text = stringResource(R.string.theme)) }, text = { Column(Modifier.selectableGroup()) { Theme.entries.forEach { theme -> Row( Modifier .fillMaxWidth() .height(56.dp) .selectable( selected = (theme == currentTheme), onClick = { onThemeSelected(theme) }, role = Role.RadioButton ) .padding(horizontal = 16.dp), verticalAlignment = Alignment.CenterVertically ) { RadioButton( selected = (theme == currentTheme), onClick = null // null recommended for accessibility with screenreaders ) Text( text = theme.title, style = MaterialTheme.typography.bodyLarge, modifier = Modifier.padding(start = 16.dp) ) } } } }, confirmButton = { TextButton(onClick = onDismiss) { Text(stringResource(R.string.cancel)) } } ) } @Composable fun LocaleSelectionDialog( currentLocale: Locale, onLocaleSelected: (Locale) -> Unit, onDismiss: () -> Unit ) { AlertDialog( onDismissRequest = onDismiss, title = { Text(text = stringResource(R.string.language)) }, text = { Column(Modifier.selectableGroup()) { Locale.entries.forEach { locale -> Row( Modifier .fillMaxWidth() .height(56.dp) .selectable( selected = (locale == currentLocale), onClick = { onLocaleSelected(locale) }, role = Role.RadioButton ) .padding(horizontal = 16.dp), verticalAlignment = Alignment.CenterVertically ) { RadioButton( selected = (locale == currentLocale), onClick = null // null recommended for accessibility with screenreaders ) Text( text = locale.title, style = MaterialTheme.typography.bodyLarge, modifier = Modifier.padding(start = 16.dp) ) } } } }, confirmButton = { TextButton(onClick = onDismiss) { Text(stringResource(R.string.cancel)) } } ) } @Preview(showBackground = true) @Composable fun SettingsScreenPreview() { ClockedTheme { SettingsScreen(viewModel = SettingsViewModel(), authViewModel = AuthViewModel()) } }