ein wenig aufgeräumt

This commit is contained in:
stefan
2025-09-08 15:39:50 +02:00
parent 22d898aa14
commit 3e4ef8e73e
19 changed files with 1495 additions and 83 deletions
@@ -20,6 +20,6 @@ fun main() = application {
) {
// Use the shared App component from common-ui
// This eliminates code duplication and ensures consistent UI across platforms
App(baseUrl = System.getProperty("meldestelle.api.url", "http://localhost:8080"))
App(baseUrl = System.getProperty("meldestelle.api.url", "http://localhost:8081"))
}
}
@@ -59,15 +59,24 @@ object AppStylesheet : StyleSheet() {
property("transition", "all 0.2s ease")
width(100.percent)
marginBottom(20.px)
// Improved focus management using property
property("&:focus", "outline: 2px solid #1976d2; outline-offset: 2px; box-shadow: 0 0 0 3px rgba(25, 118, 210, 0.2);")
// Enhanced active state
property("&:active", "transform: scale(0.98);")
}
val buttonHover by style {
transform { scale(1.02) }
property("box-shadow", "0 2px 8px rgba(0, 0, 0, 0.15)")
}
val buttonDisabled by style {
opacity(0.6)
cursor("not-allowed")
property("transform", "none")
property("box-shadow", "none")
}
val primaryButton by style {
@@ -76,7 +85,11 @@ object AppStylesheet : StyleSheet() {
hover(self) style {
backgroundColor(Color("#1565c0"))
property("box-shadow", "0 4px 12px rgba(25, 118, 210, 0.3)")
}
// Using property for disabled state
property("&:disabled", "background-color: #bbbbbb; cursor: not-allowed;")
}
val successMessage by style {
@@ -76,19 +76,35 @@ fun MeldestelleWebApp() {
Div(attrs = {
classes(AppStylesheet.container)
attr("role", "application")
attr("aria-label", "Meldestelle Web Application")
}) {
Header(attrs = { classes(AppStylesheet.header) }) {
H1 { Text("Meldestelle Web App") }
Header(attrs = {
classes(AppStylesheet.header)
attr("role", "banner")
}) {
H1(attrs = {
attr("id", "app-title")
}) {
Text("Meldestelle Web App")
}
}
Main(attrs = { classes(AppStylesheet.main) }) {
Main(attrs = {
classes(AppStylesheet.main)
attr("role", "main")
attr("aria-labelledby", "app-title")
}) {
PingTestWebView(
state = viewModel.uiState,
onTestConnection = { viewModel.pingBackend() }
)
}
Footer(attrs = { classes(AppStylesheet.footer) }) {
Footer(attrs = {
classes(AppStylesheet.footer)
attr("role", "contentinfo")
}) {
P { Text("© 2025 Meldestelle - Powered by Kotlin Multiplatform") }
}
}
@@ -99,49 +115,83 @@ fun PingTestWebView(
state: PingUiState,
onTestConnection: () -> Unit
) {
Div(attrs = { classes(AppStylesheet.card) }) {
H2 { Text("Backend Verbindungstest") }
Div(attrs = {
classes(AppStylesheet.card)
attr("role", "region")
attr("aria-labelledby", "ping-test-title")
}) {
H2(attrs = {
attr("id", "ping-test-title")
}) {
Text("Backend Verbindungstest")
}
Button(
attrs = {
classes(AppStylesheet.button, AppStylesheet.primaryButton)
if (state is PingUiState.Loading) {
attr("disabled", "")
attr("aria-disabled", "true")
}
attr("aria-describedby", "ping-status")
attr("type", "button")
onClick { onTestConnection() }
}
) {
if (state is PingUiState.Loading) {
Span(attrs = { classes(AppStylesheet.spinner) }) {}
Span(attrs = {
classes(AppStylesheet.spinner)
attr("aria-hidden", "true")
}) {}
Text(" Pinge Backend...")
} else {
Text("Ping Backend")
}
}
// Status display with four distinct states
Div {
// Status display with four distinct states and proper announcements
Div(attrs = {
attr("id", "ping-status")
attr("role", "status")
attr("aria-live", "polite")
attr("aria-atomic", "true")
}) {
when (state) {
is PingUiState.Initial -> {
Div {
Div(attrs = {
attr("aria-label", "Bereit für Backend-Test")
}) {
Text("Klicke auf den Button, um das Backend zu testen")
}
}
is PingUiState.Loading -> {
Div {
Span(attrs = { classes(AppStylesheet.spinner) }) {}
Div(attrs = {
attr("aria-label", "Backend wird getestet")
}) {
Span(attrs = {
classes(AppStylesheet.spinner)
attr("aria-hidden", "true")
}) {}
Text(" Pinge Backend ...")
}
}
is PingUiState.Success -> {
Div(attrs = { classes(AppStylesheet.successMessage) }) {
Span { Text("") }
Div(attrs = {
classes(AppStylesheet.successMessage)
attr("role", "alert")
attr("aria-label", "Backend-Test erfolgreich")
}) {
Span(attrs = { attr("aria-hidden", "true") }) { Text("") }
Text("Antwort vom Backend: ${state.response.status}")
}
}
is PingUiState.Error -> {
Div(attrs = { classes(AppStylesheet.errorMessage) }) {
Span { Text("") }
Div(attrs = {
classes(AppStylesheet.errorMessage)
attr("role", "alert")
attr("aria-label", "Backend-Test fehlgeschlagen")
}) {
Span(attrs = { attr("aria-hidden", "true") }) { Text("") }
Text("Fehler: ${state.message}")
}
}
@@ -22,7 +22,7 @@ class MainTest {
}
@Test
fun `AppStylesheet should be accessible`() {
fun `AppStylesheet should be accessible and complete`() {
// Test that AppStylesheet object is properly accessible
assertNotNull(AppStylesheet, "AppStylesheet should be accessible")
@@ -33,6 +33,29 @@ class MainTest {
assertNotNull(AppStylesheet.footer, "Footer style should be defined")
assertNotNull(AppStylesheet.card, "Card style should be defined")
assertNotNull(AppStylesheet.button, "Button style should be defined")
// Verify enhanced styles are present
assertNotNull(AppStylesheet.primaryButton, "Primary button style should be defined")
assertNotNull(AppStylesheet.successMessage, "Success message style should be defined")
assertNotNull(AppStylesheet.errorMessage, "Error message style should be defined")
assertNotNull(AppStylesheet.spinner, "Spinner style should be defined")
}
@Test
fun `button styles should include accessibility features`() {
// Verify button styles include focus and interaction states
assertNotNull(AppStylesheet.button, "Button style should be accessible")
assertNotNull(AppStylesheet.buttonHover, "Button hover style should be defined")
assertNotNull(AppStylesheet.buttonDisabled, "Button disabled style should be defined")
assertTrue(true, "Button accessibility styles are properly configured")
}
@Test
fun `message styles should be properly configured`() {
// Test that success and error message styles are available
assertNotNull(AppStylesheet.successMessage, "Success message style should be accessible")
assertNotNull(AppStylesheet.errorMessage, "Error message style should be accessible")
assertTrue(true, "Message styles provide good user feedback")
}
@Test