refactor: Migrate from monolithic to modular architecture
1. **Docker-Compose für Entwicklung optimieren** 2. **Umgebungsvariablen für lokale Entwicklung** 3. **Service-Abhängigkeiten** 4. **Docker-Compose für Produktion** 5. **Dokumentation**
This commit is contained in:
-44
@@ -1,44 +0,0 @@
|
||||
package at.mocode.client.common.components.events
|
||||
|
||||
import at.mocode.events.domain.model.Veranstaltung
|
||||
|
||||
/**
|
||||
* Simple JS-specific utility functions for event management UI
|
||||
*/
|
||||
object EventUIUtils {
|
||||
|
||||
/**
|
||||
* Formats an event for display in the browser
|
||||
*/
|
||||
fun formatEventForDisplay(event: Veranstaltung): String {
|
||||
return buildString {
|
||||
append("Event: ${event.name}")
|
||||
append(" | Location: ${event.ort}")
|
||||
append(" | From: ${event.startDatum} to: ${event.endDatum}")
|
||||
if (event.beschreibung != null) {
|
||||
append(" | Description: ${event.beschreibung}")
|
||||
}
|
||||
if (event.sparten.isNotEmpty()) {
|
||||
append(" | Sports: ${event.sparten.joinToString(", ") { it.name }}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a simple HTML representation of an event
|
||||
*/
|
||||
fun createEventHtml(event: Veranstaltung): String {
|
||||
return """
|
||||
<div class="event-card">
|
||||
<h3>${event.name}</h3>
|
||||
<p><strong>Location:</strong> ${event.ort}</p>
|
||||
<p><strong>Date:</strong> ${event.startDatum} - ${event.endDatum}</p>
|
||||
${if (event.beschreibung != null) "<p><strong>Description:</strong> ${event.beschreibung}</p>" else ""}
|
||||
${if (event.sparten.isNotEmpty())
|
||||
"<p><strong>Sports:</strong> ${event.sparten.joinToString(", ") { it.name }}</p>"
|
||||
else ""}
|
||||
</div>
|
||||
""".trimIndent()
|
||||
}
|
||||
}
|
||||
|
||||
-176
@@ -1,176 +0,0 @@
|
||||
package at.mocode.client.common.components.events
|
||||
|
||||
import at.mocode.events.domain.model.Veranstaltung
|
||||
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.h3
|
||||
import react.dom.html.ReactHTML.p
|
||||
import react.dom.html.ReactHTML.span
|
||||
import emotion.react.css
|
||||
|
||||
/**
|
||||
* Props for the VeranstaltungsListe component
|
||||
*/
|
||||
external interface VeranstaltungsListeProps : Props
|
||||
|
||||
// Create Ktor client for API calls
|
||||
private val apiClient = HttpClient {
|
||||
install(ContentNegotiation) {
|
||||
json(Json {
|
||||
ignoreUnknownKeys = true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* React component that displays a list of events (Veranstaltungen).
|
||||
*
|
||||
* This component loads event data from the API and renders it as HTML.
|
||||
* Uses useState for state management and useEffectOnce for data loading.
|
||||
*/
|
||||
val VeranstaltungsListe = FC<VeranstaltungsListeProps> { _ ->
|
||||
// State management with useState
|
||||
var events by useState<List<Veranstaltung>>(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/events")
|
||||
val loadedEvents: List<Veranstaltung> = response.body()
|
||||
events = loadedEvents
|
||||
} catch (e: Exception) {
|
||||
error = "Fehler beim Laden der Veranstaltungen: ${e.message}"
|
||||
console.error("Error loading events:", e)
|
||||
} finally {
|
||||
loading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Render HTML with React DOM elements
|
||||
div {
|
||||
css {
|
||||
// Basic styling for the main container
|
||||
}
|
||||
|
||||
h1 {
|
||||
+"Veranstaltungen"
|
||||
}
|
||||
|
||||
when {
|
||||
loading -> {
|
||||
div {
|
||||
+"Lade Veranstaltungen..."
|
||||
}
|
||||
}
|
||||
error != null -> {
|
||||
div {
|
||||
+error!!
|
||||
}
|
||||
}
|
||||
events.isEmpty() -> {
|
||||
div {
|
||||
+"Keine Veranstaltungen verfügbar"
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
div {
|
||||
events.forEach { event ->
|
||||
div {
|
||||
h3 {
|
||||
+event.name
|
||||
}
|
||||
|
||||
p {
|
||||
span {
|
||||
+"📍"
|
||||
}
|
||||
+" ${event.ort}"
|
||||
}
|
||||
|
||||
p {
|
||||
span {
|
||||
+"📅"
|
||||
}
|
||||
if (event.isMultiDay()) {
|
||||
+" ${event.startDatum} - ${event.endDatum} (${event.getDurationInDays()} Tage)"
|
||||
} else {
|
||||
+" ${event.startDatum} (Eintägige Veranstaltung)"
|
||||
}
|
||||
}
|
||||
|
||||
// Status indicators
|
||||
val statusList = mutableListOf<String>()
|
||||
if (event.istAktiv) statusList.add("Aktiv")
|
||||
if (event.istOeffentlich) statusList.add("Öffentlich")
|
||||
if (event.isRegistrationOpen()) statusList.add("Anmeldung offen")
|
||||
if (statusList.isNotEmpty()) {
|
||||
p {
|
||||
span {
|
||||
+"ℹ️"
|
||||
}
|
||||
+" Status: ${statusList.joinToString(", ")}"
|
||||
}
|
||||
}
|
||||
|
||||
// Description
|
||||
if (!event.beschreibung.isNullOrBlank()) {
|
||||
p {
|
||||
span {
|
||||
+"📝"
|
||||
}
|
||||
+" ${event.beschreibung}"
|
||||
}
|
||||
}
|
||||
|
||||
// Sports/Sparten
|
||||
if (event.sparten.isNotEmpty()) {
|
||||
p {
|
||||
span {
|
||||
+"🏆"
|
||||
}
|
||||
+" Sparten: ${event.sparten.joinToString(", ") { it.name }}"
|
||||
}
|
||||
}
|
||||
|
||||
// Additional info
|
||||
event.maxTeilnehmer?.let { max ->
|
||||
p {
|
||||
span {
|
||||
+"👥"
|
||||
}
|
||||
+" Max. Teilnehmer: $max"
|
||||
}
|
||||
}
|
||||
|
||||
event.anmeldeschluss?.let { deadline ->
|
||||
p {
|
||||
span {
|
||||
+"⏰"
|
||||
}
|
||||
+" Anmeldeschluss: $deadline"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-308
@@ -1,308 +0,0 @@
|
||||
package at.mocode.client.common.components.horses
|
||||
|
||||
import at.mocode.horses.domain.model.DomPferd
|
||||
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.h3
|
||||
import react.dom.html.ReactHTML.p
|
||||
import react.dom.html.ReactHTML.span
|
||||
import emotion.react.css
|
||||
|
||||
/**
|
||||
* Props for the PferdeListe component
|
||||
*/
|
||||
external interface PferdeListeProps : Props
|
||||
|
||||
// Create Ktor client for API calls
|
||||
private val apiClient = HttpClient {
|
||||
install(ContentNegotiation) {
|
||||
json(Json {
|
||||
ignoreUnknownKeys = true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* React component that displays a list of horses (Pferde).
|
||||
*
|
||||
* This component loads horse data from the API and renders it as HTML.
|
||||
* Uses useState for state management and useEffectOnce for data loading.
|
||||
*/
|
||||
val PferdeListe = FC<PferdeListeProps> { _ ->
|
||||
// State management with useState
|
||||
var horses by useState<List<DomPferd>>(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/horses")
|
||||
val loadedHorses: List<DomPferd> = response.body()
|
||||
horses = loadedHorses
|
||||
} catch (e: Exception) {
|
||||
error = "Fehler beim Laden der Pferde: ${e.message}"
|
||||
console.error("Error loading horses:", 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"
|
||||
}
|
||||
+"Pferde-Register"
|
||||
}
|
||||
|
||||
when {
|
||||
loading -> {
|
||||
div {
|
||||
css {
|
||||
"padding" to "20px"
|
||||
"textAlign" to "center"
|
||||
"color" to "#666"
|
||||
"fontSize" to "18px"
|
||||
}
|
||||
+"Lade Pferde..."
|
||||
}
|
||||
}
|
||||
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!!
|
||||
}
|
||||
}
|
||||
horses.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 Pferde verfügbar"
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
div {
|
||||
css {
|
||||
"display" to "grid"
|
||||
"gridTemplateColumns" to "repeat(auto-fill, minmax(300px, 1fr))"
|
||||
"gap" to "20px"
|
||||
}
|
||||
horses.forEach { horse ->
|
||||
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"
|
||||
}
|
||||
+horse.getDisplayName()
|
||||
}
|
||||
|
||||
// Basic information
|
||||
p {
|
||||
span {
|
||||
+"🐎"
|
||||
}
|
||||
+" Geschlecht: ${horse.geschlecht.name}"
|
||||
}
|
||||
|
||||
horse.geburtsdatum?.let { birthDate ->
|
||||
p {
|
||||
span {
|
||||
+"📅"
|
||||
}
|
||||
+" Geburtsdatum: $birthDate"
|
||||
horse.getAge()?.let { age ->
|
||||
+" (${age} Jahre alt)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
horse.rasse?.let { breed ->
|
||||
p {
|
||||
span {
|
||||
+"🏇"
|
||||
}
|
||||
+" Rasse: $breed"
|
||||
}
|
||||
}
|
||||
|
||||
horse.farbe?.let { color ->
|
||||
p {
|
||||
span {
|
||||
+"🎨"
|
||||
}
|
||||
+" Farbe: $color"
|
||||
}
|
||||
}
|
||||
|
||||
horse.stockmass?.let { height ->
|
||||
p {
|
||||
span {
|
||||
+"📏"
|
||||
}
|
||||
+" Stockmaß: ${height} cm"
|
||||
}
|
||||
}
|
||||
|
||||
// Identification numbers
|
||||
val identificationNumbers = mutableListOf<String>()
|
||||
horse.lebensnummer?.let { identificationNumbers.add("Lebensnummer: $it") }
|
||||
horse.chipNummer?.let { identificationNumbers.add("Chip: $it") }
|
||||
horse.passNummer?.let { identificationNumbers.add("Pass: $it") }
|
||||
horse.oepsNummer?.let { identificationNumbers.add("OEPS: $it") }
|
||||
horse.feiNummer?.let { identificationNumbers.add("FEI: $it") }
|
||||
|
||||
if (identificationNumbers.isNotEmpty()) {
|
||||
p {
|
||||
span {
|
||||
+"🆔"
|
||||
}
|
||||
+" Identifikation: ${identificationNumbers.joinToString(", ")}"
|
||||
}
|
||||
}
|
||||
|
||||
// Pedigree information
|
||||
val pedigreeInfo = mutableListOf<String>()
|
||||
horse.vaterName?.let { pedigreeInfo.add("Vater: $it") }
|
||||
horse.mutterName?.let { pedigreeInfo.add("Mutter: $it") }
|
||||
horse.mutterVaterName?.let { pedigreeInfo.add("Muttervater: $it") }
|
||||
|
||||
if (pedigreeInfo.isNotEmpty()) {
|
||||
p {
|
||||
span {
|
||||
+"🧬"
|
||||
}
|
||||
+" Abstammung: ${pedigreeInfo.joinToString(", ")}"
|
||||
}
|
||||
}
|
||||
|
||||
// Breeding information
|
||||
horse.zuechterName?.let { breeder ->
|
||||
p {
|
||||
span {
|
||||
+"👨🌾"
|
||||
}
|
||||
+" Züchter: $breeder"
|
||||
}
|
||||
}
|
||||
|
||||
horse.zuchtbuchNummer?.let { studbook ->
|
||||
p {
|
||||
span {
|
||||
+"📖"
|
||||
}
|
||||
+" Zuchtbuchnummer: $studbook"
|
||||
}
|
||||
}
|
||||
|
||||
// Status indicators
|
||||
val statusList = mutableListOf<String>()
|
||||
if (horse.istAktiv) statusList.add("Aktiv") else statusList.add("Inaktiv")
|
||||
if (horse.hasCompleteIdentification()) statusList.add("Vollständig identifiziert")
|
||||
if (horse.isOepsRegistered()) statusList.add("OEPS registriert")
|
||||
if (horse.isFeiRegistered()) statusList.add("FEI registriert")
|
||||
|
||||
p {
|
||||
span {
|
||||
+"ℹ️"
|
||||
}
|
||||
+" Status: ${statusList.joinToString(", ")}"
|
||||
}
|
||||
|
||||
// Data source
|
||||
p {
|
||||
span {
|
||||
+"📊"
|
||||
}
|
||||
+" Datenquelle: ${horse.datenQuelle.name}"
|
||||
}
|
||||
|
||||
// Notes
|
||||
horse.bemerkungen?.let { notes ->
|
||||
p {
|
||||
span {
|
||||
+"📝"
|
||||
}
|
||||
+" Bemerkungen: $notes"
|
||||
}
|
||||
}
|
||||
|
||||
// Creation and update dates
|
||||
p {
|
||||
span {
|
||||
+"📅"
|
||||
}
|
||||
+" Erstellt am: ${horse.createdAt}"
|
||||
}
|
||||
|
||||
p {
|
||||
span {
|
||||
+"🔄"
|
||||
}
|
||||
+" Zuletzt geändert: ${horse.updatedAt}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-257
@@ -1,257 +0,0 @@
|
||||
package at.mocode.client.common.components.masterdata
|
||||
|
||||
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}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
package at.mocode.client.common.di
|
||||
|
||||
import at.mocode.members.application.usecase.CreatePersonUseCase
|
||||
import at.mocode.members.domain.repository.PersonRepository
|
||||
import at.mocode.members.domain.repository.VereinRepository
|
||||
import at.mocode.members.domain.service.MasterDataService
|
||||
import at.mocode.client.web.viewmodel.CreatePersonViewModel
|
||||
import at.mocode.client.web.viewmodel.PersonListViewModel
|
||||
|
||||
/**
|
||||
* Simple dependency injection container for the application.
|
||||
* In a real application, you might want to use a proper DI framework like Koin.
|
||||
*/
|
||||
object AppDependencies {
|
||||
|
||||
// Mock implementations for demonstration
|
||||
// In a real application, these would be proper implementations
|
||||
private val mockPersonRepository = object : PersonRepository {
|
||||
override suspend fun save(person: at.mocode.members.domain.model.DomPerson): at.mocode.members.domain.model.DomPerson {
|
||||
// Mock implementation - just return the person with an ID
|
||||
return person.copy(personId = com.benasher44.uuid.uuid4())
|
||||
}
|
||||
|
||||
override suspend fun findById(id: com.benasher44.uuid.Uuid): at.mocode.members.domain.model.DomPerson? {
|
||||
return null // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun findByOepsSatzNr(oepsSatzNr: String): at.mocode.members.domain.model.DomPerson? {
|
||||
return null // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun findByStammVereinId(vereinId: com.benasher44.uuid.Uuid): List<at.mocode.members.domain.model.DomPerson> {
|
||||
return emptyList() // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun findByName(searchTerm: String, limit: Int): List<at.mocode.members.domain.model.DomPerson> {
|
||||
return emptyList() // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun findAllActive(limit: Int, offset: Int): List<at.mocode.members.domain.model.DomPerson> {
|
||||
return emptyList() // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun countActive(): Long {
|
||||
return 0L // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun existsByOepsSatzNr(oepsSatzNr: String): Boolean {
|
||||
return false // Mock implementation - no duplicates for demo
|
||||
}
|
||||
|
||||
override suspend fun delete(id: com.benasher44.uuid.Uuid): Boolean {
|
||||
return true // Mock implementation
|
||||
}
|
||||
}
|
||||
|
||||
private val mockVereinRepository = object : VereinRepository {
|
||||
override suspend fun findById(id: com.benasher44.uuid.Uuid): at.mocode.members.domain.model.DomVerein? {
|
||||
return null // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun findByOepsVereinsNr(oepsVereinsNr: String): at.mocode.members.domain.model.DomVerein? {
|
||||
return null // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun findByName(searchTerm: String, limit: Int): List<at.mocode.members.domain.model.DomVerein> {
|
||||
return emptyList() // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun findByBundeslandId(bundeslandId: com.benasher44.uuid.Uuid): List<at.mocode.members.domain.model.DomVerein> {
|
||||
return emptyList() // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun findByLandId(landId: com.benasher44.uuid.Uuid): List<at.mocode.members.domain.model.DomVerein> {
|
||||
return emptyList() // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun findAllActive(limit: Int, offset: Int): List<at.mocode.members.domain.model.DomVerein> {
|
||||
return emptyList() // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun findByLocation(searchTerm: String, limit: Int): List<at.mocode.members.domain.model.DomVerein> {
|
||||
return emptyList() // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun save(verein: at.mocode.members.domain.model.DomVerein): at.mocode.members.domain.model.DomVerein {
|
||||
return verein.copy(vereinId = com.benasher44.uuid.uuid4()) // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun delete(id: com.benasher44.uuid.Uuid): Boolean {
|
||||
return true // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun existsByOepsVereinsNr(oepsVereinsNr: String): Boolean {
|
||||
return false // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun countActive(): Long {
|
||||
return 0L // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun countActiveByBundeslandId(bundeslandId: com.benasher44.uuid.Uuid): Long {
|
||||
return 0L // Mock implementation
|
||||
}
|
||||
}
|
||||
|
||||
private val mockMasterDataService = object : MasterDataService {
|
||||
override suspend fun countryExists(countryId: com.benasher44.uuid.Uuid): Boolean {
|
||||
return true // Mock implementation - assume all countries exist
|
||||
}
|
||||
|
||||
override suspend fun stateExists(stateId: com.benasher44.uuid.Uuid): Boolean {
|
||||
return true // Mock implementation - assume all states exist
|
||||
}
|
||||
|
||||
override suspend fun getCountryById(countryId: com.benasher44.uuid.Uuid): MasterDataService.CountryInfo? {
|
||||
return null // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun getStateById(stateId: com.benasher44.uuid.Uuid): MasterDataService.StateInfo? {
|
||||
return null // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun getAllCountries(): List<MasterDataService.CountryInfo> {
|
||||
return emptyList() // Mock implementation
|
||||
}
|
||||
|
||||
override suspend fun getStatesByCountry(countryId: com.benasher44.uuid.Uuid): List<MasterDataService.StateInfo> {
|
||||
return emptyList() // Mock implementation
|
||||
}
|
||||
}
|
||||
|
||||
// Use case instances
|
||||
private val createPersonUseCase = CreatePersonUseCase(
|
||||
personRepository = mockPersonRepository,
|
||||
vereinRepository = mockVereinRepository,
|
||||
masterDataService = mockMasterDataService
|
||||
)
|
||||
|
||||
// ViewModel factory methods
|
||||
fun createPersonViewModel(): CreatePersonViewModel {
|
||||
return CreatePersonViewModel(createPersonUseCase)
|
||||
}
|
||||
|
||||
fun personListViewModel(): PersonListViewModel {
|
||||
return PersonListViewModel(mockPersonRepository)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user