From 4e5f3682567ea429f2c5730d4cbf41e91875fc34 Mon Sep 17 00:00:00 2001 From: androidlover5842 Date: Tue, 3 Feb 2026 09:38:30 +0530 Subject: [PATCH] AI:remove more boilerplate --- .../core/viewmodel/ViewModelRequest.kt | 31 +++++++++++++++++ .../ui/room/RoomFormViewModel.kt | 27 ++++++--------- .../ui/roomimage/AddImageTagScreen.kt | 19 +++-------- .../ui/roomimage/EditImageTagScreen.kt | 19 +++-------- .../ui/roomimage/ImageTagEditorScreen.kt | 31 +++++++++++++++++ .../ui/roomimage/ImageTagFormViewModel.kt | 33 ++++++++----------- .../ui/roomtype/AmenityFormViewModel.kt | 24 ++++++-------- .../ui/roomtype/RoomTypeFormViewModel.kt | 27 ++++++--------- 8 files changed, 115 insertions(+), 96 deletions(-) create mode 100644 app/src/main/java/com/android/trisolarispms/ui/roomimage/ImageTagEditorScreen.kt diff --git a/app/src/main/java/com/android/trisolarispms/core/viewmodel/ViewModelRequest.kt b/app/src/main/java/com/android/trisolarispms/core/viewmodel/ViewModelRequest.kt index f8fb0e4..df98919 100644 --- a/app/src/main/java/com/android/trisolarispms/core/viewmodel/ViewModelRequest.kt +++ b/app/src/main/java/com/android/trisolarispms/core/viewmodel/ViewModelRequest.kt @@ -2,9 +2,12 @@ package com.android.trisolarispms.core.viewmodel import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.android.trisolarispms.data.api.core.ApiClient +import com.android.trisolarispms.data.api.core.ApiService import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import retrofit2.Response internal fun ViewModel.launchRequest( state: MutableStateFlow, @@ -23,3 +26,31 @@ internal fun ViewModel.launchRequest( } } } + +internal fun ViewModel.launchApiMutation( + state: MutableStateFlow, + action: String, + setLoading: (S) -> S, + setSuccess: (S) -> S, + setError: (S, String) -> S, + onDone: () -> Unit = {}, + createApi: () -> ApiService = { ApiClient.create() }, + call: suspend (ApiService) -> Response<*> +) { + launchRequest( + state = state, + setLoading = setLoading, + setError = setError, + defaultError = "$action failed" + ) { + val response = call(createApi()) + if (response.isSuccessful) { + state.update(setSuccess) + onDone() + } else { + state.update { current -> + setError(current, "$action failed: ${response.code()}") + } + } + } +} diff --git a/app/src/main/java/com/android/trisolarispms/ui/room/RoomFormViewModel.kt b/app/src/main/java/com/android/trisolarispms/ui/room/RoomFormViewModel.kt index 3522652..421032d 100644 --- a/app/src/main/java/com/android/trisolarispms/ui/room/RoomFormViewModel.kt +++ b/app/src/main/java/com/android/trisolarispms/ui/room/RoomFormViewModel.kt @@ -1,15 +1,13 @@ package com.android.trisolarispms.ui.room import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.android.trisolarispms.data.api.core.ApiClient +import com.android.trisolarispms.core.viewmodel.launchApiMutation import com.android.trisolarispms.data.api.core.ApiService import com.android.trisolarispms.data.api.model.RoomCreateRequest import com.android.trisolarispms.data.api.model.RoomUpdateRequest import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch import retrofit2.Response class RoomFormViewModel : ViewModel() { @@ -146,19 +144,14 @@ class RoomFormViewModel : ViewModel() { onDone: () -> Unit, call: suspend (ApiService) -> Response<*> ) { - viewModelScope.launch { - _state.update { it.copy(isLoading = true, error = null) } - try { - val response = call(ApiClient.create()) - if (response.isSuccessful) { - _state.update { it.copy(isLoading = false, success = true) } - onDone() - } else { - _state.update { it.copy(isLoading = false, error = "$action failed: ${response.code()}") } - } - } catch (e: Exception) { - _state.update { it.copy(isLoading = false, error = e.localizedMessage ?: "$action failed") } - } - } + launchApiMutation( + state = _state, + action = action, + setLoading = { it.copy(isLoading = true, error = null) }, + setSuccess = { it.copy(isLoading = false, success = true) }, + setError = { current, message -> current.copy(isLoading = false, error = message) }, + onDone = onDone, + call = call + ) } } diff --git a/app/src/main/java/com/android/trisolarispms/ui/roomimage/AddImageTagScreen.kt b/app/src/main/java/com/android/trisolarispms/ui/roomimage/AddImageTagScreen.kt index 7289c03..3f737e9 100644 --- a/app/src/main/java/com/android/trisolarispms/ui/roomimage/AddImageTagScreen.kt +++ b/app/src/main/java/com/android/trisolarispms/ui/roomimage/AddImageTagScreen.kt @@ -1,9 +1,6 @@ package com.android.trisolarispms.ui.roomimage import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue import androidx.lifecycle.viewmodel.compose.viewModel @Composable @@ -12,18 +9,12 @@ fun AddImageTagScreen( onSave: () -> Unit, viewModel: ImageTagFormViewModel = viewModel() ) { - val state by viewModel.state.collectAsState() - - LaunchedEffect(Unit) { - viewModel.reset() - } - - ImageTagFormScreen( + ImageTagEditorScreen( title = "Add Tag", - name = state.name, - error = state.error, - onNameChange = viewModel::onNameChange, + setupKey = Unit, onBack = onBack, - onSave = { viewModel.submitCreate(onSave) } + onSaveClick = { viewModel.submitCreate(onSave) }, + setupForm = { viewModel.reset() }, + viewModel = viewModel ) } diff --git a/app/src/main/java/com/android/trisolarispms/ui/roomimage/EditImageTagScreen.kt b/app/src/main/java/com/android/trisolarispms/ui/roomimage/EditImageTagScreen.kt index fa6311c..e382344 100644 --- a/app/src/main/java/com/android/trisolarispms/ui/roomimage/EditImageTagScreen.kt +++ b/app/src/main/java/com/android/trisolarispms/ui/roomimage/EditImageTagScreen.kt @@ -1,9 +1,6 @@ package com.android.trisolarispms.ui.roomimage import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue import androidx.lifecycle.viewmodel.compose.viewModel import com.android.trisolarispms.data.api.model.RoomImageTagDto @@ -14,18 +11,12 @@ fun EditImageTagScreen( onSave: () -> Unit, viewModel: ImageTagFormViewModel = viewModel() ) { - val state by viewModel.state.collectAsState() - - LaunchedEffect(tag.id) { - viewModel.setTag(tag) - } - - ImageTagFormScreen( + ImageTagEditorScreen( title = "Edit Tag", - name = state.name, - error = state.error, - onNameChange = viewModel::onNameChange, + setupKey = tag.id, onBack = onBack, - onSave = { viewModel.submitUpdate(tag.id.orEmpty(), onSave) } + onSaveClick = { viewModel.submitUpdate(tag.id.orEmpty(), onSave) }, + setupForm = { viewModel.setTag(tag) }, + viewModel = viewModel ) } diff --git a/app/src/main/java/com/android/trisolarispms/ui/roomimage/ImageTagEditorScreen.kt b/app/src/main/java/com/android/trisolarispms/ui/roomimage/ImageTagEditorScreen.kt new file mode 100644 index 0000000..421bead --- /dev/null +++ b/app/src/main/java/com/android/trisolarispms/ui/roomimage/ImageTagEditorScreen.kt @@ -0,0 +1,31 @@ +package com.android.trisolarispms.ui.roomimage + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue + +@Composable +internal fun ImageTagEditorScreen( + title: String, + setupKey: Any?, + onBack: () -> Unit, + onSaveClick: () -> Unit, + setupForm: () -> Unit, + viewModel: ImageTagFormViewModel +) { + val state by viewModel.state.collectAsState() + + LaunchedEffect(setupKey) { + setupForm() + } + + ImageTagFormScreen( + title = title, + name = state.name, + error = state.error, + onNameChange = viewModel::onNameChange, + onBack = onBack, + onSave = onSaveClick + ) +} diff --git a/app/src/main/java/com/android/trisolarispms/ui/roomimage/ImageTagFormViewModel.kt b/app/src/main/java/com/android/trisolarispms/ui/roomimage/ImageTagFormViewModel.kt index 0c56d0e..d646009 100644 --- a/app/src/main/java/com/android/trisolarispms/ui/roomimage/ImageTagFormViewModel.kt +++ b/app/src/main/java/com/android/trisolarispms/ui/roomimage/ImageTagFormViewModel.kt @@ -1,14 +1,12 @@ package com.android.trisolarispms.ui.roomimage import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.android.trisolarispms.data.api.core.ApiClient +import com.android.trisolarispms.core.viewmodel.launchApiMutation import com.android.trisolarispms.data.api.core.ApiService import com.android.trisolarispms.data.api.model.RoomImageTagDto import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch import retrofit2.Response class ImageTagFormViewModel : ViewModel() { @@ -64,22 +62,17 @@ class ImageTagFormViewModel : ViewModel() { resetOnSuccess: Boolean, call: suspend (ApiService) -> Response<*> ) { - viewModelScope.launch { - _state.update { it.copy(isLoading = true, error = null) } - try { - val response = call(ApiClient.create()) - if (response.isSuccessful) { - _state.update { - if (resetOnSuccess) ImageTagFormState(success = true) - else it.copy(isLoading = false, success = true) - } - onDone() - } else { - _state.update { it.copy(isLoading = false, error = "$action failed: ${response.code()}") } - } - } catch (e: Exception) { - _state.update { it.copy(isLoading = false, error = e.localizedMessage ?: "$action failed") } - } - } + launchApiMutation( + state = _state, + action = action, + setLoading = { it.copy(isLoading = true, error = null) }, + setSuccess = { + if (resetOnSuccess) ImageTagFormState(success = true) + else it.copy(isLoading = false, success = true) + }, + setError = { current, message -> current.copy(isLoading = false, error = message) }, + onDone = onDone, + call = call + ) } } diff --git a/app/src/main/java/com/android/trisolarispms/ui/roomtype/AmenityFormViewModel.kt b/app/src/main/java/com/android/trisolarispms/ui/roomtype/AmenityFormViewModel.kt index af4ec91..ff2f036 100644 --- a/app/src/main/java/com/android/trisolarispms/ui/roomtype/AmenityFormViewModel.kt +++ b/app/src/main/java/com/android/trisolarispms/ui/roomtype/AmenityFormViewModel.kt @@ -2,6 +2,7 @@ package com.android.trisolarispms.ui.roomtype import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.android.trisolarispms.core.viewmodel.launchApiMutation import com.android.trisolarispms.data.api.core.ApiClient import com.android.trisolarispms.data.api.core.ApiService import com.android.trisolarispms.data.api.model.AmenityCreateRequest @@ -147,19 +148,14 @@ class AmenityFormViewModel : ViewModel() { onDone: () -> Unit, call: suspend (ApiService) -> Response<*> ) { - viewModelScope.launch { - _state.update { it.copy(isLoading = true, error = null) } - try { - val response = call(ApiClient.create()) - if (response.isSuccessful) { - _state.update { it.copy(isLoading = false, success = true) } - onDone() - } else { - _state.update { it.copy(isLoading = false, error = "$action failed: ${response.code()}") } - } - } catch (e: Exception) { - _state.update { it.copy(isLoading = false, error = e.localizedMessage ?: "$action failed") } - } - } + launchApiMutation( + state = _state, + action = action, + setLoading = { it.copy(isLoading = true, error = null) }, + setSuccess = { it.copy(isLoading = false, success = true) }, + setError = { current, message -> current.copy(isLoading = false, error = message) }, + onDone = onDone, + call = call + ) } } diff --git a/app/src/main/java/com/android/trisolarispms/ui/roomtype/RoomTypeFormViewModel.kt b/app/src/main/java/com/android/trisolarispms/ui/roomtype/RoomTypeFormViewModel.kt index 6213573..4369bbd 100644 --- a/app/src/main/java/com/android/trisolarispms/ui/roomtype/RoomTypeFormViewModel.kt +++ b/app/src/main/java/com/android/trisolarispms/ui/roomtype/RoomTypeFormViewModel.kt @@ -1,15 +1,13 @@ package com.android.trisolarispms.ui.roomtype import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.android.trisolarispms.data.api.core.ApiClient +import com.android.trisolarispms.core.viewmodel.launchApiMutation import com.android.trisolarispms.data.api.core.ApiService import com.android.trisolarispms.data.api.model.RoomTypeCreateRequest import com.android.trisolarispms.data.api.model.RoomTypeUpdateRequest import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch import retrofit2.Response class RoomTypeFormViewModel : ViewModel() { @@ -144,19 +142,14 @@ class RoomTypeFormViewModel : ViewModel() { onDone: () -> Unit, call: suspend (ApiService) -> Response<*> ) { - viewModelScope.launch { - _state.update { it.copy(isLoading = true, error = null) } - try { - val response = call(ApiClient.create()) - if (response.isSuccessful) { - _state.update { it.copy(isLoading = false, success = true) } - onDone() - } else { - _state.update { it.copy(isLoading = false, error = "$action failed: ${response.code()}") } - } - } catch (e: Exception) { - _state.update { it.copy(isLoading = false, error = e.localizedMessage ?: "$action failed") } - } - } + launchApiMutation( + state = _state, + action = action, + setLoading = { it.copy(isLoading = true, error = null) }, + setSuccess = { it.copy(isLoading = false, success = true) }, + setError = { current, message -> current.copy(isLoading = false, error = message) }, + onDone = onDone, + call = call + ) } }