fix(android): even concert rows — fixed calendar-style date block
The "16. Sep. 2026" date wrapped inside the 52dp column, so rows with/without a time ended up different heights and the divider/venue misaligned. The date block is now a fixed 56dp calendar block: big day number, small month/year and time, each single-line — every row is the same height and lines up. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
2208ce77b6
commit
f56d47800c
1 file changed
+24
-15
@@ -88,7 +88,7 @@ fun ConcertsSheet(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun EventRow(event: ConcertEvent, onTicketClick: (String) -> Unit) {
|
private fun EventRow(event: ConcertEvent, onTicketClick: (String) -> Unit) {
|
||||||
val (dateStr, timeStr) = formatEventDateTime(event.datetime)
|
val w = formatEventWhen(event.datetime)
|
||||||
val venue = event.venue?.name.orEmpty()
|
val venue = event.venue?.name.orEmpty()
|
||||||
val city = listOfNotNull(event.venue?.city, event.venue?.country).joinToString(", ")
|
val city = listOfNotNull(event.venue?.city, event.venue?.country).joinToString(", ")
|
||||||
val offer = event.offers.firstOrNull { !it.url.isNullOrBlank() }
|
val offer = event.offers.firstOrNull { !it.url.isNullOrBlank() }
|
||||||
@@ -102,26 +102,33 @@ private fun EventRow(event: ConcertEvent, onTicketClick: (String) -> Unit) {
|
|||||||
.background(NsSurface2)
|
.background(NsSurface2)
|
||||||
.padding(horizontal = 14.dp, vertical = 12.dp),
|
.padding(horizontal = 14.dp, vertical = 12.dp),
|
||||||
) {
|
) {
|
||||||
// Date block
|
// Date block — fixed width, calendar style (day big, month/year + time small) so every
|
||||||
|
// row is the same height and the divider/venue line up.
|
||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
modifier = Modifier.width(52.dp),
|
modifier = Modifier.width(56.dp),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
dateStr,
|
w.day,
|
||||||
fontFamily = Outfit, fontWeight = FontWeight.Bold,
|
fontFamily = Outfit, fontWeight = FontWeight.Bold,
|
||||||
fontSize = 13.sp, color = NsAccent,
|
fontSize = 18.sp, color = NsAccent, maxLines = 1,
|
||||||
)
|
)
|
||||||
if (timeStr.isNotBlank()) {
|
if (w.monthYear.isNotBlank()) {
|
||||||
Text(
|
Text(
|
||||||
timeStr,
|
w.monthYear,
|
||||||
fontFamily = Outfit, fontSize = 11.sp, color = NsOnSurface2,
|
fontFamily = Outfit, fontSize = 10.sp, color = NsOnSurface2, maxLines = 1,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (w.time.isNotBlank()) {
|
||||||
|
Text(
|
||||||
|
w.time,
|
||||||
|
fontFamily = Outfit, fontSize = 10.sp, color = NsOnSurface2, maxLines = 1,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(Modifier.width(14.dp))
|
Spacer(Modifier.width(14.dp))
|
||||||
Box(Modifier.width(1.dp).height(36.dp).background(NsBorder))
|
Box(Modifier.width(1.dp).height(40.dp).background(NsBorder))
|
||||||
Spacer(Modifier.width(14.dp))
|
Spacer(Modifier.width(14.dp))
|
||||||
|
|
||||||
// Venue
|
// Venue
|
||||||
@@ -166,19 +173,21 @@ private fun EventRow(event: ConcertEvent, onTicketClick: (String) -> Unit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val DATE_FMT = DateTimeFormatter.ofPattern("dd. MMM yyyy", Locale.GERMAN)
|
private data class EventWhen(val day: String, val monthYear: String, val time: String)
|
||||||
private val TIME_FMT = DateTimeFormatter.ofPattern("HH:mm")
|
|
||||||
|
|
||||||
private fun formatEventDateTime(datetime: String): Pair<String, String> {
|
private val DAY_FMT = DateTimeFormatter.ofPattern("dd", Locale.GERMAN)
|
||||||
|
private val MONTH_FMT = DateTimeFormatter.ofPattern("MMM yyyy", Locale.GERMAN)
|
||||||
|
private val TIME_FMT = DateTimeFormatter.ofPattern("HH:mm")
|
||||||
|
|
||||||
|
private fun formatEventWhen(datetime: String): EventWhen {
|
||||||
return try {
|
return try {
|
||||||
// Backend now sends a naive venue-local datetime ("2026-09-16T20:00:00"); older/zoned
|
// Backend now sends a naive venue-local datetime ("2026-09-16T20:00:00"); older/zoned
|
||||||
// values ("…Z") still parse via the ZonedDateTime fallback.
|
// values ("…Z") still parse via the ZonedDateTime fallback.
|
||||||
val ldt = runCatching { LocalDateTime.parse(datetime) }
|
val ldt = runCatching { LocalDateTime.parse(datetime) }
|
||||||
.getOrElse { ZonedDateTime.parse(datetime).toLocalDateTime() }
|
.getOrElse { ZonedDateTime.parse(datetime).toLocalDateTime() }
|
||||||
val date = ldt.format(DATE_FMT)
|
|
||||||
val time = if (ldt.hour == 0 && ldt.minute == 0) "" else ldt.format(TIME_FMT)
|
val time = if (ldt.hour == 0 && ldt.minute == 0) "" else ldt.format(TIME_FMT)
|
||||||
date to time
|
EventWhen(ldt.format(DAY_FMT), ldt.format(MONTH_FMT), time)
|
||||||
} catch (_: Exception) {
|
} catch (_: Exception) {
|
||||||
datetime.take(10) to ""
|
EventWhen(datetime.take(10), "", "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user