Add delete actions for rooms and room types

This commit is contained in:
androidlover5842
2026-01-27 05:04:27 +05:30
parent 4642102ff5
commit 30fcc43f42
5 changed files with 121 additions and 9 deletions

View File

@@ -9,6 +9,7 @@ import com.android.trisolarispms.data.api.model.RoomUpdateRequest
import okhttp3.ResponseBody import okhttp3.ResponseBody
import retrofit2.Response import retrofit2.Response
import retrofit2.http.Body import retrofit2.http.Body
import retrofit2.http.DELETE
import retrofit2.http.GET import retrofit2.http.GET
import retrofit2.http.POST import retrofit2.http.POST
import retrofit2.http.PUT import retrofit2.http.PUT
@@ -33,6 +34,12 @@ interface RoomApi {
@Body body: RoomUpdateRequest @Body body: RoomUpdateRequest
): Response<RoomDto> ): 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") @GET("properties/{propertyId}/rooms/board")
suspend fun getRoomBoard(@Path("propertyId") propertyId: String): Response<RoomBoardDto> suspend fun getRoomBoard(@Path("propertyId") propertyId: String): Response<RoomBoardDto>

View File

@@ -10,7 +10,9 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Done import androidx.compose.material.icons.filled.Done
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
@@ -22,6 +24,7 @@ import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Switch import androidx.compose.material3.Switch
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -52,6 +55,7 @@ fun RoomFormScreen(
val state by viewModel.state.collectAsState() val state by viewModel.state.collectAsState()
val typesState by roomTypesViewModel.state.collectAsState() val typesState by roomTypesViewModel.state.collectAsState()
var expanded by remember { mutableStateOf(false) } var expanded by remember { mutableStateOf(false) }
var showDeleteConfirm by remember { mutableStateOf(false) }
LaunchedEffect(formKey, roomId, roomData) { LaunchedEffect(formKey, roomId, roomData) {
viewModel.reset() viewModel.reset()
@@ -85,6 +89,11 @@ fun RoomFormScreen(
}) { }) {
Icon(Icons.Default.Done, contentDescription = "Save") Icon(Icons.Default.Done, contentDescription = "Save")
} }
if (roomId != null) {
IconButton(onClick = { showDeleteConfirm = true }) {
Icon(Icons.Default.Delete, contentDescription = "Delete Room")
}
}
}, },
colors = TopAppBarDefaults.topAppBarColors() 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 @Composable

View File

@@ -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") }
}
}
}
} }

View File

@@ -11,7 +11,9 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Done import androidx.compose.material.icons.filled.Done
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Checkbox import androidx.compose.material3.Checkbox
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
@@ -20,14 +22,17 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.runtime.remember
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
@@ -45,6 +50,7 @@ fun EditRoomTypeScreen(
) { ) {
val state by viewModel.state.collectAsState() val state by viewModel.state.collectAsState()
val amenityState by amenityViewModel.state.collectAsState() val amenityState by amenityViewModel.state.collectAsState()
val showDeleteConfirm = remember { mutableStateOf(false) }
LaunchedEffect(roomType.id) { LaunchedEffect(roomType.id) {
viewModel.setRoomType(roomType) viewModel.setRoomType(roomType)
@@ -66,6 +72,11 @@ fun EditRoomTypeScreen(
IconButton(onClick = { viewModel.submitUpdate(propertyId, roomType.id.orEmpty(), onSave) }) { IconButton(onClick = { viewModel.submitUpdate(propertyId, roomType.id.orEmpty(), onSave) }) {
Icon(Icons.Default.Done, contentDescription = "Save") 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() colors = TopAppBarDefaults.topAppBarColors()
) )
@@ -131,6 +142,14 @@ fun EditRoomTypeScreen(
) )
Spacer(modifier = Modifier.height(12.dp)) 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) Text(text = "Amenities", style = MaterialTheme.typography.titleSmall)
if (amenityState.items.isEmpty()) { if (amenityState.items.isEmpty()) {
Text(text = "No amenities available", style = MaterialTheme.typography.bodySmall) 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 { state.error?.let {
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))
Text(text = it, color = MaterialTheme.colorScheme.error) 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")
}
}
)
}
} }

View File

@@ -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") }
}
}
}
} }