diff --git a/.kotlin/errors/errors-1770004718940.log b/.kotlin/errors/errors-1770004718940.log deleted file mode 100644 index 44b23f1..0000000 --- a/.kotlin/errors/errors-1770004718940.log +++ /dev/null @@ -1,35 +0,0 @@ -kotlin version: 2.3.0 -error message: Incremental compilation failed: /home/androidlover5842/AndroidStudioProjects/TrisolarisPMS/app/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin (No such file or directory) -java.io.FileNotFoundException: /home/androidlover5842/AndroidStudioProjects/TrisolarisPMS/app/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin (No such file or directory) - at java.base/java.io.FileInputStream.open0(Native Method) - at java.base/java.io.FileInputStream.open(Unknown Source) - at java.base/java.io.FileInputStream.(Unknown Source) - at org.jetbrains.kotlin.incremental.storage.ExternalizersKt.loadFromFile(externalizers.kt:184) - at org.jetbrains.kotlin.incremental.snapshots.LazyClasspathSnapshot.getSavedShrunkClasspathAgainstPreviousLookups(LazyClasspathSnapshot.kt:86) - at org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotShrinkerKt.shrinkAndSaveClasspathSnapshot(ClasspathSnapshotShrinker.kt:267) - at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.performWorkAfterCompilation(IncrementalJvmCompilerRunner.kt:76) - at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.performWorkAfterCompilation(IncrementalJvmCompilerRunner.kt:23) - at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:420) - at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.tryCompileIncrementally$lambda$0$compile(IncrementalCompilerRunner.kt:249) - at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.tryCompileIncrementally(IncrementalCompilerRunner.kt:267) - at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:119) - at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:684) - at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:94) - at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1810) - at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source) - at java.base/java.lang.reflect.Method.invoke(Unknown Source) - at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(Unknown Source) - at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) - at java.rmi/sun.rmi.transport.Transport$1.run(Unknown Source) - at java.base/java.security.AccessController.doPrivileged(Unknown Source) - at java.rmi/sun.rmi.transport.Transport.serviceCall(Unknown Source) - at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(Unknown Source) - at java.base/java.security.AccessController.doPrivileged(Unknown Source) - at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source) - at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) - at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) - at java.base/java.lang.Thread.run(Unknown Source) - - diff --git a/AGENTS.md b/AGENTS.md index 865b3dd..389b7c4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,5 +1,9 @@ # TrisolarisPMS API Usage +## API Docs Path + +- `/home/androidlover5842/IdeaProjects/TrisolarisServer/docs` + ## 1) Booking ### Create booking diff --git a/app/src/main/java/com/android/trisolarispms/ui/booking/BookingCreateScreen.kt b/app/src/main/java/com/android/trisolarispms/ui/booking/BookingCreateScreen.kt index fc617cb..769cd7c 100644 --- a/app/src/main/java/com/android/trisolarispms/ui/booking/BookingCreateScreen.kt +++ b/app/src/main/java/com/android/trisolarispms/ui/booking/BookingCreateScreen.kt @@ -1,7 +1,5 @@ package com.android.trisolarispms.ui.booking -import android.app.TimePickerDialog -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -15,7 +13,6 @@ import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.CalendarMonth -import androidx.compose.material.icons.filled.Schedule import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.ExposedDropdownMenuBox @@ -36,7 +33,6 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel @@ -192,7 +188,7 @@ fun BookingCreateScreen( } if (state.billingMode == BookingBillingMode.CUSTOM_WINDOW) { Spacer(modifier = Modifier.height(12.dp)) - TimePickerTextField( + BookingTimePickerTextField( value = state.billingCheckoutTime, label = { Text("Billing check-out (HH:mm)") }, onTimeSelected = viewModel::onBillingCheckoutTimeChange, @@ -511,55 +507,3 @@ fun BookingCreateScreen( ) } } - -@Composable -private fun TimePickerTextField( - value: String, - label: @Composable () -> Unit, - onTimeSelected: (String) -> Unit, - modifier: Modifier = Modifier -) { - val context = LocalContext.current - val parsed = runCatching { - val parts = value.split(":") - val hour = parts.getOrNull(0)?.toIntOrNull() ?: 12 - val minute = parts.getOrNull(1)?.toIntOrNull() ?: 0 - (hour.coerceIn(0, 23)) to (minute.coerceIn(0, 59)) - }.getOrDefault(12 to 0) - - OutlinedTextField( - value = value, - onValueChange = {}, - readOnly = true, - label = label, - trailingIcon = { - IconButton( - onClick = { - TimePickerDialog( - context, - { _, hourOfDay, minute -> - onTimeSelected("%02d:%02d".format(hourOfDay, minute)) - }, - parsed.first, - parsed.second, - true - ).show() - } - ) { - Icon(Icons.Default.Schedule, contentDescription = "Pick time") - } - }, - modifier = modifier - .clickable { - TimePickerDialog( - context, - { _, hourOfDay, minute -> - onTimeSelected("%02d:%02d".format(hourOfDay, minute)) - }, - parsed.first, - parsed.second, - true - ).show() - } - ) -} diff --git a/app/src/main/java/com/android/trisolarispms/ui/booking/BookingDateTimePicker.kt b/app/src/main/java/com/android/trisolarispms/ui/booking/BookingDateTimePicker.kt index 8fee4fb..828b029 100644 --- a/app/src/main/java/com/android/trisolarispms/ui/booking/BookingDateTimePicker.kt +++ b/app/src/main/java/com/android/trisolarispms/ui/booking/BookingDateTimePicker.kt @@ -4,12 +4,15 @@ 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.material3.AlertDialog +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier @@ -37,64 +40,30 @@ internal fun BookingDateTimePickerDialog( onDismiss: () -> Unit, onConfirm: (LocalDate, String) -> Unit ) { - val today = remember { LocalDate.now() } - val currentMonth = remember { YearMonth.from(today) } - val startMonth = remember { currentMonth } - val endMonth = remember { currentMonth.plusMonths(24) } - val daysOfWeek = remember { daysOfWeek() } - val calendarState = rememberCalendarState( - startMonth = startMonth, - endMonth = endMonth, - firstVisibleMonth = currentMonth, - firstDayOfWeek = daysOfWeek.first() + val (selectedDate, timeValue, daysOfWeek, calendarState) = rememberBookingDateTimePickerState( + initialDate = initialDate, + initialTime = initialTime, + minDate = minDate ) - val selectedDate = remember { mutableStateOf(initialDate ?: today) } - val timeValue = remember { mutableStateOf(initialTime) } - val dateFormatter = remember { DateTimeFormatter.ISO_LOCAL_DATE } AlertDialog( onDismissRequest = onDismiss, title = { Text(title) }, text = { - Column { - CalendarDaysOfWeekHeader(daysOfWeek) - HorizontalCalendar( - state = calendarState, - dayContent = { day -> - val selectable = day.position == DayPosition.MonthDate && !day.date.isBefore(minDate) - CalendarDayCell( - day = day, - isSelectedStart = selectedDate.value == day.date, - isSelectedEnd = false, - isInRange = false, - hasRate = false, - isSelectable = selectable, - onClick = { selectedDate.value = day.date } - ) - }, - monthHeader = { month -> - CalendarMonthHeader(month) - } - ) - Spacer(modifier = Modifier.height(8.dp)) - Text( - text = "Selected: ${selectedDate.value.format(dateFormatter)}", - style = MaterialTheme.typography.bodySmall - ) - Spacer(modifier = Modifier.height(8.dp)) - OutlinedTextField( - value = timeValue.value, - onValueChange = { timeValue.value = it }, - label = { Text("Time (HH:MM)") }, - modifier = Modifier.fillMaxWidth() - ) - } + BookingDateTimePickerContent( + selectedDate = selectedDate, + timeValue = timeValue, + minDate = minDate, + daysOfWeek = daysOfWeek, + calendarState = calendarState + ) }, confirmButton = { TextButton( onClick = { val time = timeValue.value.ifBlank { initialTime } - onConfirm(selectedDate.value, time) + val date = if (selectedDate.value.isBefore(minDate)) minDate else selectedDate.value + onConfirm(date, time) } ) { Text("OK") @@ -108,6 +77,145 @@ internal fun BookingDateTimePickerDialog( ) } +@Composable +internal fun BookingDateTimePickerInline( + title: String, + initialDate: LocalDate?, + initialTime: String, + minDate: LocalDate, + onValueChange: (LocalDate, String) -> Unit +) { + val (selectedDate, timeValue, daysOfWeek, calendarState) = rememberBookingDateTimePickerState( + initialDate = initialDate, + initialTime = initialTime, + minDate = minDate + ) + Card( + colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant), + elevation = CardDefaults.cardElevation(defaultElevation = 2.dp), + modifier = Modifier.fillMaxWidth(), + shape = MaterialTheme.shapes.large + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 10.dp) + ) { + Text( + text = title, + style = MaterialTheme.typography.titleMedium, + modifier = Modifier.fillMaxWidth() + ) + Spacer(modifier = Modifier.height(8.dp)) + BookingDateTimePickerContent( + selectedDate = selectedDate, + timeValue = timeValue, + minDate = minDate, + daysOfWeek = daysOfWeek, + calendarState = calendarState, + onDateSelected = { date -> + val safeDate = if (date.isBefore(minDate)) minDate else date + onValueChange(safeDate, timeValue.value) + }, + onTimeSelected = { time -> + val safeDate = if (selectedDate.value.isBefore(minDate)) minDate else selectedDate.value + onValueChange(safeDate, time) + } + ) + } + } +} + +@Composable +private fun BookingDateTimePickerContent( + selectedDate: MutableState, + timeValue: MutableState, + minDate: LocalDate, + daysOfWeek: List, + calendarState: com.kizitonwose.calendar.compose.CalendarState, + onDateSelected: (LocalDate) -> Unit = {}, + onTimeSelected: (String) -> Unit = {} +) { + val dateFormatter = remember { DateTimeFormatter.ISO_LOCAL_DATE } + Column { + CalendarDaysOfWeekHeader(daysOfWeek) + HorizontalCalendar( + state = calendarState, + dayContent = { day -> + val selectable = day.position == DayPosition.MonthDate && !day.date.isBefore(minDate) + CalendarDayCell( + day = day, + isSelectedStart = selectedDate.value == day.date, + isSelectedEnd = false, + isInRange = false, + hasRate = false, + isSelectable = selectable, + onClick = { + selectedDate.value = day.date + onDateSelected(day.date) + } + ) + }, + monthHeader = { month -> + CalendarMonthHeader(month) + } + ) + Spacer(modifier = Modifier.height(8.dp)) + Text( + text = "Selected: ${selectedDate.value.format(dateFormatter)}", + style = MaterialTheme.typography.bodySmall + ) + Spacer(modifier = Modifier.height(8.dp)) + BookingTimePickerTextField( + value = timeValue.value, + onTimeSelected = { + timeValue.value = it + onTimeSelected(it) + }, + label = { Text("Time (HH:MM)") }, + modifier = Modifier.fillMaxWidth() + ) + } +} + +@Composable +private fun rememberBookingDateTimePickerState( + initialDate: LocalDate?, + initialTime: String, + minDate: LocalDate +): PickerUiState { + val now = remember { LocalDate.now() } + val initialSelectedDate = remember(initialDate, minDate, now) { + val seed = initialDate ?: now + if (seed.isBefore(minDate)) minDate else seed + } + val selectedDate = remember(initialSelectedDate) { mutableStateOf(initialSelectedDate) } + val timeValue = remember(initialTime) { mutableStateOf(initialTime) } + val startMonth = remember(minDate) { YearMonth.from(minDate) } + val firstVisibleMonth = remember(initialSelectedDate) { YearMonth.from(initialSelectedDate) } + val endMonth = remember(startMonth) { startMonth.plusMonths(24) } + val daysOfWeek = remember { daysOfWeek() } + val calendarState = rememberCalendarState( + startMonth = startMonth, + endMonth = endMonth, + firstVisibleMonth = firstVisibleMonth, + firstDayOfWeek = daysOfWeek.first() + ) + return PickerUiState( + selectedDate = selectedDate, + timeValue = timeValue, + daysOfWeek = daysOfWeek, + calendarState = calendarState + ) +} + +private data class PickerUiState( + val selectedDate: MutableState, + val timeValue: MutableState, + val daysOfWeek: List, + val calendarState: com.kizitonwose.calendar.compose.CalendarState +) + internal fun formatBookingIso(date: LocalDate, time: String): String { val parts = time.split(":") val hour = parts.getOrNull(0)?.toIntOrNull() ?: 0 diff --git a/app/src/main/java/com/android/trisolarispms/ui/booking/BookingExpectedDatesScreen.kt b/app/src/main/java/com/android/trisolarispms/ui/booking/BookingExpectedDatesScreen.kt index 42824b4..5218197 100644 --- a/app/src/main/java/com/android/trisolarispms/ui/booking/BookingExpectedDatesScreen.kt +++ b/app/src/main/java/com/android/trisolarispms/ui/booking/BookingExpectedDatesScreen.kt @@ -1,15 +1,9 @@ package com.android.trisolarispms.ui.booking -import androidx.compose.foundation.layout.Arrangement -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.material.icons.Icons -import androidx.compose.material.icons.filled.CalendarMonth import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text @@ -40,8 +34,6 @@ fun BookingExpectedDatesScreen( onBack: () -> Unit, onDone: () -> Unit ) { - val showCheckInPicker = remember { mutableStateOf(false) } - val showCheckOutPicker = remember { mutableStateOf(false) } val checkInDate = remember { mutableStateOf(null) } val checkOutDate = remember { mutableStateOf(null) } val checkInTime = remember { mutableStateOf("12:00") } @@ -50,6 +42,7 @@ fun BookingExpectedDatesScreen( val error = remember { mutableStateOf(null) } val displayFormatter = remember { DateTimeFormatter.ofPattern("dd-MM-yy HH:mm") } val displayZone = remember { ZoneId.of("Asia/Kolkata") } + val today = LocalDate.now(displayZone) val editableCheckIn = status?.uppercase() == "OPEN" val scope = rememberCoroutineScope() @@ -127,13 +120,22 @@ fun BookingExpectedDatesScreen( onValueChange = {}, readOnly = true, label = { Text("Expected Check-in") }, - trailingIcon = { - IconButton(onClick = { showCheckInPicker.value = true }) { - Icon(Icons.Default.CalendarMonth, contentDescription = "Pick date") - } - }, modifier = Modifier.fillMaxWidth() ) + Spacer(modifier = Modifier.height(8.dp)) + BookingDateTimePickerInline( + title = "Select check-in", + initialDate = checkInDate.value, + initialTime = checkInTime.value, + minDate = today, + onValueChange = { date, time -> + checkInDate.value = date + checkInTime.value = time + if (checkOutDate.value?.isBefore(date) == true) { + checkOutDate.value = date + } + } + ) Spacer(modifier = Modifier.height(12.dp)) } OutlinedTextField( @@ -147,13 +149,20 @@ fun BookingExpectedDatesScreen( onValueChange = {}, readOnly = true, label = { Text("Expected Check-out") }, - trailingIcon = { - IconButton(onClick = { showCheckOutPicker.value = true }) { - Icon(Icons.Default.CalendarMonth, contentDescription = "Pick date") - } - }, modifier = Modifier.fillMaxWidth() ) + val checkOutMinDate = maxOf(checkInDate.value ?: today, today) + Spacer(modifier = Modifier.height(8.dp)) + BookingDateTimePickerInline( + title = "Select check-out", + initialDate = checkOutDate.value, + initialTime = checkOutTime.value, + minDate = checkOutMinDate, + onValueChange = { date, time -> + checkOutDate.value = date + checkOutTime.value = time + } + ) if (isLoading.value) { Spacer(modifier = Modifier.height(12.dp)) CircularProgressIndicator() @@ -164,34 +173,4 @@ fun BookingExpectedDatesScreen( } } } - - if (showCheckInPicker.value && editableCheckIn) { - BookingDateTimePickerDialog( - title = "Select check-in", - initialDate = checkInDate.value, - initialTime = checkInTime.value, - minDate = LocalDate.now(), - onDismiss = { showCheckInPicker.value = false }, - onConfirm = { date, time -> - checkInDate.value = date - checkInTime.value = time - showCheckInPicker.value = false - } - ) - } - - if (showCheckOutPicker.value) { - BookingDateTimePickerDialog( - title = "Select check-out", - initialDate = checkOutDate.value, - initialTime = checkOutTime.value, - minDate = checkInDate.value ?: LocalDate.now(), - onDismiss = { showCheckOutPicker.value = false }, - onConfirm = { date, time -> - checkOutDate.value = date - checkOutTime.value = time - showCheckOutPicker.value = false - } - ) - } } diff --git a/app/src/main/java/com/android/trisolarispms/ui/booking/BookingTimePickerTextField.kt b/app/src/main/java/com/android/trisolarispms/ui/booking/BookingTimePickerTextField.kt new file mode 100644 index 0000000..231801e --- /dev/null +++ b/app/src/main/java/com/android/trisolarispms/ui/booking/BookingTimePickerTextField.kt @@ -0,0 +1,53 @@ +package com.android.trisolarispms.ui.booking + +import android.app.TimePickerDialog +import androidx.compose.foundation.clickable +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Schedule +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.OutlinedTextField +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext + +@Composable +internal fun BookingTimePickerTextField( + value: String, + label: @Composable () -> Unit, + onTimeSelected: (String) -> Unit, + modifier: Modifier = Modifier +) { + val context = LocalContext.current + val parsed = runCatching { + val parts = value.split(":") + val hour = parts.getOrNull(0)?.toIntOrNull() ?: 12 + val minute = parts.getOrNull(1)?.toIntOrNull() ?: 0 + (hour.coerceIn(0, 23)) to (minute.coerceIn(0, 59)) + }.getOrDefault(12 to 0) + + fun openDialog() { + TimePickerDialog( + context, + { _, hourOfDay, minute -> + onTimeSelected("%02d:%02d".format(hourOfDay, minute)) + }, + parsed.first, + parsed.second, + true + ).show() + } + + OutlinedTextField( + value = value, + onValueChange = {}, + readOnly = true, + label = label, + trailingIcon = { + IconButton(onClick = ::openDialog) { + Icon(Icons.Default.Schedule, contentDescription = "Pick time") + } + }, + modifier = modifier.clickable(onClick = ::openDialog) + ) +} diff --git a/app/src/main/java/com/android/trisolarispms/ui/calendar/CalendarComponents.kt b/app/src/main/java/com/android/trisolarispms/ui/calendar/CalendarComponents.kt index efce045..3f33502 100644 --- a/app/src/main/java/com/android/trisolarispms/ui/calendar/CalendarComponents.kt +++ b/app/src/main/java/com/android/trisolarispms/ui/calendar/CalendarComponents.kt @@ -16,6 +16,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.kizitonwose.calendar.core.CalendarDay import com.kizitonwose.calendar.core.CalendarMonth @@ -29,11 +30,12 @@ fun CalendarDaysOfWeekHeader(daysOfWeek: List) { text = day.name.take(3), style = MaterialTheme.typography.bodySmall, modifier = Modifier.weight(1f), - color = MaterialTheme.colorScheme.onSurfaceVariant + color = MaterialTheme.colorScheme.onSurfaceVariant, + textAlign = TextAlign.Center ) } } - Spacer(modifier = Modifier.height(4.dp)) + Spacer(modifier = Modifier.height(6.dp)) } @Composable @@ -58,14 +60,15 @@ fun CalendarDayCell( ) { val isInMonth = day.position == DayPosition.MonthDate val background = when { - isSelectedStart || isSelectedEnd -> MaterialTheme.colorScheme.primary.copy(alpha = 0.35f) - isInRange -> MaterialTheme.colorScheme.primary.copy(alpha = 0.18f) + isSelectedStart || isSelectedEnd -> MaterialTheme.colorScheme.primaryContainer + isInRange -> MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.55f) hasRate -> MaterialTheme.colorScheme.secondary.copy(alpha = 0.2f) else -> Color.Transparent } val textColor = when { + isSelectedStart || isSelectedEnd -> MaterialTheme.colorScheme.onPrimaryContainer !isInMonth -> MaterialTheme.colorScheme.onSurfaceVariant - !isSelectable -> MaterialTheme.colorScheme.error + !isSelectable -> MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.45f) else -> MaterialTheme.colorScheme.onSurface } Column(