feat(deck): быстрые опции срока (Сегодня/Завтра/Выходные/Неделя) в карточке (P1 diff)

DeckDueChip + deckQuickDueIso (полночь UTC, как пикер). Green compile+detekt (без новых замечаний).
This commit is contained in:
b-mob-deck
2026-07-13 08:10:19 +00:00
parent e6570c008e
commit d0bf3590d1
@@ -43,9 +43,13 @@ import ru.forbion.f7cloud.core.designsystem.F7Colors
import ru.forbion.f7cloud.core.designsystem.F7OutlinedField import ru.forbion.f7cloud.core.designsystem.F7OutlinedField
import ru.forbion.f7cloud.core.designsystem.F7PrimaryButton import ru.forbion.f7cloud.core.designsystem.F7PrimaryButton
import ru.forbion.f7cloud.core.designsystem.F7SecondaryButton import ru.forbion.f7cloud.core.designsystem.F7SecondaryButton
import java.time.DayOfWeek
import java.time.Instant import java.time.Instant
import java.time.LocalDate
import java.time.ZoneId import java.time.ZoneId
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.time.temporal.TemporalAdjusters
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
@Composable @Composable
@@ -120,6 +124,17 @@ fun DeckCardSheet(
Text("Сбросить", color = F7Colors.Primary, style = MaterialTheme.typography.bodyMedium, modifier = Modifier.clickable { duedate = null }) Text("Сбросить", color = F7Colors.Primary, style = MaterialTheme.typography.bodyMedium, modifier = Modifier.clickable { duedate = null })
} }
} }
if (canEdit) {
FlowRow(
horizontalArrangement = Arrangement.spacedBy(6.dp),
verticalArrangement = Arrangement.spacedBy(6.dp),
) {
DeckDueChip("Сегодня") { duedate = deckQuickDueIso(0) }
DeckDueChip("Завтра") { duedate = deckQuickDueIso(1) }
DeckDueChip("Выходные") { duedate = deckQuickDueIso(0, toWeekend = true) }
DeckDueChip("Неделя") { duedate = deckQuickDueIso(7) }
}
}
// Метки доски // Метки доски
if (boardLabels.isNotEmpty()) { if (boardLabels.isNotEmpty()) {
@@ -291,6 +306,29 @@ fun DeckConfirmDialog(
} }
} }
@Composable
private fun DeckDueChip(text: String, onClick: () -> Unit) {
Box(
modifier = Modifier
.clip(RoundedCornerShape(100.dp))
.background(F7Colors.SurfaceMuted)
.clickable(onClick = onClick)
.padding(horizontal = 10.dp, vertical = 4.dp),
) {
Text(text, style = MaterialTheme.typography.bodyMedium, color = F7Colors.TextPrimary)
}
}
/** ISO-срок для быстрых опций: сегодня/через N дней/ближайшая суббота (полночь UTC — как пикер). */
private fun deckQuickDueIso(daysAhead: Long, toWeekend: Boolean = false): String {
val date = if (toWeekend) {
LocalDate.now().with(TemporalAdjusters.nextOrSame(DayOfWeek.SATURDAY))
} else {
LocalDate.now().plusDays(daysAhead)
}
return DateTimeFormatter.ISO_INSTANT.format(date.atStartOfDay(ZoneOffset.UTC).toInstant())
}
/** Парсит ISO-строку срока Deck в миллисекунды (для инициализации пикера). */ /** Парсит ISO-строку срока Deck в миллисекунды (для инициализации пикера). */
internal fun parseDeckDueMillis(iso: String): Long? = runCatching { internal fun parseDeckDueMillis(iso: String): Long? = runCatching {
Instant.parse(iso).toEpochMilli() Instant.parse(iso).toEpochMilli()