Added autocomplete also for amount to e.g. do the same transfer again; had to fix AutocompleteTextField's value setting for this
This commit is contained in:
parent
255cc41dce
commit
f29e4b5fcc
|
@ -26,6 +26,7 @@ private val bankingService = DI.bankingService
|
||||||
fun AddAccountDialog(
|
fun AddAccountDialog(
|
||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
) {
|
) {
|
||||||
|
var enteredBankSearchQuery by remember { mutableStateOf("") }
|
||||||
var selectedBank by remember { mutableStateOf<BankInfo?>(null) }
|
var selectedBank by remember { mutableStateOf<BankInfo?>(null) }
|
||||||
var loginName by remember { mutableStateOf("") }
|
var loginName by remember { mutableStateOf("") }
|
||||||
var password by remember { mutableStateOf("") }
|
var password by remember { mutableStateOf("") }
|
||||||
|
@ -39,11 +40,11 @@ fun AddAccountDialog(
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
fun confirmCalled() {
|
fun confirmCalled() {
|
||||||
selectedBank?.let {
|
selectedBank?.let { bank ->
|
||||||
isAddingAccount = true
|
isAddingAccount = true
|
||||||
|
|
||||||
coroutineScope.launch(Dispatchers.IOorDefault) {
|
coroutineScope.launch(Dispatchers.IOorDefault) {
|
||||||
val successful = DI.bankingService.addAccount(selectedBank!!, loginName, password)
|
val successful = DI.bankingService.addAccount(bank, loginName, password)
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
isAddingAccount = false
|
isAddingAccount = false
|
||||||
|
@ -71,8 +72,10 @@ fun AddAccountDialog(
|
||||||
Column {
|
Column {
|
||||||
|
|
||||||
AutocompleteTextField(
|
AutocompleteTextField(
|
||||||
onSelectedItemChanged = { selectedBank = it },
|
|
||||||
label = "Bank (Suche mit Name, Bankleitzahl oder Ort)",
|
label = "Bank (Suche mit Name, Bankleitzahl oder Ort)",
|
||||||
|
value = enteredBankSearchQuery,
|
||||||
|
onEnteredTextChanged = { enteredBankSearchQuery = it },
|
||||||
|
onSelectedItemChanged = { selectedBank = it },
|
||||||
getItemTitle = { bank -> bank.name },
|
getItemTitle = { bank -> bank.name },
|
||||||
fetchSuggestions = { query -> bankingService.findBanks(query) }
|
fetchSuggestions = { query -> bankingService.findBanks(query) }
|
||||||
) { bank ->
|
) { bank ->
|
||||||
|
|
|
@ -181,13 +181,29 @@ fun TransferMoneyDialog(
|
||||||
)
|
)
|
||||||
|
|
||||||
Row(Modifier.padding(vertical = verticalSpace).fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
Row(Modifier.padding(vertical = verticalSpace).fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
||||||
OutlinedTextField(
|
AutocompleteTextField(
|
||||||
value = amount,
|
"Betrag",
|
||||||
onValueChange = { amount = it },
|
amount,
|
||||||
label = { Text("Betrag") },
|
dropdownMaxHeight = 250.dp,
|
||||||
|
minTextLengthForSearch = 0,
|
||||||
modifier = Modifier.weight(1f).focusRequester(amountFocus),
|
modifier = Modifier.weight(1f).focusRequester(amountFocus),
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal, imeAction = ImeAction.Next)
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal, imeAction = ImeAction.Next),
|
||||||
)
|
getItemTitle = { suggestion -> suggestion.amount.amount },
|
||||||
|
onEnteredTextChanged = { amount = it },
|
||||||
|
onSelectedItemChanged = {
|
||||||
|
amount = it?.amount?.amount ?: ""
|
||||||
|
if (it != null) {
|
||||||
|
paymentReference = it.reference
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fetchSuggestions = { recipientFinder.findPaymentDataForIban(recipientAccountIdentifier) }
|
||||||
|
) { paymentDataSuggestion ->
|
||||||
|
Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Text(formatUtil.formatAmount(paymentDataSuggestion.amount, paymentDataSuggestion.currency), Modifier.widthIn(min = 60.dp), textAlign = TextAlign.End)
|
||||||
|
|
||||||
|
Text(paymentDataSuggestion.reference, Modifier.padding(start = 6.dp), maxLines = 1, overflow = TextOverflow.Ellipsis)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Text(formatUtil.formatCurrency(senderAccount.currency), Modifier.padding(start = 4.dp))
|
Text(formatUtil.formatCurrency(senderAccount.currency), Modifier.padding(start = 4.dp))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package net.codinux.banking.ui.forms
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material.*
|
import androidx.compose.material.*
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Close
|
import androidx.compose.material.icons.filled.Close
|
||||||
|
@ -19,18 +20,19 @@ import net.codinux.banking.ui.config.Colors
|
||||||
@Composable
|
@Composable
|
||||||
fun <T> AutocompleteTextField(
|
fun <T> AutocompleteTextField(
|
||||||
label: String,
|
label: String,
|
||||||
initialValue: String? = null,
|
value: String,
|
||||||
|
onEnteredTextChanged: (String) -> Unit,
|
||||||
onSelectedItemChanged: (T?) -> Unit,
|
onSelectedItemChanged: (T?) -> Unit,
|
||||||
onEnteredTextChanged: ((String) -> Unit)? = null,
|
|
||||||
minTextLengthForSearch: Int = 1,
|
minTextLengthForSearch: Int = 1,
|
||||||
showDividersBetweenItems: Boolean = true,
|
showDividersBetweenItems: Boolean = true,
|
||||||
getItemTitle: ((T) -> String)? = null,
|
getItemTitle: ((T) -> String)? = null,
|
||||||
dropdownMaxHeight: Dp = 400.dp,
|
dropdownMaxHeight: Dp = 400.dp,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||||
leadingIcon: @Composable (() -> Unit)? = null,
|
leadingIcon: @Composable (() -> Unit)? = null,
|
||||||
fetchSuggestions: suspend (query: String) -> Collection<T> = { emptyList() },
|
fetchSuggestions: suspend (query: String) -> Collection<T> = { emptyList() },
|
||||||
suggestionContent: @Composable (T) -> Unit
|
suggestionContent: @Composable (T) -> Unit
|
||||||
) {
|
) {
|
||||||
var searchQuery by remember { mutableStateOf(initialValue ?: "") }
|
|
||||||
var expanded by remember { mutableStateOf(false) }
|
var expanded by remember { mutableStateOf(false) }
|
||||||
var isLoading by remember { mutableStateOf(false) }
|
var isLoading by remember { mutableStateOf(false) }
|
||||||
var suggestions by remember { mutableStateOf<Collection<T>>(emptyList()) }
|
var suggestions by remember { mutableStateOf<Collection<T>>(emptyList()) }
|
||||||
|
@ -47,7 +49,7 @@ fun <T> AutocompleteTextField(
|
||||||
suggestionsFetchJob = coroutineScope.launch {
|
suggestionsFetchJob = coroutineScope.launch {
|
||||||
isLoading = true
|
isLoading = true
|
||||||
|
|
||||||
suggestions = fetchSuggestions(searchQuery)
|
suggestions = fetchSuggestions(value)
|
||||||
|
|
||||||
isLoading = false
|
isLoading = false
|
||||||
if (expanded == false && suggestions.isNotEmpty()) {
|
if (expanded == false && suggestions.isNotEmpty()) {
|
||||||
|
@ -57,13 +59,12 @@ fun <T> AutocompleteTextField(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ExposedDropdownMenuBox(expanded, { isExpanded -> expanded = isExpanded }, Modifier.fillMaxWidth()) {
|
ExposedDropdownMenuBox(expanded, { isExpanded -> expanded = isExpanded }, modifier.fillMaxWidth()) {
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = searchQuery,
|
value = value,
|
||||||
onValueChange = { query ->
|
onValueChange = { query ->
|
||||||
searchQuery = query
|
|
||||||
onSelectedItemChanged(null)
|
onSelectedItemChanged(null)
|
||||||
onEnteredTextChanged?.invoke(query)
|
onEnteredTextChanged(query)
|
||||||
|
|
||||||
if (query.length >= minTextLengthForSearch) {
|
if (query.length >= minTextLengthForSearch) {
|
||||||
fetchSuggestionsAsync()
|
fetchSuggestionsAsync()
|
||||||
|
@ -79,6 +80,7 @@ fun <T> AutocompleteTextField(
|
||||||
},
|
},
|
||||||
label = { Text(label) },
|
label = { Text(label) },
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
|
keyboardOptions = keyboardOptions,
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
|
@ -90,7 +92,7 @@ fun <T> AutocompleteTextField(
|
||||||
imageVector = Icons.Default.Close,
|
imageVector = Icons.Default.Close,
|
||||||
contentDescription = "Sucheingabe löschen",
|
contentDescription = "Sucheingabe löschen",
|
||||||
modifier = Modifier.clickable {
|
modifier = Modifier.clickable {
|
||||||
searchQuery = ""
|
onEnteredTextChanged("")
|
||||||
suggestions = emptyList()
|
suggestions = emptyList()
|
||||||
expanded = false
|
expanded = false
|
||||||
onSelectedItemChanged(null)
|
onSelectedItemChanged(null)
|
||||||
|
@ -114,9 +116,7 @@ fun <T> AutocompleteTextField(
|
||||||
Column(
|
Column(
|
||||||
Modifier.fillMaxWidth().padding(8.dp).clickable {
|
Modifier.fillMaxWidth().padding(8.dp).clickable {
|
||||||
onSelectedItemChanged(item)
|
onSelectedItemChanged(item)
|
||||||
getItemTitle?.let {
|
onEnteredTextChanged(getItemTitle?.invoke(item) ?: "")
|
||||||
searchQuery = it.invoke(item)
|
|
||||||
}
|
|
||||||
expanded = false
|
expanded = false
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
|
|
Loading…
Reference in New Issue