diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index dd68fbd..bf6b3bc 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -15,8 +15,7 @@ plugins { kotlin { - @OptIn(ExperimentalWasmDsl::class) - wasmJs { + js { moduleName = "composeApp" browser { val projectDirPath = project.projectDir.path @@ -58,6 +57,7 @@ kotlin { commonMain.dependencies { implementation(libs.banking.client.model) + implementation(libs.fints4k.banking.client) implementation(libs.kcsv) implementation(libs.klf) diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/dialogs/AddAccountDialog.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/dialogs/AddAccountDialog.kt index bf16470..4f4de4e 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/dialogs/AddAccountDialog.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/dialogs/AddAccountDialog.kt @@ -6,12 +6,16 @@ import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Close import androidx.compose.runtime.* +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.window.Dialog +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import net.codinux.banking.ui.forms.* import net.codinux.banking.ui.model.BankInfo import net.codinux.banking.ui.service.Colors @@ -32,6 +36,11 @@ fun AddAccountDialog( derivedStateOf { selectedBank != null && loginName.length > 3 && password.length > 3 } } + var isAddingAccount by remember { mutableStateOf(false) } + + val coroutineScope = rememberCoroutineScope() + + Dialog(onDismissRequest = onDismiss) { RoundedCornersCard { Column(Modifier.background(Color.White).padding(8.dp)) { @@ -93,10 +102,35 @@ fun AddAccountDialog( Spacer(Modifier.width(8.dp)) TextButton( - onClick = onDismiss, - enabled = isRequiredDataEntered + modifier = Modifier.width(150.dp), + enabled = isRequiredDataEntered && isAddingAccount == false, + onClick = { + selectedBank?.let { + isAddingAccount = true + + coroutineScope.launch { // TODO: launch on Dispatchers.IO where it is available + val errorMessage = DI.bankingService.addAccount(selectedBank!!, loginName, password) + + withContext(Dispatchers.Main) { + isAddingAccount = false + + if (errorMessage == null) { + onDismiss() + } else { + // TODO: show error Message + } + } + } + } + } ) { - Text("Hinzufügen") + Row(verticalAlignment = Alignment.CenterVertically) { + if (isAddingAccount) { + CircularProgressIndicator(Modifier.padding(end = 6.dp)) + } + + Text("Hinzufügen") + } } } } diff --git a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankingService.kt b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankingService.kt index d35d572..2ce5264 100644 --- a/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankingService.kt +++ b/composeApp/src/commonMain/kotlin/net/codinux/banking/ui/service/BankingService.kt @@ -2,8 +2,12 @@ package net.codinux.banking.ui.service import bankmeister.composeapp.generated.resources.Res import kotlinx.datetime.LocalDate +import net.codinux.banking.client.SimpleBankingClientCallback +import net.codinux.banking.client.fints4k.FinTs4kBankingClientForCustomer import net.codinux.banking.client.model.AccountTransaction import net.codinux.banking.client.model.Amount +import net.codinux.banking.fints.config.FinTsClientConfiguration +import net.codinux.banking.fints.config.FinTsClientOptions import net.codinux.banking.ui.model.BankInfo import net.codinux.csv.reader.CsvReader import net.codinux.log.logger @@ -33,6 +37,29 @@ class BankingService( return transactions } + suspend fun addAccount(bank: BankInfo, loginName: String, password: String): String? { + try { + val config = FinTsClientConfiguration(FinTsClientOptions(true)) + val client = FinTs4kBankingClientForCustomer(bank.bankCode, loginName, password, config, SimpleBankingClientCallback { tanChallenge, callback -> + // TODO: show EnterTanDialog + }) + + val response = client.getAccountDataAsync() + response.data?.let { accountData -> + if (cachedTransactions == null) { + cachedTransactions = accountData.bookedTransactions + } else { + cachedTransactions = (cachedTransactions!! + accountData.bookedTransactions).sortedByDescending { it.valueDate } + } + } + + return response.error?.internalError ?: response.error?.errorMessagesFromBank?.joinToString("\n") + } catch (e: Throwable) { + log.error(e) { "Could not add account for ${bank.name} $loginName" } + return e.message + } + } + private suspend fun readTransactionsFromCsv(): List { val csv = Res.readBytes("files/transactions.csv").decodeToString() val csvReader = CsvReader(hasHeaderRow = true, reuseRowInstance = true, skipEmptyRows = true).read(csv) diff --git a/gradle.properties b/gradle.properties index 93239c3..98924f5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,4 +8,7 @@ android.nonTransitiveRClass=true android.useAndroidX=true #Kotlin Multiplatform -kotlin.mpp.enableCInteropCommonization=true \ No newline at end of file +kotlin.mpp.enableCInteropCommonization=true + +# Compose Multiplatform Web +org.jetbrains.compose.experimental.jscanvas.enabled=true \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 76b03fb..5d68080 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -26,6 +26,7 @@ junit = "4.13.2" [libraries] banking-client-model = { group = "net.codinux.banking.client", name = "banking-client-model", version.ref = "banking-client" } +fints4k-banking-client = { group = "net.codinux.banking.client", name = "fints4k-banking-client", version.ref = "banking-client" } kcsv = { group = "net.codinux.csv", name = "kcsv", version.ref = "kcsv" } klf = { group = "net.codinux.log", name = "klf", version.ref = "klf" } diff --git a/settings.gradle.kts b/settings.gradle.kts index e7673d6..a10d6cc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -25,6 +25,10 @@ dependencyResolutionManagement { } } mavenCentral() + mavenLocal() + maven { + setUrl("https://maven.dankito.net/api/packages/codinux/maven") + } } }