From fed18285af43b98238e08aaa3d70f93d4098432c Mon Sep 17 00:00:00 2001 From: dgomesdev Date: Fri, 29 Sep 2023 17:05:46 -0300 Subject: [PATCH] New version --- .idea/appInsightsSettings.xml | 45 ++++ .idea/deploymentTargetDropDown.xml | 10 + .idea/gradle.xml | 5 +- .idea/migrations.xml | 10 + app/build.gradle.kts | 4 +- app/src/main/AndroidManifest.xml | 1 - .../data/data/ExchangeRepository.kt | 2 +- .../data/data/ExchangeRepositoryImpl.kt | 4 +- .../domain/model/ExchangeValues.kt | 9 +- .../domain/useCases/CoinConversionUseCase.kt | 45 ++++ .../GetLastUpdatedValuesIfNoNetworkUseCase.kt | 25 +++ .../domain/useCases/GetTodayValuesUseCase.kt | 34 +++ .../presentation/ExchangeViewModel.kt | 76 +++++-- .../exchangeapp/presentation/MainActivity.kt | 32 ++- .../presentation/screens/ConversionScreen.kt | 95 ++++++++ .../presentation/screens/HistoryScreen.kt | 25 --- .../presentation/screens/MainScreen.kt | 210 ------------------ .../screens/TodayConversionScreen.kt | 52 +++++ .../exchangeapp/presentation/ui/CoinList.kt | 5 +- .../ui/composables/ConversionValue.kt | 37 +++ .../presentation/ui/composables/CoreScreen.kt | 86 ++++--- .../presentation/ui/composables/NavHost.kt | 44 ++-- .../ui/composables/ToBeConverted.kt | 109 +++++++++ .../presentation/ui/theme/Color.kt | 2 +- .../res/drawable/ic_launcher_foreground.xml | 6 +- app/src/main/res/values-fr/strings.xml | 13 +- app/src/main/res/values-pt/strings.xml | 13 +- app/src/main/res/values/strings.xml | 13 +- build.gradle.kts | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 30 files changed, 658 insertions(+), 358 deletions(-) create mode 100644 .idea/appInsightsSettings.xml create mode 100644 .idea/deploymentTargetDropDown.xml create mode 100644 .idea/migrations.xml create mode 100644 app/src/main/java/com/dgomesdev/exchangeapp/domain/useCases/CoinConversionUseCase.kt create mode 100644 app/src/main/java/com/dgomesdev/exchangeapp/domain/useCases/GetLastUpdatedValuesIfNoNetworkUseCase.kt create mode 100644 app/src/main/java/com/dgomesdev/exchangeapp/domain/useCases/GetTodayValuesUseCase.kt create mode 100644 app/src/main/java/com/dgomesdev/exchangeapp/presentation/screens/ConversionScreen.kt delete mode 100644 app/src/main/java/com/dgomesdev/exchangeapp/presentation/screens/HistoryScreen.kt delete mode 100644 app/src/main/java/com/dgomesdev/exchangeapp/presentation/screens/MainScreen.kt create mode 100644 app/src/main/java/com/dgomesdev/exchangeapp/presentation/screens/TodayConversionScreen.kt create mode 100644 app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/composables/ConversionValue.kt create mode 100644 app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/composables/ToBeConverted.kt diff --git a/.idea/appInsightsSettings.xml b/.idea/appInsightsSettings.xml new file mode 100644 index 0000000..f91f22e --- /dev/null +++ b/.idea/appInsightsSettings.xml @@ -0,0 +1,45 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..0c0c338 --- /dev/null +++ b/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index ae388c2..0897082 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -4,16 +4,15 @@ diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e3b52da..e0a2cd4 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -7,12 +7,12 @@ plugins { android { namespace = "com.dgomesdev.exchangeapp" - compileSdk = 33 + compileSdk = 34 defaultConfig { applicationId = "com.dgomesdev.exchangeapp" minSdk = 26 - targetSdk = 33 + targetSdk = 34 versionCode = 1 versionName = "1.0" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 41a30b6..adba1f4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,7 +18,6 @@ diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/data/data/ExchangeRepository.kt b/app/src/main/java/com/dgomesdev/exchangeapp/data/data/ExchangeRepository.kt index 4bf537d..405f978 100644 --- a/app/src/main/java/com/dgomesdev/exchangeapp/data/data/ExchangeRepository.kt +++ b/app/src/main/java/com/dgomesdev/exchangeapp/data/data/ExchangeRepository.kt @@ -9,5 +9,5 @@ interface ExchangeRepository { suspend fun save(exchangeValues: ExchangeValues) - fun list(): Flow> + fun getLastUpdatedValues(): Flow> } \ No newline at end of file diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/data/data/ExchangeRepositoryImpl.kt b/app/src/main/java/com/dgomesdev/exchangeapp/data/data/ExchangeRepositoryImpl.kt index 341e6bf..ffb39bc 100644 --- a/app/src/main/java/com/dgomesdev/exchangeapp/data/data/ExchangeRepositoryImpl.kt +++ b/app/src/main/java/com/dgomesdev/exchangeapp/data/data/ExchangeRepositoryImpl.kt @@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import javax.inject.Inject -class ExchangeRepositoryImpl @Inject constructor( +class ExchangeRepositoryImpl @Inject constructor( private val service: ExchangeService, private val exchangeDao: ExchangeDao ) : ExchangeRepository { @@ -19,5 +19,5 @@ class ExchangeRepositoryImpl @Inject constructor( exchangeDao.save(exchangeValues) } - override fun list(): Flow> = exchangeDao.getAll() + override fun getLastUpdatedValues(): Flow> = exchangeDao.getAll() } \ No newline at end of file diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/domain/model/ExchangeValues.kt b/app/src/main/java/com/dgomesdev/exchangeapp/domain/model/ExchangeValues.kt index 93f56e4..bdf73a3 100644 --- a/app/src/main/java/com/dgomesdev/exchangeapp/domain/model/ExchangeValues.kt +++ b/app/src/main/java/com/dgomesdev/exchangeapp/domain/model/ExchangeValues.kt @@ -2,16 +2,15 @@ package com.dgomesdev.exchangeapp.domain.model import androidx.room.Entity import androidx.room.PrimaryKey +import com.google.gson.annotations.SerializedName typealias ExchangeResponse = HashMap @Entity(tableName = "coin_table") data class ExchangeValues ( - @PrimaryKey(autoGenerate = true) - val id: Int, - val code: String, - val codein: String, + @PrimaryKey val name: String, val bid: Double, - val convertedAmount: Double + @SerializedName("create_date") + val createDate: String ) diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/domain/useCases/CoinConversionUseCase.kt b/app/src/main/java/com/dgomesdev/exchangeapp/domain/useCases/CoinConversionUseCase.kt new file mode 100644 index 0000000..019b222 --- /dev/null +++ b/app/src/main/java/com/dgomesdev/exchangeapp/domain/useCases/CoinConversionUseCase.kt @@ -0,0 +1,45 @@ +package com.dgomesdev.exchangeapp.domain.useCases + +import com.dgomesdev.exchangeapp.data.data.ExchangeRepositoryImpl +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flow +import javax.inject.Inject + +class CoinConversionUseCase @Inject constructor( + private val repository: ExchangeRepositoryImpl, +) { + + suspend operator fun invoke(coin: String) = execute(coin) + + private suspend fun execute(coin: String): Flow> = flow { + + val valuesList: MutableList = mutableListOf() + when (coin) { + "BRL" -> { + valuesList.add(1.0) + valuesList.add(repository.getExchangeValues("BRL-USD").first().bid) + valuesList.add(repository.getExchangeValues("BRL-EUR").first().bid) + } + + "USD" -> { + valuesList.add(repository.getExchangeValues("USD-BRL").first().bid) + valuesList.add(1.0) + valuesList.add(repository.getExchangeValues("USD-EUR").first().bid) + } + + "EUR" -> { + valuesList.add(repository.getExchangeValues("EUR-BRL").first().bid) + valuesList.add(repository.getExchangeValues("EUR-USD").first().bid) + valuesList.add(1.0) + } + + else -> { + valuesList.add(1.0) + valuesList.add(1.0) + valuesList.add(1.0) + } + } + emit(valuesList) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/domain/useCases/GetLastUpdatedValuesIfNoNetworkUseCase.kt b/app/src/main/java/com/dgomesdev/exchangeapp/domain/useCases/GetLastUpdatedValuesIfNoNetworkUseCase.kt new file mode 100644 index 0000000..dee5235 --- /dev/null +++ b/app/src/main/java/com/dgomesdev/exchangeapp/domain/useCases/GetLastUpdatedValuesIfNoNetworkUseCase.kt @@ -0,0 +1,25 @@ +package com.dgomesdev.exchangeapp.domain.useCases + +import com.dgomesdev.exchangeapp.data.data.ExchangeRepositoryImpl +import com.dgomesdev.exchangeapp.domain.model.ExchangeValues +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flow +import javax.inject.Inject + +class GetLastUpdatedValuesIfNoNetworkUseCase @Inject constructor( + private val repository: ExchangeRepositoryImpl +) { + + suspend operator fun invoke() = flow { + + val valuesList: List = repository.getLastUpdatedValues().first() + + val bidValuesList = mutableListOf() + + for (value in valuesList) { + bidValuesList.add(value.bid) + } + + emit (Pair(bidValuesList, valuesList.first().createDate)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/domain/useCases/GetTodayValuesUseCase.kt b/app/src/main/java/com/dgomesdev/exchangeapp/domain/useCases/GetTodayValuesUseCase.kt new file mode 100644 index 0000000..1d3d42b --- /dev/null +++ b/app/src/main/java/com/dgomesdev/exchangeapp/domain/useCases/GetTodayValuesUseCase.kt @@ -0,0 +1,34 @@ +package com.dgomesdev.exchangeapp.domain.useCases + +import android.util.Log +import com.dgomesdev.exchangeapp.data.data.ExchangeRepositoryImpl +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flow +import javax.inject.Inject + +class GetTodayValuesUseCase @Inject constructor( + private val repository: ExchangeRepositoryImpl, +) { + + suspend operator fun invoke() = flow { + + val valuesList = mutableListOf() + + val exchangeValuesList = listOf( + repository.getExchangeValues("USD-BRL").first(), + repository.getExchangeValues("EUR-BRL").first(), + repository.getExchangeValues("BRL-USD").first(), + repository.getExchangeValues("EUR-USD").first(), + repository.getExchangeValues("BRL-EUR").first(), + repository.getExchangeValues("USD-EUR").first() + ) + + for (exchangeValue in exchangeValuesList) { + try{ repository.save(exchangeValue) } + catch (error: Throwable) { Log.e("ROOM ERROR", error.message ?: "No error") } + finally { valuesList.add(exchangeValue.bid) } + } + + emit(Pair(valuesList, exchangeValuesList.first().createDate)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ExchangeViewModel.kt b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ExchangeViewModel.kt index 6a37cf8..29976a4 100644 --- a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ExchangeViewModel.kt +++ b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ExchangeViewModel.kt @@ -1,49 +1,81 @@ package com.dgomesdev.exchangeapp.presentation +import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.dgomesdev.exchangeapp.data.data.ExchangeRepositoryImpl -import com.dgomesdev.exchangeapp.domain.model.ExchangeValues +import com.dgomesdev.exchangeapp.domain.useCases.CoinConversionUseCase +import com.dgomesdev.exchangeapp.domain.useCases.GetLastUpdatedValuesIfNoNetworkUseCase +import com.dgomesdev.exchangeapp.domain.useCases.GetTodayValuesUseCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class ExchangeViewModel @Inject constructor( - private val exchangeRepository: ExchangeRepositoryImpl + private val coinConversionUseCase: CoinConversionUseCase, + private val getTodayValuesUseCase: GetTodayValuesUseCase, + private val getLastUpdatedValuesIfNoNetworkUseCase: GetLastUpdatedValuesIfNoNetworkUseCase, ) : ViewModel() { - private val _mainState = MutableStateFlow(null) - val mainState: StateFlow = _mainState + private val _conversionValuesList = MutableStateFlow(null) + val conversionValuesList: StateFlow = _conversionValuesList - private val _historyState = MutableStateFlow>(emptyList()) - val historyState: StateFlow> = _historyState + private val _todayValuesList = MutableStateFlow(listOf(0.0, 0.0, 0.0, 0.0, 0.0, 0.0)) + val todayValuesList: StateFlow> = _todayValuesList + + private val _lastUpdateDate = MutableStateFlow("") + val lastUpdateDate: StateFlow = _lastUpdateDate init { + getExchangeValues("USD") + getTodayValues() + } + + fun getExchangeValues(coin: String) { viewModelScope.launch { - exchangeRepository.list() - .collect{ - _historyState.value = it + coinConversionUseCase(coin) + .onStart { + _conversionValuesList.value = State.Loading + }.catch { + _conversionValuesList.value = State.Failure(it) + }.collect { + _conversionValuesList.value = State.Success(it) } } } - fun getExchangeValues(coins: String) = viewModelScope.launch { - exchangeRepository.getExchangeValues(coins) - .collect { - _mainState.value = it - } - } - - fun saveExchangeValues(exchangeValues: ExchangeValues, convertedAmount: Double) { + private fun getTodayValues() { viewModelScope.launch { - exchangeRepository.save(exchangeValues.copy(convertedAmount = convertedAmount)) - exchangeRepository.list() - .collect {valuesList -> - _historyState.value = valuesList + getTodayValuesUseCase() + .catch {firstError -> + Log.e("FIRST ERROR", firstError.message ?: "NO FIRST ERROR") + getLastUpdatedValuesIfNoNetworkUseCase() + .catch {secondError -> + Log.e("SECOND ERROR", secondError.message ?: "NO SECOND ERROR") + _todayValuesList.value = listOf(1.0, 1.0, 1.0, 1.0, 1.0, 1.0) + }.collect { + _todayValuesList.value = it.first + _lastUpdateDate.value = it.second + } + }.collect { + _todayValuesList.value = it.first + _lastUpdateDate.value = it.second } } } +} + +sealed class State { + object Loading : State() + data class Success( + val valuesList: List, + ) : State() + + data class Failure( + val error: Throwable, + ) : State() } \ No newline at end of file diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/MainActivity.kt b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/MainActivity.kt index 5428620..a60e367 100644 --- a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/MainActivity.kt +++ b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/MainActivity.kt @@ -9,6 +9,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier +import com.dgomesdev.exchangeapp.R import com.dgomesdev.exchangeapp.presentation.ui.composables.ExchangeApp import com.dgomesdev.exchangeapp.presentation.ui.theme.ExchangeAppTheme import dagger.hilt.android.AndroidEntryPoint @@ -20,19 +21,36 @@ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { - val mainState = viewModel.mainState.collectAsState().value - val historyState = viewModel.historyState.collectAsState().value + lateinit var valuesList: List + lateinit var statusMessage: String + val todayValues = viewModel.todayValuesList.collectAsState().value + val lastUpdateDate = viewModel.lastUpdateDate.collectAsState().value + when (val valuesListState = viewModel.conversionValuesList.collectAsState().value) { + is State.Success -> { + valuesList = valuesListState.valuesList + statusMessage = getString(R.string.success) + } + is State.Failure -> { + valuesList = listOf(0.0, 0.0, 0.0) + statusMessage = getString(R.string.error) + } + State.Loading -> { + valuesList = listOf(0.0, 0.0, 0.0) + statusMessage = getString(R.string.loading) + } + null -> {} + } ExchangeAppTheme { Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { ExchangeApp( - convertCoinsAction = viewModel::getExchangeValues, - saveExchangeValues = viewModel::saveExchangeValues, - exchangeValues = mainState, - bidValue = mainState?.bid ?: 1.0, - savedValues = historyState + convertedValues = valuesList, + todayValues = todayValues, + lastUpdateDate = lastUpdateDate, + onCoinConversion = viewModel::getExchangeValues, + statusMessage = statusMessage ) } } diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/screens/ConversionScreen.kt b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/screens/ConversionScreen.kt new file mode 100644 index 0000000..e04534d --- /dev/null +++ b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/screens/ConversionScreen.kt @@ -0,0 +1,95 @@ +package com.dgomesdev.exchangeapp.presentation.screens + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.dgomesdev.exchangeapp.R +import com.dgomesdev.exchangeapp.presentation.ui.composables.AmountToBeConverted +import com.dgomesdev.exchangeapp.presentation.ui.composables.CoinToBeConverted +import com.dgomesdev.exchangeapp.presentation.ui.composables.ConversionValue + +typealias OnCoinConversion = (String) -> Unit +typealias OnConversionButtonClick = () -> Unit + +@OptIn(ExperimentalComposeUiApi::class) +@Composable +fun ConversionScreen( + modifier: Modifier, + convertedValues: List, + onCoinConversion: OnCoinConversion, + onConversionButtonClick: OnConversionButtonClick, +) { + + var coinToBeConverted by rememberSaveable { + mutableStateOf("USD") + } + var amountToBeConverted by rememberSaveable { + mutableStateOf(1.0) + } + val keyBoard = LocalSoftwareKeyboardController.current + + Column(modifier, horizontalAlignment = Alignment.CenterHorizontally) { + AmountToBeConverted( + modifier = modifier, + amountToBeConverted = { amountToBeConverted = it }, + onCoinConversion = onCoinConversion, + onConversionButtonClick = onConversionButtonClick, + coinToBeConverted = coinToBeConverted + ) + CoinToBeConverted( + modifier = modifier, + convertedCoin = coinToBeConverted, + coinToBeConverted = { coinToBeConverted = it } + ) + Button( + onClick = { + onCoinConversion(coinToBeConverted); + onConversionButtonClick(); + keyBoard?.hide() + }, + modifier + ) { + Text(stringResource(R.string.convert), fontSize = 18.sp) + } + Text(stringResource(R.string.exchange_values), modifier, fontSize = 24.sp) + ConversionValue( + modifier = modifier, + value = convertedValues[0] * amountToBeConverted, + coin = "R\$" + ) + ConversionValue( + modifier = modifier, + value = convertedValues[1] * amountToBeConverted, + coin = "\$" + ) + ConversionValue( + modifier = modifier, + value = convertedValues[2] * amountToBeConverted, + coin = "€" + ) + } +} + +@Preview(showBackground = true) +@Composable +fun ConversionScreenPreview() { + ConversionScreen( + modifier = Modifier.padding(8.dp), + convertedValues = listOf(1.0, 1.0, 1.0), + onCoinConversion = {}, + {}) +} \ No newline at end of file diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/screens/HistoryScreen.kt b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/screens/HistoryScreen.kt deleted file mode 100644 index b8a9d76..0000000 --- a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/screens/HistoryScreen.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.dgomesdev.exchangeapp.presentation.screens - -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.dgomesdev.exchangeapp.domain.model.ExchangeValues -import java.text.DecimalFormat - -@Composable -fun HistoryScreen( - modifier: Modifier, - savedValues: List -) { - LazyColumn( - modifier = modifier - ) { - items(savedValues) { - Text("${DecimalFormat("#,#00.00").format(it.convertedAmount)} ${it.code} = ${DecimalFormat("#,#00.00").format(it.bid * it.convertedAmount)} ${it.codein}" , modifier.padding(top = 8.dp)) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/screens/MainScreen.kt b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/screens/MainScreen.kt deleted file mode 100644 index 7fed9e8..0000000 --- a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/screens/MainScreen.kt +++ /dev/null @@ -1,210 +0,0 @@ -package com.dgomesdev.exchangeapp.presentation.screens - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowDropDown -import androidx.compose.material.icons.filled.KeyboardArrowUp -import androidx.compose.material3.DropdownMenu -import androidx.compose.material3.DropdownMenuItem -import androidx.compose.material3.ElevatedButton -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.Text -import androidx.compose.material3.TextField -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.text.input.TextFieldValue -import androidx.compose.ui.unit.dp -import com.dgomesdev.exchangeapp.R -import com.dgomesdev.exchangeapp.domain.model.ExchangeValues -import com.dgomesdev.exchangeapp.presentation.ui.CoinList -import java.text.NumberFormat -import java.util.Locale - -typealias AmountToBeConverted = (Double) -> Unit -typealias ConvertCoinsAction = (String) -> Unit -typealias SaveExchangeValues = (ExchangeValues, Double) -> Unit - -@Composable -fun MainScreen( - modifier: Modifier, - convertCoinsAction: ConvertCoinsAction, - saveExchangeValues: SaveExchangeValues, - exchangeValues: ExchangeValues?, - bidValue: Double, -) { - var coinFrom by rememberSaveable { - mutableStateOf("EUR") - } - var coinTo by rememberSaveable { - mutableStateOf("USD") - } - var amount by rememberSaveable { - mutableStateOf(0.0) - } - var convertedAmount by rememberSaveable { - mutableStateOf(0.0) - } - val isConversionValid = coinFrom != coinTo - Column(modifier, horizontalAlignment = Alignment.CenterHorizontally) { - AmountTextField(modifier = modifier.fillMaxWidth(), amountToBeConverted = {amount = it}) - Row(modifier) { - CoinSelectionButton(coinToBeConverted = {coinFrom = it}, defaultCoin = coinFrom, isCoinFrom = true) - Spacer(modifier = modifier.padding(horizontal = 24.dp)) - CoinSelectionButton(coinToBeConverted = {coinTo = it}, defaultCoin = coinTo, isCoinFrom = false) - } - if (!isConversionValid) AlertText(modifier = modifier) - ConvertButton( - modifier = modifier, - convertCoinsAction = convertCoinsAction, - coinsToBeConverted = "$coinFrom-$coinTo", - isEnabled = isConversionValid, - convertedAmount = amount * bidValue, - returnConvertedAmount = { convertedAmount = it } - ) - SaveButton( - modifier = modifier, - saveExchangeValues = saveExchangeValues, - exchangeValues = exchangeValues, - isEnabled = isConversionValid, - convertedAmount = convertedAmount - ) - ExchangeText( - modifier = modifier, - exchangeValue = convertedAmount, - coinFormat = coinTo - ) - } -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun AmountTextField( - modifier: Modifier, - amountToBeConverted: AmountToBeConverted -) { - var amount by rememberSaveable(stateSaver = TextFieldValue.Saver) { - mutableStateOf(TextFieldValue("")) - } - TextField( - value = amount, - onValueChange = { amount = it ; amountToBeConverted(it.text.toDoubleOrNull() ?: 0.0) }, - label = { Text(stringResource(R.string.amount_to_be_converted)) }, - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal), - modifier = modifier - .fillMaxWidth() - ) -} - -@Composable -fun CoinSelectionButton( - coinToBeConverted: (String) -> Unit, - defaultCoin: String, - isCoinFrom: Boolean -) { - var selectedCoin by rememberSaveable { - mutableStateOf(defaultCoin) - } - var expandedMenu by remember { - mutableStateOf(false) - } - Column { - Text(if (isCoinFrom) stringResource(R.string.from) else (stringResource(R.string.to))) - OutlinedButton( - onClick = { expandedMenu = true } - ) { - Text(selectedCoin) - Icon( - imageVector = if (!expandedMenu) - Icons.Default.ArrowDropDown else Icons.Default.KeyboardArrowUp, - contentDescription = "Coin selection" - ) - } - DropdownMenu( - expanded = expandedMenu, - onDismissRequest = { expandedMenu = false } - ) { - for (coin in CoinList.coinList) { - DropdownMenuItem( - text = { Text(coin) }, - onClick = { coinToBeConverted(coin); selectedCoin = coin } - ) - } - } - } -} - -@Composable -fun AlertText(modifier: Modifier) { - Text( - stringResource(R.string.a_coin_can_t_be_converted_to_itself), - color = Color.Red, - modifier = modifier - ) -} - -@Composable -fun ConvertButton( - modifier: Modifier, - convertCoinsAction: ConvertCoinsAction, - coinsToBeConverted: String, - isEnabled: Boolean, - convertedAmount: Double, - returnConvertedAmount: (Double) -> Unit -) { - ElevatedButton( - onClick = { convertCoinsAction(coinsToBeConverted) ; returnConvertedAmount(convertedAmount) }, - enabled = isEnabled, - modifier = modifier - ) { - Text(stringResource(R.string.convert)) - } -} - -@Composable -fun SaveButton( - modifier: Modifier, - saveExchangeValues: SaveExchangeValues, - exchangeValues: ExchangeValues?, - isEnabled: Boolean, - convertedAmount: Double -) { - ElevatedButton( - onClick = { saveExchangeValues(exchangeValues!!, convertedAmount) }, - enabled = if (exchangeValues == null) false else isEnabled, - modifier = modifier - ) { - Text(stringResource(R.string.save)) - } -} - -@Composable -fun ExchangeText( - modifier: Modifier, - exchangeValue: Double, - coinFormat: String -) { - val formattedAmount = when (coinFormat) { - "EUR" -> NumberFormat.getCurrencyInstance(Locale.FRANCE).format(exchangeValue) - "BRL" -> NumberFormat.getCurrencyInstance(Locale("pt", "BR")).format(exchangeValue) - "GBP" -> NumberFormat.getCurrencyInstance(Locale.UK).format(exchangeValue) - else -> NumberFormat.getCurrencyInstance(Locale.US).format(exchangeValue) - } - - Text(formattedAmount, modifier = modifier) -} \ No newline at end of file diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/screens/TodayConversionScreen.kt b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/screens/TodayConversionScreen.kt new file mode 100644 index 0000000..1207038 --- /dev/null +++ b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/screens/TodayConversionScreen.kt @@ -0,0 +1,52 @@ +package com.dgomesdev.exchangeapp.presentation.screens + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.sp +import com.dgomesdev.exchangeapp.R +import com.dgomesdev.exchangeapp.presentation.ui.composables.ConversionValue + +@Composable +fun TodayConversionScreen( + modifier: Modifier, + valuesList: List, + lastUpdateDate: String +) { + + Column(modifier.fillMaxWidth(), Arrangement.Center, Alignment.CenterHorizontally) { + Text(stringResource(R.string.last_update_values), modifier, fontSize = 20.sp) + Row(modifier, Arrangement.Center, Alignment.CenterVertically) { + Text("1 \$ = ", fontSize = 20.sp) + ConversionValue(value = valuesList[0], coin = "R\$") + } + Row(modifier, Arrangement.Center, Alignment.CenterVertically) { + Text("1 € = ", fontSize = 20.sp) + ConversionValue(value = valuesList[1], coin = "R\$") + } + Row(modifier, Arrangement.Center, Alignment.CenterVertically) { + Text("1 R\$ = ", fontSize = 20.sp) + ConversionValue(value = valuesList[2], coin = "\$") + } + Row(modifier, Arrangement.Center, Alignment.CenterVertically) { + Text("1 € = ", fontSize = 20.sp) + ConversionValue(value = valuesList[3], coin = "\$") + } + Row(modifier, Arrangement.Center, Alignment.CenterVertically) { + Text("1 R\$ = ", fontSize = 20.sp) + ConversionValue(value = valuesList[4], coin = "€") + } + Row(modifier, Arrangement.Center, Alignment.CenterVertically) { + Text("1 \$ = ", fontSize = 20.sp) + ConversionValue(value = valuesList[5], coin = "€") + } + Text("${stringResource(R.string.last_update_at)} $lastUpdateDate", modifier, fontSize = 20.sp, textAlign = TextAlign.Center) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/CoinList.kt b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/CoinList.kt index 7f97902..3e8ffa4 100644 --- a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/CoinList.kt +++ b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/CoinList.kt @@ -3,9 +3,8 @@ package com.dgomesdev.exchangeapp.presentation.ui object CoinList { val coinList = listOf( - "EUR", - "USD", "BRL", - "GBP" + "USD", + "EUR" ) } \ No newline at end of file diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/composables/ConversionValue.kt b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/composables/ConversionValue.kt new file mode 100644 index 0000000..795a2d1 --- /dev/null +++ b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/composables/ConversionValue.kt @@ -0,0 +1,37 @@ +package com.dgomesdev.exchangeapp.presentation.ui.composables + +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import java.text.DecimalFormat + +@Composable +fun ConversionValue( + modifier: Modifier = Modifier, + value: Double, + coin: String +) { + + Row(modifier, verticalAlignment = Alignment.CenterVertically) { + Text(text = "${value.formatNumber()} $coin", modifier, fontSize = 20.sp) + } +} + +@Preview(showBackground = true) +@Composable +fun ConversionValuePreview() { + + ConversionValue( + Modifier.padding(8.dp), + 10.00000, + "USD" + ) +} + +fun Double.formatNumber(): String = DecimalFormat("#,##0.00").format(this) \ No newline at end of file diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/composables/CoreScreen.kt b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/composables/CoreScreen.kt index 7db8ceb..2803b9e 100644 --- a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/composables/CoreScreen.kt +++ b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/composables/CoreScreen.kt @@ -3,57 +3,70 @@ package com.dgomesdev.exchangeapp.presentation.ui.composables import android.widget.Toast import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.DateRange import androidx.compose.material.icons.filled.Home import androidx.compose.material.icons.filled.Info import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarDuration +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp import androidx.navigation.compose.rememberNavController import com.dgomesdev.exchangeapp.R -import com.dgomesdev.exchangeapp.domain.model.ExchangeValues -import com.dgomesdev.exchangeapp.presentation.screens.ConvertCoinsAction -import com.dgomesdev.exchangeapp.presentation.screens.SaveExchangeValues +import com.dgomesdev.exchangeapp.presentation.screens.OnCoinConversion import com.dgomesdev.exchangeapp.presentation.ui.theme.barColor +import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class) @Composable fun ExchangeApp( - convertCoinsAction: ConvertCoinsAction, - saveExchangeValues: SaveExchangeValues, - exchangeValues: ExchangeValues?, - bidValue: Double, - savedValues: List + convertedValues: List, + todayValues: List, + lastUpdateDate: String, + onCoinConversion: OnCoinConversion, + statusMessage: String, ) { val navController = rememberNavController() + val scope = rememberCoroutineScope() + val snackbarHostState = remember { SnackbarHostState() } Scaffold( topBar = { ExchangeTopBar() }, - bottomBar = { ExchangeBottomBar { navController.navigate(it) } } + bottomBar = { ExchangeBottomBar { navController.navigate(it) } }, + snackbarHost = { SnackbarHost(hostState = snackbarHostState) } ) { ExchangeNavHost( navController = navController, modifier = Modifier.padding(it), - convertCoinsAction = convertCoinsAction, - saveExchangeValues = saveExchangeValues, - exchangeValues = exchangeValues, - bidValue = bidValue, - savedValues = savedValues + convertedValues = convertedValues, + todayValues = todayValues, + lastUpdateDate = lastUpdateDate, + onCoinConversion = onCoinConversion, + onConversionButtonClick = { + scope.launch { + snackbarHostState.showSnackbar( + statusMessage, + duration = SnackbarDuration.Short + ) + } + } ) } } @@ -63,7 +76,7 @@ fun ExchangeApp( fun ExchangeTopBar() { val context = LocalContext.current TopAppBar( - title = { Text(stringResource(R.string.exchange_app)) }, + title = { Text(stringResource(R.string.app_name), color = Color.Black) }, actions = { IconButton(onClick = { Toast.makeText( @@ -74,7 +87,8 @@ fun ExchangeTopBar() { }) { Icon( imageVector = Icons.Filled.Info, - contentDescription = "Developed by Dgomes Dev" + contentDescription = "Developed by Dgomes Dev", + tint = Color.Black ) } }, @@ -84,27 +98,37 @@ fun ExchangeTopBar() { @Composable fun ExchangeBottomBar( - navigateToScreen: (String) -> Unit + navigateToScreen: (String) -> Unit, ) { var currentScreen by rememberSaveable { mutableStateOf(0) } - val screens = listOf("Main screen", "History screen") - NavigationBar ( + val screens = listOf("Conversion screen", "Today's values screen") + NavigationBar( containerColor = barColor - ){ + ) { screens.forEachIndexed { index, screen -> NavigationBarItem( selected = currentScreen == index, - onClick = { navigateToScreen(screen) ; currentScreen = index }, + onClick = { navigateToScreen(screen); currentScreen = index }, icon = { - if (index == 0) Icon(imageVector = Icons.Default.Home, contentDescription = "Main screen") - else Icon(painter = painterResource(R.drawable.ic_history), contentDescription = "History") - }, - label = {Text( - if (index == 0) stringResource(R.string.main_screen) - else stringResource(R.string.history) - ) + if (index == 0) Icon( + imageVector = Icons.Default.Home, + contentDescription = "Main screen", + tint = Color.Black + ) + else Icon( + imageVector = Icons.Default.DateRange, + contentDescription = "Today's conversion values", + tint = Color.Black + ) + }, + label = { + Text( + if (index == 0) stringResource(R.string.main_screen) + else stringResource(R.string.history), + color = Color.Black + ) } ) } diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/composables/NavHost.kt b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/composables/NavHost.kt index eb4c9a3..5c040bc 100644 --- a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/composables/NavHost.kt +++ b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/composables/NavHost.kt @@ -7,44 +7,44 @@ import androidx.compose.ui.unit.dp import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable -import com.dgomesdev.exchangeapp.domain.model.ExchangeValues -import com.dgomesdev.exchangeapp.presentation.screens.ConvertCoinsAction -import com.dgomesdev.exchangeapp.presentation.screens.HistoryScreen -import com.dgomesdev.exchangeapp.presentation.screens.MainScreen -import com.dgomesdev.exchangeapp.presentation.screens.SaveExchangeValues +import com.dgomesdev.exchangeapp.presentation.screens.ConversionScreen +import com.dgomesdev.exchangeapp.presentation.screens.OnCoinConversion +import com.dgomesdev.exchangeapp.presentation.screens.OnConversionButtonClick +import com.dgomesdev.exchangeapp.presentation.screens.TodayConversionScreen @Composable fun ExchangeNavHost( navController: NavHostController, modifier: Modifier, - convertCoinsAction: ConvertCoinsAction, - saveExchangeValues: SaveExchangeValues, - exchangeValues: ExchangeValues?, - bidValue: Double, - savedValues: List + convertedValues: List, + todayValues: List, + lastUpdateDate: String, + onCoinConversion: OnCoinConversion, + onConversionButtonClick: OnConversionButtonClick ) { + val padding = Modifier.padding(8.dp) NavHost( navController = navController, - startDestination = "Main screen", + startDestination = "Conversion screen", modifier = modifier ) { composable( - route = "Main screen" + route = "Conversion screen" ) { - MainScreen( - modifier = Modifier.padding(16.dp), - convertCoinsAction = convertCoinsAction, - saveExchangeValues = saveExchangeValues, - exchangeValues = exchangeValues, - bidValue = bidValue + ConversionScreen( + modifier = padding, + convertedValues = convertedValues, + onCoinConversion = onCoinConversion, + onConversionButtonClick = onConversionButtonClick ) } composable( - route = "History screen" + route = "Today's values screen" ) { - HistoryScreen( - modifier = Modifier.padding(16.dp), - savedValues = savedValues + TodayConversionScreen( + modifier = padding, + valuesList = todayValues, + lastUpdateDate = lastUpdateDate ) } } diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/composables/ToBeConverted.kt b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/composables/ToBeConverted.kt new file mode 100644 index 0000000..6e178b8 --- /dev/null +++ b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/composables/ToBeConverted.kt @@ -0,0 +1,109 @@ +package com.dgomesdev.exchangeapp.presentation.ui.composables + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowDropDown +import androidx.compose.material.icons.filled.KeyboardArrowUp +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.unit.sp +import com.dgomesdev.exchangeapp.R +import com.dgomesdev.exchangeapp.presentation.screens.OnCoinConversion +import com.dgomesdev.exchangeapp.presentation.screens.OnConversionButtonClick +import com.dgomesdev.exchangeapp.presentation.ui.CoinList + +@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class) +@Composable +fun AmountToBeConverted( + modifier: Modifier, + amountToBeConverted: (Double) -> Unit, + onCoinConversion: OnCoinConversion, + onConversionButtonClick: OnConversionButtonClick, + coinToBeConverted: String +) { + + var amount by rememberSaveable(stateSaver = TextFieldValue.Saver) { + mutableStateOf(TextFieldValue("")) + } + + val keyBoard = LocalSoftwareKeyboardController.current + + TextField( + value = amount, + onValueChange = { amount = it ; amountToBeConverted(it.text.toDoubleOrNull() ?: 1.0) }, + modifier = modifier.fillMaxWidth(), + label = { Text(stringResource(R.string.amount_to_be_converted)) }, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Decimal, + imeAction = ImeAction.Go + ), + keyboardActions = KeyboardActions( + onGo = { keyBoard?.hide() ; onCoinConversion(coinToBeConverted) ; onConversionButtonClick()} + ) + ) +} + +@Composable +fun CoinToBeConverted( + modifier: Modifier, + convertedCoin: String, + coinToBeConverted: (String) -> Unit +) { + + var selectedCoin by rememberSaveable { + mutableStateOf(convertedCoin) + } + + var expandedMenu by remember { + mutableStateOf(false) + } + + Column(modifier) { + OutlinedButton( + onClick = { expandedMenu = true } + ) { + Text(selectedCoin, fontSize = 20.sp) + Icon( + imageVector = if (!expandedMenu) + Icons.Default.ArrowDropDown else Icons.Default.KeyboardArrowUp, + contentDescription = "Coin selection button" + ) + } + DropdownMenu( + expanded = expandedMenu, + onDismissRequest = { expandedMenu = false } + ) { + for (coin in CoinList.coinList) { + if (coin != selectedCoin) { + DropdownMenuItem( + text = { Text(coin) }, + onClick = { + coinToBeConverted(coin); selectedCoin = coin; expandedMenu = false + } + ) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/theme/Color.kt b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/theme/Color.kt index 9413e7d..e2f73b4 100644 --- a/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/theme/Color.kt +++ b/app/src/main/java/com/dgomesdev/exchangeapp/presentation/ui/theme/Color.kt @@ -10,4 +10,4 @@ val Purple40 = Color(0xFF6650a4) val PurpleGrey40 = Color(0xFF625b71) val Pink40 = Color(0xFF7D5260) -val barColor = Color(0xFF32C83C) \ No newline at end of file +val barColor = Color(0xFF3DDC84) \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml index 47e09f7..ed8d630 100644 --- a/app/src/main/res/drawable/ic_launcher_foreground.xml +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -3,11 +3,11 @@ android:height="108dp" android:viewportWidth="24" android:viewportHeight="24" - android:tint="#23D972"> + android:tint="#3DDC84"> + android:translateX="2.5" + android:translateY="2.5"> diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 2512422..6541885 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -2,12 +2,13 @@ Conversion de devises Ecran principal - Historique - Conversion de devises + Valeurs d\'ajourd\'hui Montant à convertir - De - Vers - La monnaie ne peut pas être convertie vers elle même Convertir - Sauvegarder + Valeurs de conversion + Dernières valeurs mises à jour + Dernière mise à jour: + Succès + Erreur de chargement + Chargement \ No newline at end of file diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 779137a..65695d6 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -2,12 +2,13 @@ Conversão de moedas Tela principal - Histórico - Conversão de moedas + Valores de hoje Valor a ser convertido - De - Para - A moeda não pode ser convertida para ela mesma Converter - Salvar + Valores de conversão + Últimos valores atualizados + Data da última atualização: + Sucesso + Erro de carregamento dos dados + Carregando \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1916fa5..01daeef 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,12 +1,13 @@ Exchange App Main screen - History - Exchange App + Today\'s values Amount to be converted - From - To - A currency can\'t be converted to itself Convert - Save + Exchange values + Last updated exchange values + Last update at: + Success + Error while loading the data + Loading \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index a409d1d..03da34c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,6 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id("com.android.application") version "8.1.0-rc01" apply false + id("com.android.application") version "8.1.1" apply false id("org.jetbrains.kotlin.android") version "1.8.10" apply false id("com.google.dagger.hilt.android") version "2.46.1" apply false } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 06aa911..405d8f5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Fri Jun 23 20:15:44 BRT 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists