diff --git a/docs/images/graphs/dep_graph_feature_onboarding_language.svg b/docs/images/graphs/dep_graph_feature_onboarding_language.svg new file mode 100644 index 0000000000..ebbf760428 --- /dev/null +++ b/docs/images/graphs/dep_graph_feature_onboarding_language.svg @@ -0,0 +1,176 @@ + + + + +G + + + +:feature:onboarding-language + +:feature:onboarding-language + + + +:core:designsystem + +:core:designsystem + + + +:feature:onboarding-language->:core:designsystem + + + + + +:core:ui + +:core:ui + + + +:feature:onboarding-language->:core:ui + + + + + +:core:data + +:core:data + + + +:feature:onboarding-language->:core:data + + + + + +:core:model + +:core:model + + + +:feature:onboarding-language->:core:model + + + + + +:core:common + +:core:common + + + +:feature:onboarding-language->:core:common + + + + + +:core:ui->:core:designsystem + + + + + +:core:ui->:core:model + + + + + +:core:ui->:core:common + + + + + +:core:data->:core:model + + + + + +:core:data->:core:common + + + + + +:core:network + +:core:network + + + +:core:data->:core:network + + + + + +:core:database + +:core:database + + + +:core:data->:core:database + + + + + +:core:datastore + +:core:datastore + + + +:core:data->:core:datastore + + + + + +:core:model->:core:common + + + + + +:core:network->:core:model + + + + + +:core:network->:core:common + + + + + +:core:network->:core:datastore + + + + + +:core:datastore->:core:model + + + + + +:core:datastore->:core:common + + + + + diff --git a/feature/onboarding-language/README.md b/feature/onboarding-language/README.md new file mode 100644 index 0000000000..5c0cbda42d --- /dev/null +++ b/feature/onboarding-language/README.md @@ -0,0 +1,45 @@ +# Onboarding Language Module + +## Dependencies + +![Dependency Graph](../docs/images/graphs/dep_graph_feature_onboarding_language.svg) + +## Sequence Diagram + +```mermaid +sequenceDiagram + participant User + participant Screen as SetOnboardingLanguageScreen + participant ViewModel as SetOnboardingLanguageViewModel + participant Repository as UserPreferencesRepository + + User->>Screen: Selects language + Screen->>ViewModel: handleAction(SetLanguage(language)) + ViewModel->>Repository: setLanguage(language) + Repository-->>ViewModel: Language updated + ViewModel->>Screen: Update UI with new language + + Note over Screen,Repository: Language preference is now persisted +``` + +## Architecture + +```mermaid +graph TD + subgraph UI Layer + A[SetOnboardingLanguageScreen] -->|Observes| B[SetOnboardingLanguageViewModel] + end + + subgraph Domain Layer + B -->|Uses| C[UserPreferencesRepository] + end + + subgraph Data Layer + C -->|Manages| D[Language Preferences] + end + + style A fill:#e3f2fd,stroke:#1565c0 + style B fill:#e8f5e9,stroke:#2e7d32 + style C fill:#fff3e0,stroke:#f57c00 + style D fill:#f3e5f5,stroke:#7b1fa2 +``` diff --git a/feature/onboarding-language/src/commonMain/kotlin/org/mifos/mobile/feature/onboarding/language/SetOnboardingLanguageViewModel.kt b/feature/onboarding-language/src/commonMain/kotlin/org/mifos/mobile/feature/onboarding/language/SetOnboardingLanguageViewModel.kt index 55ab4afddb..5c34fd6ee7 100644 --- a/feature/onboarding-language/src/commonMain/kotlin/org/mifos/mobile/feature/onboarding/language/SetOnboardingLanguageViewModel.kt +++ b/feature/onboarding-language/src/commonMain/kotlin/org/mifos/mobile/feature/onboarding/language/SetOnboardingLanguageViewModel.kt @@ -19,6 +19,16 @@ import org.mifos.mobile.core.datastore.UserPreferencesRepository import org.mifos.mobile.core.model.LanguageConfig import org.mifos.mobile.core.ui.utils.BaseViewModel +/** + * ViewModel responsible for managing the onboarding language selection screen state and business logic. + * + * This ViewModel handles: + * - Loading the current language preference + * - Updating the selected language + * - Managing the onboarding flow state + * + * @property repository [UserPreferencesRepository] for accessing and modifying user preferences + */ internal class SetOnboardingLanguageViewModel( private val repository: UserPreferencesRepository, ) : BaseViewModel( @@ -31,6 +41,10 @@ internal class SetOnboardingLanguageViewModel( .launchIn(viewModelScope) } + /** + * Processes incoming actions and delegates to appropriate handlers. + * @param action The action to process + */ override fun handleAction(action: OnboardingLanguageAction) { when (action) { is OnboardingLanguageAction.Internal.LoadLanguage -> handleLoadLanguage(action) @@ -38,6 +52,24 @@ internal class SetOnboardingLanguageViewModel( } } + /** + * Updates the selected language and updates onboarding state. + * + * This method will: + * 1. Persist the new language preference + * 2. Update the UI state + * 3. Mark onboarding as complete + * + * @param action Contains the new language configuration + * + * Example: + * ```kotlin + * // When user selects a language + * viewModel.trySendAction( + * OnboardingLanguageAction.SetLanguage(selectedLanguage) + * ) + * ``` + */ private fun handleSetLanguage(action: OnboardingLanguageAction.SetLanguage) { viewModelScope.launch { repository.setLanguage(action.languageConfig) @@ -49,6 +81,23 @@ internal class SetOnboardingLanguageViewModel( } } + /** + * Updates the current language in the state. + * + * This is called internally when the language preference changes. + * + * @param action Contains the language to load + * + * Example: + * ```kotlin + * // Internal usage - triggered by language preference changes + * private fun onLanguagePreferenceChanged(newLanguage: LanguageConfig) { + * trySendAction( + * OnboardingLanguageAction.Internal.LoadLanguage(newLanguage) + * ) + * } + * ``` + */ private fun handleLoadLanguage(action: OnboardingLanguageAction.Internal.LoadLanguage) { mutableStateFlow.update { it.copy(currentLanguage = action.language) @@ -56,16 +105,38 @@ internal class SetOnboardingLanguageViewModel( } } +/** + * Represents the UI state for the language selection screen. + * @property currentLanguage The currently selected language + */ internal data class OnboardingLanguageState( val currentLanguage: LanguageConfig, ) +/** + * Events that can be triggered from the UI. + * Currently not used but available for future extensions. + */ internal sealed interface OnboardingLanguageEvent +/** + * Actions that can be processed by the ViewModel. + */ internal sealed interface OnboardingLanguageAction { + /** + * Action to set a new language. + * @property languageConfig The language configuration to set + */ data class SetLanguage(val languageConfig: LanguageConfig) : OnboardingLanguageAction + /** + * Internal actions used by the ViewModel for state management. + */ sealed interface Internal : OnboardingLanguageAction { + /** + * Action to load a language configuration. + * @property language The language configuration to load + */ data class LoadLanguage(val language: LanguageConfig) : Internal } }