diff --git a/client/build.gradle.kts b/client/build.gradle.kts
index 8288d45b..20da3102 100644
--- a/client/build.gradle.kts
+++ b/client/build.gradle.kts
@@ -3,6 +3,7 @@ import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
plugins {
alias(libs.plugins.kotlin.multiplatform)
+ alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.compose.multiplatform)
alias(libs.plugins.compose.compiler)
}
@@ -28,6 +29,13 @@ kotlin {
implementation(compose.ui)
implementation(compose.components.resources)
implementation(compose.components.uiToolingPreview)
+
+ // HTTP client dependencies for ping-service
+ implementation(libs.ktor.client.core)
+ implementation(libs.ktor.client.contentNegotiation)
+ implementation(libs.ktor.client.serialization.kotlinx.json)
+ implementation(libs.kotlinx.coroutines.core)
+ implementation(libs.kotlinx.serialization.json)
}
commonTest.dependencies {
implementation(libs.kotlin.test)
@@ -35,6 +43,10 @@ kotlin {
jvmMain.dependencies {
implementation(compose.desktop.currentOs)
implementation(libs.kotlinx.coroutines.swing)
+ implementation(libs.ktor.client.cio)
+ }
+ wasmJsMain.dependencies {
+ implementation(libs.ktor.client.js)
}
}
}
diff --git a/client/src/commonMain/composeResources/drawable/compose-multiplatform.xml b/client/src/commonMain/composeResources/drawable/compose-multiplatform.xml
index 1ffc948c..704b517f 100644
--- a/client/src/commonMain/composeResources/drawable/compose-multiplatform.xml
+++ b/client/src/commonMain/composeResources/drawable/compose-multiplatform.xml
@@ -4,41 +4,51 @@
android:width="450dp"
android:height="450dp"
android:viewportWidth="64"
- android:viewportHeight="64">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+ android:viewportHeight="64"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://schemas.android.com/aapt ">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/src/commonMain/kotlin/at/mocode/App.kt b/client/src/commonMain/kotlin/at/mocode/App.kt
index 33f5e7a8..79f81661 100644
--- a/client/src/commonMain/kotlin/at/mocode/App.kt
+++ b/client/src/commonMain/kotlin/at/mocode/App.kt
@@ -7,20 +7,66 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeContentPadding
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.height
import androidx.compose.material3.Button
+import androidx.compose.material3.Card
+import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import org.jetbrains.compose.ui.tooling.preview.Preview
+import io.ktor.client.*
+import io.ktor.client.call.*
+import io.ktor.client.plugins.contentnegotiation.*
+import io.ktor.client.request.*
+import io.ktor.http.*
+import io.ktor.serialization.kotlinx.json.*
+import kotlinx.coroutines.launch
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class PingResponse(
+ val status: String,
+ val timestamp: String? = null,
+ val message: String? = null
+)
+
+sealed class PingState {
+ object Idle : PingState()
+ object Loading : PingState()
+ data class Success(val response: PingResponse) : PingState()
+ data class Error(val message: String) : PingState()
+}
@Composable
@Preview
fun App() {
MaterialTheme {
var showContent by remember { mutableStateOf(false) }
+ var pingState by remember { mutableStateOf(PingState.Idle) }
+ val coroutineScope = rememberCoroutineScope()
+
+ // Create HTTP client
+ val httpClient = remember {
+ HttpClient {
+ install(ContentNegotiation) {
+ json()
+ }
+ }
+ }
+
+ // Cleanup client on disposal
+ DisposableEffect(Unit) {
+ onDispose {
+ httpClient.close()
+ }
+ }
+
Column(
modifier = Modifier
.background(MaterialTheme.colorScheme.background)
@@ -35,6 +81,7 @@ fun App() {
modifier = Modifier.padding(top = 32.dp, bottom = 16.dp)
)
+ // Platform Info Button
Button(
onClick = { showContent = !showContent },
modifier = Modifier.padding(16.dp)
@@ -42,6 +89,91 @@ fun App() {
Text(if (showContent) "Platform-Info ausblenden" else "Platform-Info anzeigen")
}
+ // Ping Backend Button
+ Button(
+ onClick = {
+ coroutineScope.launch {
+ pingState = PingState.Loading
+ try {
+ val response: PingResponse = httpClient.get("http://localhost:8082/ping").body()
+ pingState = PingState.Success(response)
+ } catch (e: Exception) {
+ pingState = PingState.Error(e.message ?: "Unknown error occurred")
+ }
+ }
+ },
+ enabled = pingState !is PingState.Loading,
+ modifier = Modifier.padding(8.dp)
+ ) {
+ if (pingState is PingState.Loading) {
+ CircularProgressIndicator(
+ modifier = Modifier.height(16.dp),
+ color = MaterialTheme.colorScheme.onPrimary
+ )
+ Spacer(modifier = Modifier.height(8.dp))
+ }
+ Text("Ping Backend")
+ }
+
+ // Ping Status Display
+ when (val state = pingState) {
+ is PingState.Success -> {
+ Card(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(16.dp)
+ ) {
+ Column(
+ modifier = Modifier.padding(16.dp)
+ ) {
+ Text(
+ text = "✅ Ping erfolgreich!",
+ style = MaterialTheme.typography.titleMedium,
+ color = Color(0xFF4CAF50)
+ )
+ Text(
+ text = "Status: ${state.response.status}",
+ style = MaterialTheme.typography.bodyMedium,
+ modifier = Modifier.padding(top = 4.dp)
+ )
+ state.response.timestamp?.let {
+ Text(
+ text = "Zeit: $it",
+ style = MaterialTheme.typography.bodySmall,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.padding(top = 2.dp)
+ )
+ }
+ }
+ }
+ }
+ is PingState.Error -> {
+ Card(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(16.dp)
+ ) {
+ Column(
+ modifier = Modifier.padding(16.dp)
+ ) {
+ Text(
+ text = "❌ Ping fehlgeschlagen",
+ style = MaterialTheme.typography.titleMedium,
+ color = Color(0xFFF44336)
+ )
+ Text(
+ text = "Fehler: ${state.message}",
+ style = MaterialTheme.typography.bodyMedium,
+ modifier = Modifier.padding(top = 4.dp)
+ )
+ }
+ }
+ }
+ else -> {
+ // Idle or Loading state - no additional display needed
+ }
+ }
+
AnimatedVisibility(showContent) {
val greeting = remember { Greeting().greet() }
Column(
diff --git a/temp/ping-service/src/main/kotlin/at/mocode/temp/pingservice/PingController.kt b/temp/ping-service/src/main/kotlin/at/mocode/temp/pingservice/PingController.kt
index 548f29e9..35cff732 100644
--- a/temp/ping-service/src/main/kotlin/at/mocode/temp/pingservice/PingController.kt
+++ b/temp/ping-service/src/main/kotlin/at/mocode/temp/pingservice/PingController.kt
@@ -1,10 +1,12 @@
package at.mocode.temp.pingservice
+import org.springframework.web.bind.annotation.CrossOrigin
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
@RestController
+@CrossOrigin(origins = ["http://localhost:8080"])
class PingController(
private val pingService: PingServiceCircuitBreaker
) {