feat: Refactor Item Edit Screen with all API fields and user-friendly UI
This commit is contained in:
@@ -5,28 +5,48 @@
|
||||
package com.homebox.lens.ui.screen.itemedit
|
||||
|
||||
// [IMPORTS]
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowDropDown
|
||||
import androidx.compose.material.icons.filled.DateRange
|
||||
import androidx.compose.material.icons.filled.Save
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.DatePicker
|
||||
import androidx.compose.material3.DatePickerDialog
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.rememberDatePickerState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
@@ -36,13 +56,16 @@ import com.homebox.lens.R
|
||||
import com.homebox.lens.navigation.NavigationActions
|
||||
import com.homebox.lens.ui.common.MainScaffold
|
||||
import timber.log.Timber
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
// [END_IMPORTS]
|
||||
|
||||
// [ENTITY: Function('ItemEditScreen')]
|
||||
// [RELATION: Function('ItemEditScreen')] -> [DEPENDS_ON] -> [Class('NavigationActions')]
|
||||
// [RELATION: Function('ItemEditScreen')] -> [DEPENDS_ON] -> [ViewModel('ItemEditViewModel')]
|
||||
// [RELATION: Function('ItemEditScreen')] -> [CONSUMES_STATE] -> [DataClass('ItemEditUiState')]
|
||||
// [RELATION: Function('ItemEditScreen')] -> [CALLS] -> [Function('MainScaffold')]
|
||||
// [ENTITY: Composable('ItemEditScreen')]
|
||||
// [RELATION: Composable('ItemEditScreen')] -> [DEPENDS_ON] -> [Class('NavigationActions')]
|
||||
// [RELATION: Composable('ItemEditScreen')] -> [DEPENDS_ON] -> [ViewModel('ItemEditViewModel')]
|
||||
// [RELATION: Composable('ItemEditScreen')] -> [CONSUMES_STATE] -> [DataClass('ItemEditUiState')]
|
||||
// [RELATION: Composable('ItemEditScreen')] -> [CALLS] -> [Composable('MainScaffold')]
|
||||
/**
|
||||
* @summary Composable-функция для экрана "Редактирование элемента".
|
||||
* @param currentRoute Текущий маршрут для подсветки активного элемента в Drawer.
|
||||
@@ -51,6 +74,7 @@ import timber.log.Timber
|
||||
* @param viewModel ViewModel для управления состоянием экрана.
|
||||
* @param onSaveSuccess Callback, вызываемый после успешного сохранения товара.
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ItemEditScreen(
|
||||
currentRoute: String?,
|
||||
@@ -75,7 +99,7 @@ fun ItemEditScreen(
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
viewModel.saveCompleted.collect {
|
||||
viewModel.saveCompleted.collect {
|
||||
Timber.i("[INFO][ACTION][save_completed_callback] Item save completed. Triggering onSaveSuccess.")
|
||||
onSaveSuccess()
|
||||
}
|
||||
@@ -85,7 +109,7 @@ fun ItemEditScreen(
|
||||
topBarTitle = stringResource(id = R.string.item_edit_title),
|
||||
currentRoute = currentRoute,
|
||||
navigationActions = navigationActions
|
||||
) {
|
||||
) { paddingValues ->
|
||||
Scaffold(
|
||||
snackbarHost = { SnackbarHost(snackbarHostState) },
|
||||
floatingActionButton = {
|
||||
@@ -100,40 +124,389 @@ fun ItemEditScreen(
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(it)
|
||||
.padding(paddingValues)
|
||||
.padding(16.dp)
|
||||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
if (uiState.isLoading) {
|
||||
CircularProgressIndicator(modifier = Modifier.fillMaxWidth())
|
||||
} else {
|
||||
uiState.item?.let { item ->
|
||||
OutlinedTextField(
|
||||
value = item.name,
|
||||
onValueChange = { viewModel.updateName(it) },
|
||||
label = { Text(stringResource(R.string.item_name)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
OutlinedTextField(
|
||||
value = item.description ?: "",
|
||||
onValueChange = { viewModel.updateDescription(it) },
|
||||
label = { Text(stringResource(R.string.item_description)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
OutlinedTextField(
|
||||
value = item.quantity.toString(),
|
||||
onValueChange = { viewModel.updateQuantity(it.toIntOrNull() ?: 0) },
|
||||
label = { Text(stringResource(R.string.item_quantity)) },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
// Add more fields as needed
|
||||
// [AI_NOTE]: General Information section for basic item details.
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
elevation = CardDefaults.cardElevation(4.dp)
|
||||
) {
|
||||
Column(modifier = Modifier.padding(16.dp)) {
|
||||
Text(
|
||||
text = stringResource(R.string.item_general_information),
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
OutlinedTextField(
|
||||
value = item.name,
|
||||
onValueChange = { viewModel.updateName(it) },
|
||||
label = { Text(stringResource(R.string.item_name)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
OutlinedTextField(
|
||||
value = item.description ?: "",
|
||||
onValueChange = { viewModel.updateDescription(it) },
|
||||
label = { Text(stringResource(R.string.item_description)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
OutlinedTextField(
|
||||
value = item.quantity.toString(),
|
||||
onValueChange = { viewModel.updateQuantity(it.toIntOrNull() ?: 0) },
|
||||
label = { Text(stringResource(R.string.item_quantity)) },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
// [AI_NOTE]: Location selection will require a separate component or screen.
|
||||
OutlinedTextField(
|
||||
value = item.location?.name ?: "",
|
||||
onValueChange = { /* TODO: Implement location selection */ },
|
||||
label = { Text(stringResource(R.string.item_location)) },
|
||||
readOnly = true,
|
||||
trailingIcon = {
|
||||
IconButton(onClick = { /* TODO: Implement location selection */ }) {
|
||||
Icon(Icons.Filled.ArrowDropDown, contentDescription = stringResource(R.string.select_location))
|
||||
}
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
// [AI_NOTE]: Label selection will require a separate component or screen.
|
||||
OutlinedTextField(
|
||||
value = item.labels.joinToString { it.name },
|
||||
onValueChange = { /* TODO: Implement label selection */ },
|
||||
label = { Text(stringResource(R.string.item_labels)) },
|
||||
readOnly = true,
|
||||
trailingIcon = {
|
||||
IconButton(onClick = { /* TODO: Implement label selection */ }) {
|
||||
Icon(Icons.Filled.ArrowDropDown, contentDescription = stringResource(R.string.select_labels))
|
||||
}
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
// [AI_NOTE]: Purchase Information section.
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
elevation = CardDefaults.cardElevation(4.dp)
|
||||
) {
|
||||
Column(modifier = Modifier.padding(16.dp)) {
|
||||
Text(
|
||||
text = stringResource(R.string.item_purchase_information),
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
OutlinedTextField(
|
||||
value = item.purchasePrice?.toString() ?: "",
|
||||
onValueChange = { viewModel.updatePurchasePrice(it.toBigDecimalOrNull()) },
|
||||
label = { Text(stringResource(R.string.item_purchase_price)) },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
OutlinedTextField(
|
||||
value = item.purchaseFrom ?: "",
|
||||
onValueChange = { viewModel.updatePurchaseFrom(it) },
|
||||
label = { Text(stringResource(R.string.item_purchase_from)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
// [AI_NOTE]: Date picker for purchase time.
|
||||
var showPurchaseDatePicker by remember { mutableStateOf(false) }
|
||||
val purchaseDateState = rememberDatePickerState()
|
||||
OutlinedTextField(
|
||||
value = item.purchaseTime ?: "",
|
||||
onValueChange = { }, // Read-only, handled by date picker
|
||||
label = { Text(stringResource(R.string.item_purchase_time)) },
|
||||
readOnly = true,
|
||||
trailingIcon = {
|
||||
IconButton(onClick = { showPurchaseDatePicker = true }) {
|
||||
Icon(Icons.Filled.DateRange, contentDescription = stringResource(R.string.select_date))
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { showPurchaseDatePicker = true }
|
||||
)
|
||||
if (showPurchaseDatePicker) {
|
||||
DatePickerDialog(
|
||||
onDismissRequest = { showPurchaseDatePicker = false },
|
||||
confirmButton = {
|
||||
Text(stringResource(R.string.ok), modifier = Modifier.clickable {
|
||||
val selectedDate = purchaseDateState.selectedDateMillis?.let {
|
||||
SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date(it))
|
||||
}
|
||||
if (selectedDate != null) {
|
||||
viewModel.updatePurchaseTime(selectedDate)
|
||||
}
|
||||
showPurchaseDatePicker = false
|
||||
})
|
||||
},
|
||||
dismissButton = {
|
||||
Text(stringResource(R.string.cancel), modifier = Modifier.clickable { showPurchaseDatePicker = false })
|
||||
}
|
||||
) {
|
||||
DatePicker(state = purchaseDateState)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
// [AI_NOTE]: Warranty Information section.
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
elevation = CardDefaults.cardElevation(4.dp)
|
||||
) {
|
||||
Column(modifier = Modifier.padding(16.dp)) {
|
||||
Text(
|
||||
text = stringResource(R.string.item_warranty_information),
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(stringResource(R.string.item_lifetime_warranty))
|
||||
Switch(
|
||||
checked = item.lifetimeWarranty,
|
||||
onCheckedChange = { viewModel.updateLifetimeWarranty(it) }
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
OutlinedTextField(
|
||||
value = item.warrantyDetails ?: "",
|
||||
onValueChange = { viewModel.updateWarrantyDetails(it) },
|
||||
label = { Text(stringResource(R.string.item_warranty_details)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
// [AI_NOTE]: Date picker for warranty expiration.
|
||||
var showWarrantyDatePicker by remember { mutableStateOf(false) }
|
||||
val warrantyDateState = rememberDatePickerState()
|
||||
OutlinedTextField(
|
||||
value = item.warrantyExpires ?: "",
|
||||
onValueChange = { }, // Read-only, handled by date picker
|
||||
label = { Text(stringResource(R.string.item_warranty_expires)) },
|
||||
readOnly = true,
|
||||
trailingIcon = {
|
||||
IconButton(onClick = { showWarrantyDatePicker = true }) {
|
||||
Icon(Icons.Filled.DateRange, contentDescription = stringResource(R.string.select_date))
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { showWarrantyDatePicker = true }
|
||||
)
|
||||
if (showWarrantyDatePicker) {
|
||||
DatePickerDialog(
|
||||
onDismissRequest = { showWarrantyDatePicker = false },
|
||||
confirmButton = {
|
||||
Text(stringResource(R.string.ok), modifier = Modifier.clickable {
|
||||
val selectedDate = warrantyDateState.selectedDateMillis?.let {
|
||||
SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date(it))
|
||||
}
|
||||
if (selectedDate != null) {
|
||||
viewModel.updateWarrantyExpires(selectedDate)
|
||||
}
|
||||
showWarrantyDatePicker = false
|
||||
})
|
||||
},
|
||||
dismissButton = {
|
||||
Text(stringResource(R.string.cancel), modifier = Modifier.clickable { showWarrantyDatePicker = false })
|
||||
}
|
||||
) {
|
||||
DatePicker(state = warrantyDateState)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
// [AI_NOTE]: Identification section.
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
elevation = CardDefaults.cardElevation(4.dp)
|
||||
) {
|
||||
Column(modifier = Modifier.padding(16.dp)) {
|
||||
Text(
|
||||
text = stringResource(R.string.item_identification),
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
OutlinedTextField(
|
||||
value = item.assetId ?: "",
|
||||
onValueChange = { viewModel.updateAssetId(it) },
|
||||
label = { Text(stringResource(R.string.item_asset_id)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
OutlinedTextField(
|
||||
value = item.serialNumber ?: "",
|
||||
onValueChange = { viewModel.updateSerialNumber(it) },
|
||||
label = { Text(stringResource(R.string.item_serial_number)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
OutlinedTextField(
|
||||
value = item.manufacturer ?: "",
|
||||
onValueChange = { viewModel.updateManufacturer(it) },
|
||||
label = { Text(stringResource(R.string.item_manufacturer)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
OutlinedTextField(
|
||||
value = item.modelNumber ?: "",
|
||||
onValueChange = { viewModel.updateModelNumber(it) },
|
||||
label = { Text(stringResource(R.string.item_model_number)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
// [AI_NOTE]: Status & Notes section.
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
elevation = CardDefaults.cardElevation(4.dp)
|
||||
) {
|
||||
Column(modifier = Modifier.padding(16.dp)) {
|
||||
Text(
|
||||
text = stringResource(R.string.item_status_notes),
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(stringResource(R.string.item_archived))
|
||||
Switch(
|
||||
checked = item.archived,
|
||||
onCheckedChange = { viewModel.updateArchived(it) }
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(stringResource(R.string.item_insured))
|
||||
Switch(
|
||||
checked = item.insured,
|
||||
onCheckedChange = { viewModel.updateInsured(it) }
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
OutlinedTextField(
|
||||
value = item.notes ?: "",
|
||||
onValueChange = { viewModel.updateNotes(it) },
|
||||
label = { Text(stringResource(R.string.item_notes)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
// [AI_NOTE]: Sold Information section (conditionally displayed).
|
||||
if (item.soldTime != null || item.soldPrice != null || item.soldTo != null || item.soldNotes != null) {
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
elevation = CardDefaults.cardElevation(4.dp)
|
||||
) {
|
||||
Column(modifier = Modifier.padding(16.dp)) {
|
||||
Text(
|
||||
text = stringResource(R.string.item_sold_information),
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
OutlinedTextField(
|
||||
value = item.soldPrice?.toString() ?: "",
|
||||
onValueChange = { viewModel.updateSoldPrice(it.toBigDecimalOrNull()) },
|
||||
label = { Text(stringResource(R.string.item_sold_price)) },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
OutlinedTextField(
|
||||
value = item.soldTo ?: "",
|
||||
onValueChange = { viewModel.updateSoldTo(it) },
|
||||
label = { Text(stringResource(R.string.item_sold_to)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
OutlinedTextField(
|
||||
value = item.soldNotes ?: "",
|
||||
onValueChange = { viewModel.updateSoldNotes(it) },
|
||||
label = { Text(stringResource(R.string.item_sold_notes)) },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
// [AI_NOTE]: Date picker for sold time.
|
||||
var showSoldDatePicker by remember { mutableStateOf(false) }
|
||||
val soldDateState = rememberDatePickerState()
|
||||
OutlinedTextField(
|
||||
value = item.soldTime ?: "",
|
||||
onValueChange = { }, // Read-only, handled by date picker
|
||||
label = { Text(stringResource(R.string.item_sold_time)) },
|
||||
readOnly = true,
|
||||
trailingIcon = {
|
||||
IconButton(onClick = { showSoldDatePicker = true }) {
|
||||
Icon(Icons.Filled.DateRange, contentDescription = stringResource(R.string.select_date))
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { showSoldDatePicker = true }
|
||||
)
|
||||
if (showSoldDatePicker) {
|
||||
DatePickerDialog(
|
||||
onDismissRequest = { showSoldDatePicker = false },
|
||||
confirmButton = {
|
||||
Text(stringResource(R.string.ok), modifier = Modifier.clickable {
|
||||
val selectedDate = soldDateState.selectedDateMillis?.let {
|
||||
SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date(it))
|
||||
}
|
||||
if (selectedDate != null) {
|
||||
viewModel.updateSoldTime(selectedDate)
|
||||
}
|
||||
showSoldDatePicker = false
|
||||
})
|
||||
},
|
||||
dismissButton = {
|
||||
Text(stringResource(R.string.cancel), modifier = Modifier.clickable { showSoldDatePicker = false })
|
||||
}
|
||||
) {
|
||||
DatePicker(state = soldDateState)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// [END_ENTITY: Function('ItemEditScreen')]
|
||||
// [END_ENTITY: Composable('ItemEditScreen')]
|
||||
// [END_FILE_ItemEditScreen.kt]
|
||||
|
||||
@@ -7,8 +7,10 @@ package com.homebox.lens.ui.screen.itemedit
|
||||
// [IMPORTS]
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.homebox.lens.data.db.entity.toDomainItem
|
||||
import com.homebox.lens.domain.model.Item
|
||||
import com.homebox.lens.domain.model.ItemCreate
|
||||
import com.homebox.lens.domain.model.ItemUpdate
|
||||
import com.homebox.lens.domain.model.Label
|
||||
import com.homebox.lens.domain.model.Location
|
||||
import com.homebox.lens.domain.usecase.CreateItemUseCase
|
||||
@@ -23,6 +25,7 @@ import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import java.math.BigDecimal
|
||||
import javax.inject.Inject
|
||||
// [END_IMPORTS]
|
||||
|
||||
@@ -73,24 +76,45 @@ class ItemEditViewModel @Inject constructor(
|
||||
_uiState.value = _uiState.value.copy(isLoading = true, error = null)
|
||||
if (itemId == null) {
|
||||
Timber.i("[INFO][ACTION][new_item_preparation] Preparing for new item creation.")
|
||||
_uiState.value = _uiState.value.copy(isLoading = false, item = Item(id = "", name = "", description = null, quantity = 0, image = null, location = null, labels = emptyList(), value = null, createdAt = null))
|
||||
_uiState.value = _uiState.value.copy(
|
||||
isLoading = false,
|
||||
item = Item(
|
||||
id = "",
|
||||
name = "",
|
||||
description = null,
|
||||
quantity = 1,
|
||||
image = null,
|
||||
location = null,
|
||||
labels = emptyList(),
|
||||
purchasePrice = null,
|
||||
createdAt = null,
|
||||
archived = false,
|
||||
assetId = null,
|
||||
fields = emptyList(),
|
||||
insured = false,
|
||||
lifetimeWarranty = false,
|
||||
manufacturer = null,
|
||||
modelNumber = null,
|
||||
notes = null,
|
||||
parentId = null,
|
||||
purchaseFrom = null,
|
||||
purchaseTime = null,
|
||||
serialNumber = null,
|
||||
soldNotes = null,
|
||||
soldPrice = null,
|
||||
soldTime = null,
|
||||
soldTo = null,
|
||||
syncChildItemsLocations = false,
|
||||
warrantyDetails = null,
|
||||
warrantyExpires = null
|
||||
)
|
||||
)
|
||||
} else {
|
||||
try {
|
||||
Timber.i("[INFO][ACTION][fetching_item_details] Fetching details for item ID: %s", itemId)
|
||||
val itemOut = getItemDetailsUseCase(itemId)
|
||||
Timber.d("[DEBUG][ACTION][mapping_item_out_to_item] Mapping ItemOut to Item for UI state.")
|
||||
val item = Item(
|
||||
id = itemOut.id,
|
||||
name = itemOut.name,
|
||||
description = itemOut.description,
|
||||
quantity = itemOut.quantity,
|
||||
image = itemOut.images.firstOrNull()?.path, // Assuming first image is the main one
|
||||
location = itemOut.location?.let { Location(it.id, it.name) }, // Simplified mapping
|
||||
labels = itemOut.labels.map { Label(it.id, it.name) }, // Simplified mapping
|
||||
value = itemOut.value?.toBigDecimal(),
|
||||
createdAt = itemOut.createdAt
|
||||
)
|
||||
_uiState.value = _uiState.value.copy(isLoading = false, item = item)
|
||||
_uiState.value = _uiState.value.copy(isLoading = false, item = itemOut.toDomainItem())
|
||||
Timber.i("[INFO][ACTION][item_details_fetched] Successfully fetched item details for ID: %s", itemId)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "[ERROR][FALLBACK][item_load_failed] Failed to load item details for ID: %s", itemId)
|
||||
@@ -117,53 +141,72 @@ class ItemEditViewModel @Inject constructor(
|
||||
try {
|
||||
if (currentItem.id.isBlank()) {
|
||||
Timber.i("[INFO][ACTION][creating_new_item] Creating new item: %s", currentItem.name)
|
||||
val createdItemSummary = createItemUseCase(ItemCreate(
|
||||
name = currentItem.name,
|
||||
description = currentItem.description,
|
||||
quantity = currentItem.quantity,
|
||||
assetId = null, // Item does not have assetId
|
||||
notes = null, // Item does not have notes
|
||||
serialNumber = null, // Item does not have serialNumber
|
||||
value = currentItem.value?.toDouble(), // Convert BigDecimal to Double
|
||||
purchasePrice = null, // Item does not have purchasePrice
|
||||
purchaseDate = null, // Item does not have purchaseDate
|
||||
warrantyUntil = null, // Item does not have warrantyUntil
|
||||
locationId = currentItem.location?.id,
|
||||
parentId = null, // Item does not have parentId
|
||||
labelIds = currentItem.labels.map { it.id }
|
||||
))
|
||||
Timber.d("[DEBUG][ACTION][mapping_item_summary_to_item] Mapping ItemSummary to Item for UI state.")
|
||||
val createdItem = Item(
|
||||
id = createdItemSummary.id,
|
||||
name = createdItemSummary.name,
|
||||
description = null, // ItemSummary does not have description
|
||||
quantity = 0, // ItemSummary does not have quantity
|
||||
image = null, // ItemSummary does not have image
|
||||
location = null, // ItemSummary does not have location
|
||||
labels = emptyList(), // ItemSummary does not have labels
|
||||
value = null, // ItemSummary does not have value
|
||||
createdAt = null // ItemSummary does not have createdAt
|
||||
val createdItemOut = createItemUseCase(
|
||||
ItemCreate(
|
||||
name = currentItem.name,
|
||||
description = currentItem.description,
|
||||
quantity = currentItem.quantity,
|
||||
archived = currentItem.archived,
|
||||
assetId = currentItem.assetId,
|
||||
insured = currentItem.insured,
|
||||
lifetimeWarranty = currentItem.lifetimeWarranty,
|
||||
manufacturer = currentItem.manufacturer,
|
||||
modelNumber = currentItem.modelNumber,
|
||||
notes = currentItem.notes,
|
||||
parentId = currentItem.parentId,
|
||||
purchaseFrom = currentItem.purchaseFrom,
|
||||
purchasePrice = currentItem.purchasePrice,
|
||||
purchaseTime = currentItem.purchaseTime,
|
||||
serialNumber = currentItem.serialNumber,
|
||||
soldNotes = currentItem.soldNotes,
|
||||
soldPrice = currentItem.soldPrice,
|
||||
soldTime = currentItem.soldTime,
|
||||
soldTo = currentItem.soldTo,
|
||||
syncChildItemsLocations = currentItem.syncChildItemsLocations,
|
||||
warrantyDetails = currentItem.warrantyDetails,
|
||||
warrantyExpires = currentItem.warrantyExpires,
|
||||
locationId = currentItem.location?.id,
|
||||
labelIds = currentItem.labels.map { it.id }
|
||||
)
|
||||
)
|
||||
_uiState.value = _uiState.value.copy(isLoading = false, item = createdItem)
|
||||
Timber.i("[INFO][ACTION][new_item_created] Successfully created new item with ID: %s", createdItem.id)
|
||||
Timber.d("[DEBUG][ACTION][mapping_item_out_to_item] Mapping ItemOut to Item for UI state.")
|
||||
_uiState.value = _uiState.value.copy(isLoading = false, item = createdItemOut.toDomainItem())
|
||||
Timber.i("[INFO][ACTION][new_item_created] Successfully created new item with ID: %s", createdItemOut.id)
|
||||
_saveCompleted.emit(Unit)
|
||||
} else {
|
||||
Timber.i("[INFO][ACTION][updating_existing_item] Updating existing item with ID: %s", currentItem.id)
|
||||
val updatedItemOut = updateItemUseCase(currentItem)
|
||||
Timber.d("[DEBUG][ACTION][mapping_item_out_to_item] Mapping ItemOut to Item for UI state.")
|
||||
val updatedItem = Item(
|
||||
id = updatedItemOut.id,
|
||||
name = updatedItemOut.name,
|
||||
description = updatedItemOut.description,
|
||||
quantity = updatedItemOut.quantity,
|
||||
image = updatedItemOut.images.firstOrNull()?.path,
|
||||
location = updatedItemOut.location?.let { Location(it.id, it.name) },
|
||||
labels = updatedItemOut.labels.map { Label(it.id, it.name) },
|
||||
value = updatedItemOut.value.toBigDecimal(),
|
||||
createdAt = updatedItemOut.createdAt
|
||||
val updatedItemOut = updateItemUseCase(
|
||||
ItemUpdate(
|
||||
id = currentItem.id,
|
||||
name = currentItem.name,
|
||||
description = currentItem.description,
|
||||
quantity = currentItem.quantity,
|
||||
archived = currentItem.archived,
|
||||
assetId = currentItem.assetId,
|
||||
insured = currentItem.insured,
|
||||
lifetimeWarranty = currentItem.lifetimeWarranty,
|
||||
manufacturer = currentItem.manufacturer,
|
||||
modelNumber = currentItem.modelNumber,
|
||||
notes = currentItem.notes,
|
||||
parentId = currentItem.parentId,
|
||||
purchaseFrom = currentItem.purchaseFrom,
|
||||
purchasePrice = currentItem.purchasePrice,
|
||||
purchaseTime = currentItem.purchaseTime,
|
||||
serialNumber = currentItem.serialNumber,
|
||||
soldNotes = currentItem.soldNotes,
|
||||
soldPrice = currentItem.soldPrice,
|
||||
soldTime = currentItem.soldTime,
|
||||
soldTo = currentItem.soldTo,
|
||||
syncChildItemsLocations = currentItem.syncChildItemsLocations,
|
||||
warrantyDetails = currentItem.warrantyDetails,
|
||||
warrantyExpires = currentItem.warrantyExpires,
|
||||
locationId = currentItem.location?.id,
|
||||
labelIds = currentItem.labels.map { it.id }
|
||||
)
|
||||
)
|
||||
_uiState.value = _uiState.value.copy(isLoading = false, item = updatedItem)
|
||||
Timber.i("[INFO][ACTION][item_updated] Successfully updated item with ID: %s", updatedItem.id)
|
||||
Timber.d("[DEBUG][ACTION][mapping_item_out_to_item] Mapping ItemOut to Item for UI state.")
|
||||
_uiState.value = _uiState.value.copy(isLoading = false, item = updatedItemOut.toDomainItem())
|
||||
Timber.i("[INFO][ACTION][item_updated] Successfully updated item with ID: %s", updatedItemOut.id)
|
||||
_saveCompleted.emit(Unit)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
@@ -209,6 +252,234 @@ class ItemEditViewModel @Inject constructor(
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(quantity = newQuantity))
|
||||
}
|
||||
// [END_ENTITY: Function('updateQuantity')]
|
||||
}
|
||||
// [END_ENTITY: ViewModel('ItemEditViewModel')]
|
||||
// [END_FILE_ItemEditViewModel.kt]
|
||||
|
||||
// [ENTITY: Function('updateArchived')]
|
||||
/**
|
||||
* @summary Updates the archived status of the item in the UI state.
|
||||
* @param newArchived The new archived status for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updateArchived(newArchived: Boolean) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_archived] Updating item archived status to: %s", newArchived)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(archived = newArchived))
|
||||
}
|
||||
// [END_ENTITY: Function('updateArchived')]
|
||||
|
||||
// [ENTITY: Function('updateAssetId')]
|
||||
/**
|
||||
* @summary Updates the asset ID of the item in the UI state.
|
||||
* @param newAssetId The new asset ID for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updateAssetId(newAssetId: String) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_assetId] Updating item asset ID to: %s", newAssetId)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(assetId = newAssetId))
|
||||
}
|
||||
// [END_ENTITY: Function('updateAssetId')]
|
||||
|
||||
// [ENTITY: Function('updateInsured')]
|
||||
/**
|
||||
* @summary Updates the insured status of the item in the UI state.
|
||||
* @param newInsured The new insured status for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updateInsured(newInsured: Boolean) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_insured] Updating item insured status to: %s", newInsured)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(insured = newInsured))
|
||||
}
|
||||
// [END_ENTITY: Function('updateInsured')]
|
||||
|
||||
// [ENTITY: Function('updateLifetimeWarranty')]
|
||||
/**
|
||||
* @summary Updates the lifetime warranty status of the item in the UI state.
|
||||
* @param newLifetimeWarranty The new lifetime warranty status for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updateLifetimeWarranty(newLifetimeWarranty: Boolean) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_lifetime_warranty] Updating item lifetime warranty status to: %s", newLifetimeWarranty)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(lifetimeWarranty = newLifetimeWarranty))
|
||||
}
|
||||
// [END_ENTITY: Function('updateLifetimeWarranty')]
|
||||
|
||||
// [ENTITY: Function('updateManufacturer')]
|
||||
/**
|
||||
* @summary Updates the manufacturer of the item in the UI state.
|
||||
* @param newManufacturer The new manufacturer for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updateManufacturer(newManufacturer: String) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_manufacturer] Updating item manufacturer to: %s", newManufacturer)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(manufacturer = newManufacturer))
|
||||
}
|
||||
// [END_ENTITY: Function('updateManufacturer')]
|
||||
|
||||
// [ENTITY: Function('updateModelNumber')]
|
||||
/**
|
||||
* @summary Updates the model number of the item in the UI state.
|
||||
* @param newModelNumber The new model number for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updateModelNumber(newModelNumber: String) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_model_number] Updating item model number to: %s", newModelNumber)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(modelNumber = newModelNumber))
|
||||
}
|
||||
// [END_ENTITY: Function('updateModelNumber')]
|
||||
|
||||
// [ENTITY: Function('updateNotes')]
|
||||
/**
|
||||
* @summary Updates the notes of the item in the UI state.
|
||||
* @param newNotes The new notes for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updateNotes(newNotes: String) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_notes] Updating item notes to: %s", newNotes)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(notes = newNotes))
|
||||
}
|
||||
// [END_ENTITY: Function('updateNotes')]
|
||||
|
||||
// [ENTITY: Function('updateParentId')]
|
||||
/**
|
||||
* @summary Updates the parent ID of the item in the UI state.
|
||||
* @param newParentId The new parent ID for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updateParentId(newParentId: String) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_parent_id] Updating item parent ID to: %s", newParentId)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(parentId = newParentId))
|
||||
}
|
||||
// [END_ENTITY: Function('updateParentId')]
|
||||
|
||||
// [ENTITY: Function('updatePurchaseFrom')]
|
||||
/**
|
||||
* @summary Updates the purchase source of the item in the UI state.
|
||||
* @param newPurchaseFrom The new purchase source for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updatePurchaseFrom(newPurchaseFrom: String) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_purchase_from] Updating item purchase from to: %s", newPurchaseFrom)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(purchaseFrom = newPurchaseFrom))
|
||||
}
|
||||
// [END_ENTITY: Function('updatePurchaseFrom')]
|
||||
|
||||
// [ENTITY: Function('updatePurchasePrice')]
|
||||
/**
|
||||
* @summary Updates the purchase price of the item in the UI state.
|
||||
* @param newPurchasePrice The new purchase price for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updatePurchasePrice(newPurchasePrice: BigDecimal?) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_purchase_price] Updating item purchase price to: %s", newPurchasePrice)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(purchasePrice = newPurchasePrice))
|
||||
}
|
||||
// [END_ENTITY: Function('updatePurchasePrice')]
|
||||
|
||||
// [ENTITY: Function('updatePurchaseTime')]
|
||||
/**
|
||||
* @summary Updates the purchase time of the item in the UI state.
|
||||
* @param newPurchaseTime The new purchase time for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updatePurchaseTime(newPurchaseTime: String) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_purchase_time] Updating item purchase time to: %s", newPurchaseTime)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(purchaseTime = newPurchaseTime))
|
||||
}
|
||||
// [END_ENTITY: Function('updatePurchaseTime')]
|
||||
|
||||
// [ENTITY: Function('updateSerialNumber')]
|
||||
/**
|
||||
* @summary Updates the serial number of the item in the UI state.
|
||||
* @param newSerialNumber The new serial number for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updateSerialNumber(newSerialNumber: String) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_serial_number] Updating item serial number to: %s", newSerialNumber)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(serialNumber = newSerialNumber))
|
||||
}
|
||||
// [END_ENTITY: Function('updateSerialNumber')]
|
||||
|
||||
// [ENTITY: Function('updateSoldNotes')]
|
||||
/**
|
||||
* @summary Updates the sold notes of the item in the UI state.
|
||||
* @param newSoldNotes The new sold notes for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updateSoldNotes(newSoldNotes: String) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_sold_notes] Updating item sold notes to: %s", newSoldNotes)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(soldNotes = newSoldNotes))
|
||||
}
|
||||
// [END_ENTITY: Function('updateSoldNotes')]
|
||||
|
||||
// [ENTITY: Function('updateSoldPrice')]
|
||||
/**
|
||||
* @summary Updates the sold price of the item in the UI state.
|
||||
* @param newSoldPrice The new sold price for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updateSoldPrice(newSoldPrice: BigDecimal?) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_sold_price] Updating item sold price to: %s", newSoldPrice)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(soldPrice = newSoldPrice))
|
||||
}
|
||||
// [END_ENTITY: Function('updateSoldPrice')]
|
||||
|
||||
// [ENTITY: Function('updateSoldTime')]
|
||||
/**
|
||||
* @summary Updates the sold time of the item in the UI state.
|
||||
* @param newSoldTime The new sold time for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updateSoldTime(newSoldTime: String) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_sold_time] Updating item sold time to: %s", newSoldTime)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(soldTime = newSoldTime))
|
||||
}
|
||||
// [END_ENTITY: Function('updateSoldTime')]
|
||||
|
||||
// [ENTITY: Function('updateSoldTo')]
|
||||
/**
|
||||
* @summary Updates the sold to field of the item in the UI state.
|
||||
* @param newSoldTo The new sold to for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updateSoldTo(newSoldTo: String) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_sold_to] Updating item sold to to: %s", newSoldTo)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(soldTo = newSoldTo))
|
||||
}
|
||||
// [END_ENTITY: Function('updateSoldTo')]
|
||||
|
||||
// [ENTITY: Function('updateSyncChildItemsLocations')]
|
||||
/**
|
||||
* @summary Updates the sync child items locations status of the item in the UI state.
|
||||
* @param newSyncChildItemsLocations The new sync child items locations status for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updateSyncChildItemsLocations(newSyncChildItemsLocations: Boolean) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_sync_child_items_locations] Updating item sync child items locations status to: %s", newSyncChildItemsLocations)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(syncChildItemsLocations = newSyncChildItemsLocations))
|
||||
}
|
||||
// [END_ENTITY: Function('updateSyncChildItemsLocations')]
|
||||
|
||||
// [ENTITY: Function('updateWarrantyDetails')]
|
||||
/**
|
||||
* @summary Updates the warranty details of the item in the UI state.
|
||||
* @param newWarrantyDetails The new warranty details for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updateWarrantyDetails(newWarrantyDetails: String) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_warranty_details] Updating item warranty details to: %s", newWarrantyDetails)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(warrantyDetails = newWarrantyDetails))
|
||||
}
|
||||
// [END_ENTITY: Function('updateWarrantyDetails')]
|
||||
|
||||
// [ENTITY: Function('updateWarrantyExpires')]
|
||||
/**
|
||||
* @summary Updates the warranty expires date of the item in the UI state.
|
||||
* @param newWarrantyExpires The new warranty expires date for the item.
|
||||
* @sideeffect Updates the `item` in `_uiState`.
|
||||
*/
|
||||
fun updateWarrantyExpires(newWarrantyExpires: String) {
|
||||
Timber.d("[DEBUG][ACTION][updating_item_warranty_expires] Updating item warranty expires date to: %s", newWarrantyExpires)
|
||||
_uiState.value = _uiState.value.copy(item = _uiState.value.item?.copy(warrantyExpires = newWarrantyExpires))
|
||||
}
|
||||
// [END_ENTITY: Function('updateWarrantyExpires')]
|
||||
}
|
||||
// [END_ENTITY: ViewModel('ItemEditViewModel')]
|
||||
// [END_FILE_ItemEditViewModel.kt]
|
||||
|
||||
Reference in New Issue
Block a user