Add delete actions for rooms and room types
This commit is contained in:
@@ -9,6 +9,7 @@ import com.android.trisolarispms.data.api.model.RoomUpdateRequest
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.Response
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.DELETE
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.PUT
|
||||
@@ -33,6 +34,12 @@ interface RoomApi {
|
||||
@Body body: RoomUpdateRequest
|
||||
): Response<RoomDto>
|
||||
|
||||
@DELETE("properties/{propertyId}/rooms/{roomId}")
|
||||
suspend fun deleteRoom(
|
||||
@Path("propertyId") propertyId: String,
|
||||
@Path("roomId") roomId: String
|
||||
): Response<Unit>
|
||||
|
||||
@GET("properties/{propertyId}/rooms/board")
|
||||
suspend fun getRoomBoard(@Path("propertyId") propertyId: String): Response<RoomBoardDto>
|
||||
|
||||
|
||||
@@ -10,7 +10,9 @@ import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material.icons.filled.Done
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
@@ -22,6 +24,7 @@ import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Switch
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -52,6 +55,7 @@ fun RoomFormScreen(
|
||||
val state by viewModel.state.collectAsState()
|
||||
val typesState by roomTypesViewModel.state.collectAsState()
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
var showDeleteConfirm by remember { mutableStateOf(false) }
|
||||
|
||||
LaunchedEffect(formKey, roomId, roomData) {
|
||||
viewModel.reset()
|
||||
@@ -85,6 +89,11 @@ fun RoomFormScreen(
|
||||
}) {
|
||||
Icon(Icons.Default.Done, contentDescription = "Save")
|
||||
}
|
||||
if (roomId != null) {
|
||||
IconButton(onClick = { showDeleteConfirm = true }) {
|
||||
Icon(Icons.Default.Delete, contentDescription = "Delete Room")
|
||||
}
|
||||
}
|
||||
},
|
||||
colors = TopAppBarDefaults.topAppBarColors()
|
||||
)
|
||||
@@ -174,6 +183,27 @@ fun RoomFormScreen(
|
||||
}
|
||||
}
|
||||
|
||||
if (showDeleteConfirm && roomId != null) {
|
||||
AlertDialog(
|
||||
onDismissRequest = { showDeleteConfirm = false },
|
||||
title = { Text("Delete room?") },
|
||||
text = { Text("This will remove the room. Continue?") },
|
||||
confirmButton = {
|
||||
TextButton(onClick = {
|
||||
showDeleteConfirm = false
|
||||
viewModel.deleteRoom(propertyId, roomId, onSave)
|
||||
}) {
|
||||
Text("Delete")
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = { showDeleteConfirm = false }) {
|
||||
Text("Cancel")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -124,4 +124,26 @@ class RoomFormViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteRoom(propertyId: String, roomId: String, onDone: () -> Unit) {
|
||||
if (roomId.isBlank()) {
|
||||
_state.update { it.copy(error = "Room ID is missing") }
|
||||
return
|
||||
}
|
||||
viewModelScope.launch {
|
||||
_state.update { it.copy(isLoading = true, error = null) }
|
||||
try {
|
||||
val api = ApiClient.create()
|
||||
val response = api.deleteRoom(propertyId, roomId)
|
||||
if (response.isSuccessful) {
|
||||
_state.update { it.copy(isLoading = false, success = true) }
|
||||
onDone()
|
||||
} else {
|
||||
_state.update { it.copy(isLoading = false, error = "Delete failed: ${response.code()}") }
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
_state.update { it.copy(isLoading = false, error = e.localizedMessage ?: "Delete failed") }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,9 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material.icons.filled.Done
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
@@ -20,14 +22,17 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
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.ui.Modifier
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
@@ -45,6 +50,7 @@ fun EditRoomTypeScreen(
|
||||
) {
|
||||
val state by viewModel.state.collectAsState()
|
||||
val amenityState by amenityViewModel.state.collectAsState()
|
||||
val showDeleteConfirm = remember { mutableStateOf(false) }
|
||||
|
||||
LaunchedEffect(roomType.id) {
|
||||
viewModel.setRoomType(roomType)
|
||||
@@ -66,6 +72,11 @@ fun EditRoomTypeScreen(
|
||||
IconButton(onClick = { viewModel.submitUpdate(propertyId, roomType.id.orEmpty(), onSave) }) {
|
||||
Icon(Icons.Default.Done, contentDescription = "Save")
|
||||
}
|
||||
if (!roomType.id.isNullOrBlank()) {
|
||||
IconButton(onClick = { showDeleteConfirm.value = true }) {
|
||||
Icon(Icons.Default.Delete, contentDescription = "Delete Room Type")
|
||||
}
|
||||
}
|
||||
},
|
||||
colors = TopAppBarDefaults.topAppBarColors()
|
||||
)
|
||||
@@ -131,6 +142,14 @@ fun EditRoomTypeScreen(
|
||||
)
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
|
||||
OutlinedTextField(
|
||||
value = state.otaAliases,
|
||||
onValueChange = viewModel::onAliasesChange,
|
||||
label = { Text("OTA Aliases (comma separated)") },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
|
||||
Text(text = "Amenities", style = MaterialTheme.typography.titleSmall)
|
||||
if (amenityState.items.isEmpty()) {
|
||||
Text(text = "No amenities available", style = MaterialTheme.typography.bodySmall)
|
||||
@@ -150,19 +169,31 @@ fun EditRoomTypeScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
|
||||
OutlinedTextField(
|
||||
value = state.otaAliases,
|
||||
onValueChange = viewModel::onAliasesChange,
|
||||
label = { Text("OTA Aliases (comma separated)") },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
|
||||
state.error?.let {
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
Text(text = it, color = MaterialTheme.colorScheme.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showDeleteConfirm.value && !roomType.id.isNullOrBlank()) {
|
||||
AlertDialog(
|
||||
onDismissRequest = { showDeleteConfirm.value = false },
|
||||
title = { Text("Delete room type?") },
|
||||
text = { Text("This will remove the room type. Continue?") },
|
||||
confirmButton = {
|
||||
TextButton(onClick = {
|
||||
showDeleteConfirm.value = false
|
||||
viewModel.deleteRoomType(propertyId, roomType.id.orEmpty(), onSave)
|
||||
}) {
|
||||
Text("Delete")
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = { showDeleteConfirm.value = false }) {
|
||||
Text("Cancel")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,4 +110,26 @@ class RoomTypeFormViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteRoomType(propertyId: String, roomTypeId: String, onDone: () -> Unit) {
|
||||
if (roomTypeId.isBlank()) {
|
||||
_state.update { it.copy(error = "Room type ID is missing") }
|
||||
return
|
||||
}
|
||||
viewModelScope.launch {
|
||||
_state.update { it.copy(isLoading = true, error = null) }
|
||||
try {
|
||||
val api = ApiClient.create()
|
||||
val response = api.deleteRoomType(propertyId, roomTypeId)
|
||||
if (response.isSuccessful) {
|
||||
_state.update { it.copy(isLoading = false, success = true) }
|
||||
onDone()
|
||||
} else {
|
||||
_state.update { it.copy(isLoading = false, error = "Delete failed: ${response.code()}") }
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
_state.update { it.copy(isLoading = false, error = e.localizedMessage ?: "Delete failed") }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user