### feat: verbessere PDF-Handling und füge neuen Versionsmarker hinzu
All checks were successful
Build and Publish Docker Images / build-and-push (., backend/services/mail/Dockerfile, mail-service, mail-service) (push) Successful in 5m52s
Build and Publish Docker Images / build-and-push (., config/docker/caddy/web-app/Dockerfile, web-app, web-app) (push) Successful in 4m19s

- **WebMainScreen:** Implementiere Öffnen von Ausschreibungen (PDFs) in neuem Tab.
- **UI:** Ergänze dezentralen Versions-Marker in der Web-Oberfläche.
- **Docker-Publish:** Kopiere Turnier-Ausschreibungen (PDFs) in den Zielordner.
- **Assets:** Füge neue PDF-Dateien für Neumarkt2026 hinzu.
This commit is contained in:
Stefan Mogeritsch 2026-04-23 08:11:06 +02:00
parent eea022b862
commit dbbca96c69
5 changed files with 29 additions and 23 deletions

View File

@ -84,6 +84,8 @@ jobs:
rm -rf "$TARGET_DIR" rm -rf "$TARGET_DIR"
mkdir -p "$TARGET_DIR" mkdir -p "$TARGET_DIR"
cp -r "$DIST_DIR"/. "$TARGET_DIR/" cp -r "$DIST_DIR"/. "$TARGET_DIR/"
# Kopiere Turnier-Ausschreibungen (PDFs) für Plan-B
cp docs/Neumarkt2026/*.pdf "$TARGET_DIR/" || true
echo "✓ Assets für Docker vorbereitet (Stand: $(date))" echo "✓ Assets für Docker vorbereitet (Stand: $(date))"

BIN
docs/Neumarkt2026/26128.pdf Normal file

Binary file not shown.

BIN
docs/Neumarkt2026/26129.pdf Normal file

Binary file not shown.

View File

@ -214,22 +214,6 @@ fun OnlineNennungFormular(
color = AppColors.Primary color = AppColors.Primary
) )
if (!isMobile) {
Text(
text = "https://nennung.mo-code.at/#/nennung/$turnierNr",
style = MaterialTheme.typography.labelMedium,
color = AppColors.Primary.copy(alpha = 0.6f),
modifier = Modifier.padding(bottom = 4.dp)
)
Text(
text = "v2026-04-23.7 - URL-ROUTING", // Version erhöht für URL-Routing Fix
style = MaterialTheme.typography.labelLarge,
fontWeight = FontWeight.Bold,
color = Color.Blue, // Farbe geändert für neue Version
modifier = Modifier.padding(bottom = 4.dp).background(Color.Black.copy(alpha = 0.05f))
)
}
Text( Text(
text = "Turnier-Nr: $turnierNr | Datum: ${if (turnierNr == "26128") "25. April 2026" else "26. April 2026"}", text = "Turnier-Nr: $turnierNr | Datum: ${if (turnierNr == "26128") "25. April 2026" else "26. April 2026"}",
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,

View File

@ -35,6 +35,9 @@ private fun setWindowHash(hash: String): Unit = js("window.location.hash = hash"
@OptIn(ExperimentalWasmJsInterop::class) @OptIn(ExperimentalWasmJsInterop::class)
private fun onHashChange(onChanged: () -> Unit): Unit = js("window.addEventListener('hashchange', onChanged)") private fun onHashChange(onChanged: () -> Unit): Unit = js("window.addEventListener('hashchange', onChanged)")
@OptIn(ExperimentalWasmJsInterop::class)
private fun openInNewTab(url: String): Unit = js("window.open(url, '_blank')")
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun MainAppContent() { fun MainAppContent() {
@ -88,6 +91,9 @@ fun MainAppContent() {
}, },
onNennenClick = { vId, tId -> onNennenClick = { vId, tId ->
currentScreen = WebScreen.Nennung(vId, tId) currentScreen = WebScreen.Nennung(vId, tId)
},
onAusschreibungClick = { pdfUrl ->
openInNewTab(pdfUrl)
} }
) )
@ -112,6 +118,15 @@ fun MainAppContent() {
onBack = { currentScreen = WebScreen.Landing } onBack = { currentScreen = WebScreen.Landing }
) )
} }
// Dezentraler Versions-Marker in der unteren rechten Ecke
Box(modifier = Modifier.fillMaxSize().padding(8.dp), contentAlignment = Alignment.BottomEnd) {
Text(
text = "v2026-04-23.9",
style = MaterialTheme.typography.labelSmall,
color = Color.LightGray.copy(alpha = 0.5f)
)
}
} }
} }
} }
@ -149,7 +164,8 @@ fun Erfolgsscreen(email: String, onBack: () -> Unit) {
@Composable @Composable
fun LandingPage( fun LandingPage(
onVeranstaltungClick: (Long) -> Unit, onVeranstaltungClick: (Long) -> Unit,
onNennenClick: (Long, Long) -> Unit onNennenClick: (Long, Long) -> Unit,
onAusschreibungClick: (String) -> Unit
) { ) {
val veranstaltungen = remember { val veranstaltungen = remember {
listOf( listOf(
@ -195,7 +211,8 @@ fun LandingPage(
items(veranstaltungen) { veranstaltung -> items(veranstaltungen) { veranstaltung ->
VeranstaltungsCardWeb( VeranstaltungsCardWeb(
veranstaltung = veranstaltung, veranstaltung = veranstaltung,
onNennenClick = { tId -> onNennenClick(veranstaltung.id, tId) } onNennenClick = { tId -> onNennenClick(veranstaltung.id, tId) },
onAusschreibungClick = onAusschreibungClick
) )
} }
} }
@ -204,7 +221,8 @@ fun LandingPage(
@Composable @Composable
fun VeranstaltungsCardWeb( fun VeranstaltungsCardWeb(
veranstaltung: VeranstaltungWebModel, veranstaltung: VeranstaltungWebModel,
onNennenClick: (Long) -> Unit onNennenClick: (Long) -> Unit,
onAusschreibungClick: (String) -> Unit
) { ) {
Card( Card(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
@ -230,7 +248,8 @@ fun VeranstaltungsCardWeb(
veranstaltung.turniere.forEach { turnier -> veranstaltung.turniere.forEach { turnier ->
TurnierCardWeb( TurnierCardWeb(
turnier = turnier, turnier = turnier,
onNennenClick = { onNennenClick(turnier.id) } onNennenClick = { onNennenClick(turnier.id) },
onAusschreibungClick = { onAusschreibungClick(turnier.pdfUrl) }
) )
} }
} }
@ -240,7 +259,8 @@ fun VeranstaltungsCardWeb(
@Composable @Composable
fun TurnierCardWeb( fun TurnierCardWeb(
turnier: TurnierWebModel, turnier: TurnierWebModel,
onNennenClick: () -> Unit onNennenClick: () -> Unit,
onAusschreibungClick: () -> Unit
) { ) {
BoxWithConstraints { BoxWithConstraints {
val isMobile = maxWidth < 500.dp val isMobile = maxWidth < 500.dp
@ -258,7 +278,7 @@ fun TurnierCardWeb(
horizontalArrangement = Arrangement.spacedBy(8.dp) horizontalArrangement = Arrangement.spacedBy(8.dp)
) { ) {
TextButton( TextButton(
onClick = { /* PDF öffnen Logik */ }, onClick = onAusschreibungClick,
modifier = Modifier.weight(1f) modifier = Modifier.weight(1f)
) { ) {
Icon(Icons.Default.Description, contentDescription = null) Icon(Icons.Default.Description, contentDescription = null)
@ -287,7 +307,7 @@ fun TurnierCardWeb(
} }
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) { Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
TextButton(onClick = { /* PDF öffnen Logik */ }) { TextButton(onClick = onAusschreibungClick) {
Icon(Icons.Default.Description, contentDescription = null) Icon(Icons.Default.Description, contentDescription = null)
Spacer(Modifier.width(4.dp)) Spacer(Modifier.width(4.dp))
Text("Ausschreibung") Text("Ausschreibung")