Skip to content

Commit

Permalink
added DI
Browse files Browse the repository at this point in the history
  • Loading branch information
myofficework000 committed Mar 23, 2024
1 parent 7ab0281 commit 4321818
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,46 +19,67 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.jetpack_compose_all_in_one.demos.currency_converter.presentation.intent.CurrencyIntent
import com.example.jetpack_compose_all_in_one.demos.currency_converter.presentation.intent.CurrencyState
import com.example.jetpack_compose_all_in_one.demos.currency_converter.presentation.viewmodel.CurrencyViewModel

/**
* Composable function representing the Currency From-To screen.
* This function displays UI elements for entering the EUR amount and showing converted JPY amount.
*
* @param viewModel The [CurrencyViewModel] used to manage the UI logic and data.
*/
@Composable
fun CurrencyFromToScreen(viewModel: CurrencyViewModel = hiltViewModel()) {
// Observe the state from the view model
val state by viewModel.state

// Mutable state for the text entered by the user
var text by remember { mutableStateOf("") }

// Effect that launches when the text changes
LaunchedEffect(text) {
// Notify the view model about the user input change
viewModel.onUserInputChanged(text)
}

// Column composable to arrange UI elements vertically
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
// TextField for entering the EUR amount
TextField(
value = text,
onValueChange = {
text = it
// Notify the view model about the input change
viewModel.handleIntent(CurrencyIntent.CurrencyInputChanged(it))
},
placeholder = { Text("Enter EUR Amount") },
modifier = Modifier.fillMaxWidth()
)

// Spacer to add vertical space
Spacer(modifier = Modifier.height(16.dp))

when(state) {
// Display different UI based on the state
when (state) {
// Loading state: Show a progress indicator
is CurrencyState.Loading -> CircularProgressIndicator()
// Success state: Display converted amount
is CurrencyState.Success -> {
// Calculate and display the converted amount
val convertedAmount = viewModel.calculateConvertedAmount(text)
Text("Converted amount: ${String.format("%.2f JPY", convertedAmount)}")
}
// Error state: Display error message
is CurrencyState.Error -> Text(text = "Error: ${(state as CurrencyState.Error).error}")
// Idle state: Do nothing
else -> {}
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -18,59 +18,80 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import javax.inject.Inject

/**
* ViewModel responsible for managing the currency conversion logic and UI state.
*
* @param repository The repository used to fetch currency exchange rates.
*/
@HiltViewModel
class CurrencyViewModel @Inject constructor(private val repository: CurrencyRepository) : ViewModel() {
class CurrencyViewModel @Inject constructor(private val repository: CurrencyRepository) :
ViewModel() {

// Mutable state representing the current UI state
private val _state = mutableStateOf<CurrencyState>(CurrencyState.Idle)
val state: State<CurrencyState> = _state

// Mutable state flow to collect user input
private val userInputFlow = MutableStateFlow("")

// Mutable state for storing the conversion rate from EUR to JPY
private var jpyConversionRate by mutableStateOf<Double?>(null)

init {
// Start observing user input
observeUserInput()
}

// Function to observe user input flow
private fun observeUserInput() {
userInputFlow
.debounce(500)
.filter { it.isNotEmpty() }
.debounce(500) // Add debounce to reduce frequency of updates
.filter { it.isNotEmpty() } // Filter out empty input
.onEach { query ->
fetchCurrency(query)
fetchCurrency(query) // Fetch currency data based on user input
}
.launchIn(viewModelScope)
.launchIn(viewModelScope) // Launch the flow in the viewModelScope
}

// Function to fetch currency data based on user input
private fun fetchCurrency(query: String) {
viewModelScope.launch {
// Update UI state to indicate loading
_state.value = CurrencyState.Loading
// Fetch currency data from the repository
val result = repository.getEURToJPY()
// Update UI state based on the result
_state.value = if (result.isSuccess) {
// If successful, update conversion rate and set state to success
jpyConversionRate = result.getOrNull()?.jpy
CurrencyState.Success(result.getOrNull()!!)
} else {
// If failed, set state to error with appropriate message
CurrencyState.Error(result.exceptionOrNull()?.message ?: "Unknown Error")
}
}
}

// Function to handle user input change
fun onUserInputChanged(input: String) {
userInputFlow.value = input
userInputFlow.value = input // Update the value of userInputFlow
}

// Function to calculate converted amount
fun calculateConvertedAmount(input: String): Double {
val inputAmount = input.toDoubleOrNull() ?: return 0.0
val rate = jpyConversionRate ?: return 0.0
return inputAmount * rate
val inputAmount =
input.toDoubleOrNull() ?: return 0.0 // Convert input to double or return 0.0 if failed
val rate =
jpyConversionRate ?: return 0.0 // Get conversion rate, or return 0.0 if not available
return inputAmount * rate // Calculate and return converted amount
}

// Function to handle intents
fun handleIntent(intent: CurrencyIntent) {
when (intent) {
is CurrencyIntent.CurrencyInputChanged -> {
onUserInputChanged(intent.input)
onUserInputChanged(intent.input) // Handle currency input change
}
}

}
}
}

0 comments on commit 4321818

Please sign in to comment.