change: Konzerte ohne Zeitfenster — Chips nur noch bei den Veroeffentlichungen
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
17a677a5a5
commit
ae357b0eb9
9 files changed
+66
-48
No files matched your search
@@ -40,11 +40,12 @@ object ReleasesClient {
|
||||
}
|
||||
|
||||
/** Anstehende Konzerte derselben Kuenstler — gleicher Weg, anderer Endpunkt. */
|
||||
suspend fun konzerte(backendUrl: String, artists: List<ArtistRef>, days: Int): ArtistKonzerteResponse {
|
||||
suspend fun konzerte(backendUrl: String, artists: List<ArtistRef>): ArtistKonzerteResponse {
|
||||
if (backendUrl.isBlank() || artists.isEmpty()) return ArtistKonzerteResponse()
|
||||
// Ohne `days`: das Backend liefert alles Angekuendigte.
|
||||
return http.post("${backendUrl.trimEnd('/')}/api/artist-concerts") {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(ArtistKonzerteRequest(artists, days))
|
||||
setBody(ArtistKonzerteRequest(artists))
|
||||
}.body()
|
||||
}
|
||||
}
|
||||
@@ -56,4 +56,4 @@ data class ArtistKonzerteResponse(
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ArtistKonzerteRequest(val artists: List<ArtistRef>, val days: Int)
|
||||
data class ArtistKonzerteRequest(val artists: List<ArtistRef>)
|
||||
@@ -91,24 +91,28 @@ fun ArtistNewsScreen(
|
||||
}
|
||||
}
|
||||
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier.padding(start = 16.dp, top = 8.dp, bottom = 10.dp),
|
||||
) {
|
||||
// 90 Tage zuerst, weil es die Vorgabe ist — der aktive Chip steht dann vorn.
|
||||
// Bei den Konzerten zeigt dasselbe Fenster nach VORN, dort sind 1 Jahr die Vorgabe.
|
||||
val aktuell = if (state.reiter == NewsReiter.KONZERTE) state.tageKonzerte else state.tage
|
||||
listOf(90 to "90 Tage", 30 to "30 Tage", 365 to "1 Jahr").forEach { (tage, label) ->
|
||||
FilterChip(
|
||||
selected = aktuell == tage,
|
||||
onClick = { vm.setzeTage(tage) },
|
||||
label = { Text(label, fontSize = 12.sp) },
|
||||
colors = FilterChipDefaults.filterChipColors(
|
||||
selectedContainerColor = NsAccent.copy(alpha = 0.2f),
|
||||
selectedLabelColor = NsAccent,
|
||||
),
|
||||
)
|
||||
// Das Zeitfenster gilt nur fuer die Veroeffentlichungen. Konzerte sind ohnehin Zukunft,
|
||||
// dort will man alles Angekuendigte sehen — eine Tagesgrenze schnitte nur willkuerlich ab.
|
||||
if (state.reiter == NewsReiter.RELEASES) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier.padding(start = 16.dp, top = 8.dp, bottom = 10.dp),
|
||||
) {
|
||||
// 90 Tage zuerst, weil es die Vorgabe ist — der aktive Chip steht dann vorn.
|
||||
listOf(90 to "90 Tage", 30 to "30 Tage", 365 to "1 Jahr").forEach { (tage, label) ->
|
||||
FilterChip(
|
||||
selected = state.tage == tage,
|
||||
onClick = { vm.setzeTage(tage) },
|
||||
label = { Text(label, fontSize = 12.sp) },
|
||||
colors = FilterChipDefaults.filterChipColors(
|
||||
selectedContainerColor = NsAccent.copy(alpha = 0.2f),
|
||||
selectedLabelColor = NsAccent,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Spacer(Modifier.height(10.dp))
|
||||
}
|
||||
HorizontalDivider(color = MaterialTheme.colorScheme.outline)
|
||||
|
||||
@@ -125,7 +129,7 @@ fun ArtistNewsScreen(
|
||||
state.reiter == NewsReiter.KONZERTE && state.keinSchluessel -> Hinweis("🎟",
|
||||
"Kein Ticketmaster-Schlüssel hinterlegt", "Im Backend TICKETMASTER_API_KEY setzen.")
|
||||
state.reiter == NewsReiter.KONZERTE && state.konzerte.isEmpty() -> Hinweis("🎪",
|
||||
"Keine Termine in den nächsten ${state.tageKonzerte} Tagen",
|
||||
"Keine anstehenden Termine",
|
||||
"Gesucht wird weltweit über den Künstlernamen.")
|
||||
state.reiter == NewsReiter.KONZERTE -> LazyColumn(contentPadding = PaddingValues(bottom = 90.dp)) {
|
||||
var letzterMonat = ""
|
||||
|
||||
@@ -26,8 +26,6 @@ data class ArtistNewsUiState(
|
||||
val reiter: NewsReiter = NewsReiter.RELEASES,
|
||||
val releases: List<ArtistRelease> = emptyList(),
|
||||
val konzerte: List<ArtistKonzert> = emptyList(),
|
||||
/** Zeitfenster der Konzerte — nach VORN, deshalb ein eigener Wert. */
|
||||
val tageKonzerte: Int = 365,
|
||||
val keinSchluessel: Boolean = false,
|
||||
/** Schlüssel (Künstler + Album, normalisiert) alles dessen, was schon in der Bibliothek liegt. */
|
||||
val vorhanden: Set<String> = emptySet(),
|
||||
@@ -59,13 +57,13 @@ class ArtistNewsViewModel(app: Application) : AndroidViewModel(app) {
|
||||
if (r == NewsReiter.KONZERTE && _state.value.konzerte.isEmpty()) ladeKonzerte()
|
||||
}
|
||||
|
||||
/** Zeitfenster setzen — es gilt je Reiter, weil es in verschiedene Richtungen zeigt. */
|
||||
fun setzeTage(tage: Int) {
|
||||
if (_state.value.reiter == NewsReiter.KONZERTE) ladeKonzerte(tage) else laden(tage)
|
||||
}
|
||||
/** Zeitfenster setzen — gibt es nur bei den Veroeffentlichungen. */
|
||||
fun setzeTage(tage: Int) = laden(tage)
|
||||
|
||||
fun ladeKonzerte(tage: Int = _state.value.tageKonzerte) = viewModelScope.launch {
|
||||
_state.value = _state.value.copy(isLoading = true, tageKonzerte = tage, error = null,
|
||||
// Kein Zeitfenster: Ticketmaster liefert ohnehin nur Anstehendes, und dort will man alles
|
||||
// Angekuendigte sehen — eine Tagesgrenze schnitte nur willkuerlich ab.
|
||||
fun ladeKonzerte() = viewModelScope.launch {
|
||||
_state.value = _state.value.copy(isLoading = true, error = null,
|
||||
keineGefolgten = false, keinBackend = false, keinSchluessel = false)
|
||||
try {
|
||||
val backendUrl = runCatching { repo.getBackendUrl() }.getOrDefault("")
|
||||
@@ -78,7 +76,7 @@ class ArtistNewsViewModel(app: Application) : AndroidViewModel(app) {
|
||||
_state.value = _state.value.copy(isLoading = false, keineGefolgten = true)
|
||||
return@launch
|
||||
}
|
||||
val antwort = ReleasesClient.konzerte(backendUrl, kuenstler, tage)
|
||||
val antwort = ReleasesClient.konzerte(backendUrl, kuenstler)
|
||||
_state.value = _state.value.copy(
|
||||
konzerte = antwort.konzerte,
|
||||
keinSchluessel = antwort.keinSchluessel,
|
||||
|
||||
Reference in new issue
Block a user