(fix) Umbau zu SCS

This commit is contained in:
stefan
2025-07-21 12:08:20 +02:00
parent 83d0d81193
commit 62b5e71427
34 changed files with 3403 additions and 20 deletions
+24
View File
@@ -0,0 +1,24 @@
import at.mocode.masterdata.ui.components.StammdatenListe
import react.create
/**
* Main entry point for the Master Data JavaScript build.
*
* This function serves as the entry point for the Kotlin/JS application.
* It registers the React component as a web component using r2wc.
*/
fun main() {
console.log("Master Data JS module loaded successfully!")
// Import r2wc function from @r2wc/react-to-web-component npm package
val r2wc = js("require('@r2wc/react-to-web-component')")
// Convert React component to Web Component using r2wc
val StammdatenListeWebComponent = r2wc(StammdatenListe, js("{}"))
// Register the new component with a custom HTML tag
js("customElements.define('stammdaten-liste', arguments[0])")(StammdatenListeWebComponent)
console.log("Web component 'stammdaten-liste' registered successfully!")
console.log("You can now use <stammdaten-liste></stammdaten-liste> in your HTML")
}
@@ -0,0 +1,257 @@
package at.mocode.masterdata.ui.components
import at.mocode.masterdata.domain.model.LandDefinition
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.request.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import kotlinx.serialization.json.Json
import react.*
import react.dom.html.ReactHTML.div
import react.dom.html.ReactHTML.h1
import react.dom.html.ReactHTML.h2
import react.dom.html.ReactHTML.h3
import react.dom.html.ReactHTML.p
import react.dom.html.ReactHTML.span
import emotion.react.css
/**
* Props for the StammdatenListe component
*/
external interface StammdatenListeProps : Props
// Create Ktor client for API calls
private val apiClient = HttpClient {
install(ContentNegotiation) {
json(Json {
ignoreUnknownKeys = true
})
}
}
/**
* React component that displays master data (Stammdaten).
*
* This component loads master data from the API and renders it as HTML.
* Currently focuses on countries (LandDefinition) but can be extended for other master data types.
* Uses useState for state management and useEffectOnce for data loading.
*/
val StammdatenListe = FC<StammdatenListeProps> { _ ->
// State management with useState
var countries by useState<List<LandDefinition>>(emptyList())
var loading by useState(true)
var error by useState<String?>(null)
// Data loading with useEffectOnce hook
useEffectOnce {
val scope = MainScope()
scope.launch {
try {
loading = true
error = null
// Load data with Ktor client
val response = apiClient.get("http://localhost:8080/api/masterdata/countries")
val loadedCountries: List<LandDefinition> = response.body()
countries = loadedCountries
} catch (e: Exception) {
error = "Fehler beim Laden der Stammdaten: ${e.message}"
console.error("Error loading master data:", e)
} finally {
loading = false
}
}
}
// Render HTML with React DOM elements
div {
css {
// Basic styling for the main container
"padding" to "20px"
"fontFamily" to "Arial, sans-serif"
"maxWidth" to "1200px"
"margin" to "0 auto"
}
h1 {
css {
"color" to "#2c3e50"
"borderBottom" to "2px solid #3498db"
"paddingBottom" to "10px"
"marginBottom" to "20px"
}
+"Stammdaten"
}
h2 {
css {
"color" to "#34495e"
"marginTop" to "20px"
"marginBottom" to "15px"
"fontSize" to "1.5em"
}
+"Länder"
}
when {
loading -> {
div {
css {
"padding" to "20px"
"textAlign" to "center"
"color" to "#666"
"fontSize" to "18px"
}
+"Lade Stammdaten..."
}
}
error != null -> {
div {
css {
"padding" to "20px"
"textAlign" to "center"
"color" to "#e74c3c"
"backgroundColor" to "#fdeaea"
"border" to "1px solid #e74c3c"
"borderRadius" to "8px"
"margin" to "20px 0"
}
+error!!
}
}
countries.isEmpty() -> {
div {
css {
"padding" to "20px"
"textAlign" to "center"
"color" to "#666"
"backgroundColor" to "#f8f9fa"
"border" to "1px solid #e0e0e0"
"borderRadius" to "8px"
"margin" to "20px 0"
}
+"Keine Länder verfügbar"
}
}
else -> {
div {
css {
"display" to "grid"
"gridTemplateColumns" to "repeat(auto-fill, minmax(300px, 1fr))"
"gap" to "20px"
}
countries.forEach { country ->
div {
css {
"border" to "1px solid #e0e0e0"
"borderRadius" to "8px"
"padding" to "15px"
"backgroundColor" to "#f9f9f9"
"boxShadow" to "0 2px 4px rgba(0,0,0,0.1)"
"transition" to "transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out"
"hover" to {
"transform" to "translateY(-5px)"
"boxShadow" to "0 5px 15px rgba(0,0,0,0.1)"
}
}
h3 {
css {
"color" to "#3498db"
"marginTop" to "0"
"marginBottom" to "10px"
"borderBottom" to "1px solid #e0e0e0"
"paddingBottom" to "5px"
}
+country.nameDeutsch
}
// ISO codes
p {
span {
+"🌍"
}
+" ISO-Codes: ${country.isoAlpha2Code} / ${country.isoAlpha3Code}"
country.isoNumerischerCode?.let { numCode ->
+" / $numCode"
}
}
// English name if available
country.nameEnglisch?.let { englishName ->
p {
span {
+"🇬🇧"
}
+" Englischer Name: $englishName"
}
}
// EU/EWR membership
val membershipInfo = mutableListOf<String>()
country.istEuMitglied?.let { isEuMember ->
if (isEuMember) membershipInfo.add("EU-Mitglied")
}
country.istEwrMitglied?.let { isEwrMember ->
if (isEwrMember) membershipInfo.add("EWR-Mitglied")
}
if (membershipInfo.isNotEmpty()) {
p {
span {
+"🇪🇺"
}
+" Mitgliedschaft: ${membershipInfo.joinToString(", ")}"
}
}
// Status
p {
span {
+""
}
+" Status: ${if (country.istAktiv) "Aktiv" else "Inaktiv"}"
}
// Sort order if available
country.sortierReihenfolge?.let { sortOrder ->
p {
span {
+"🔢"
}
+" Sortierreihenfolge: $sortOrder"
}
}
// Coat of arms/flag URL if available
country.wappenUrl?.let { flagUrl ->
p {
span {
+"🏴"
}
+" Wappen/Flagge: $flagUrl"
}
}
// Creation and update dates
p {
span {
+"📅"
}
+" Erstellt am: ${country.createdAt}"
}
p {
span {
+"🔄"
}
+" Zuletzt geändert: ${country.updatedAt}"
}
}
}
}
}
}
}
}