AI:remove more boilerplate
This commit is contained in:
@@ -14,10 +14,8 @@ import androidx.compose.foundation.rememberScrollState
|
|||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
|
||||||
import androidx.compose.material.icons.filled.CalendarMonth
|
import androidx.compose.material.icons.filled.CalendarMonth
|
||||||
import androidx.compose.material.icons.filled.Schedule
|
import androidx.compose.material.icons.filled.Schedule
|
||||||
import androidx.compose.material.icons.filled.Done
|
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
import androidx.compose.material3.ExposedDropdownMenuBox
|
import androidx.compose.material3.ExposedDropdownMenuBox
|
||||||
@@ -27,11 +25,8 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
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.TopAppBar
|
|
||||||
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
|
||||||
@@ -46,6 +41,7 @@ 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
|
||||||
import com.android.trisolarispms.data.api.model.BookingBillingMode
|
import com.android.trisolarispms.data.api.model.BookingBillingMode
|
||||||
|
import com.android.trisolarispms.ui.common.SaveTopBarScaffold
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.OffsetDateTime
|
import java.time.OffsetDateTime
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
@@ -94,23 +90,10 @@ fun BookingCreateScreen(
|
|||||||
viewModel.onExpectedCheckOutAtChange(formatBookingIso(defaultCheckoutDate, checkOutTime.value))
|
viewModel.onExpectedCheckOutAtChange(formatBookingIso(defaultCheckoutDate, checkOutTime.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
SaveTopBarScaffold(
|
||||||
topBar = {
|
title = "Create Booking",
|
||||||
TopAppBar(
|
onBack = onBack,
|
||||||
title = { Text("Create Booking") },
|
onSave = { viewModel.submit(propertyId, onCreated) }
|
||||||
navigationIcon = {
|
|
||||||
IconButton(onClick = onBack) {
|
|
||||||
Icon(Icons.AutoMirrored.Default.ArrowBack, contentDescription = "Back")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions = {
|
|
||||||
IconButton(onClick = { viewModel.submit(propertyId, onCreated) }) {
|
|
||||||
Icon(Icons.Default.Done, contentDescription = "Save")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors = TopAppBarDefaults.topAppBarColors()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { padding ->
|
) { padding ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|||||||
@@ -3,24 +3,16 @@ package com.android.trisolarispms.ui.booking
|
|||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
|
||||||
import androidx.compose.material.icons.filled.CalendarMonth
|
import androidx.compose.material.icons.filled.CalendarMonth
|
||||||
import androidx.compose.material.icons.filled.Done
|
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
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
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
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.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@@ -30,6 +22,8 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.android.trisolarispms.data.api.core.ApiClient
|
import com.android.trisolarispms.data.api.core.ApiClient
|
||||||
import com.android.trisolarispms.data.api.model.BookingExpectedDatesRequest
|
import com.android.trisolarispms.data.api.model.BookingExpectedDatesRequest
|
||||||
|
import com.android.trisolarispms.ui.common.PaddedScreenColumn
|
||||||
|
import com.android.trisolarispms.ui.common.SaveTopBarScaffold
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.OffsetDateTime
|
import java.time.OffsetDateTime
|
||||||
@@ -37,7 +31,6 @@ import java.time.ZoneId
|
|||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
fun BookingExpectedDatesScreen(
|
fun BookingExpectedDatesScreen(
|
||||||
propertyId: String,
|
propertyId: String,
|
||||||
bookingId: String,
|
bookingId: String,
|
||||||
@@ -84,65 +77,44 @@ fun BookingExpectedDatesScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
SaveTopBarScaffold(
|
||||||
topBar = {
|
title = "Update Expected Dates",
|
||||||
TopAppBar(
|
onBack = onBack,
|
||||||
title = { Text("Update Expected Dates") },
|
saveEnabled = !isLoading.value,
|
||||||
navigationIcon = {
|
onSave = {
|
||||||
IconButton(onClick = onBack) {
|
isLoading.value = true
|
||||||
Icon(Icons.AutoMirrored.Default.ArrowBack, contentDescription = "Back")
|
error.value = null
|
||||||
|
val inAt = if (editableCheckIn) {
|
||||||
|
checkInDate.value?.let { formatBookingIso(it, checkInTime.value) }
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
val outAt = checkOutDate.value?.let { formatBookingIso(it, checkOutTime.value) }
|
||||||
|
scope.launch {
|
||||||
|
try {
|
||||||
|
val api = ApiClient.create()
|
||||||
|
val response = api.updateExpectedDates(
|
||||||
|
propertyId = propertyId,
|
||||||
|
bookingId = bookingId,
|
||||||
|
body = BookingExpectedDatesRequest(
|
||||||
|
expectedCheckInAt = inAt,
|
||||||
|
expectedCheckOutAt = outAt
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
onDone()
|
||||||
|
} else {
|
||||||
|
error.value = "Update failed: ${response.code()}"
|
||||||
}
|
}
|
||||||
},
|
} catch (e: Exception) {
|
||||||
actions = {
|
error.value = e.localizedMessage ?: "Update failed"
|
||||||
IconButton(
|
} finally {
|
||||||
onClick = {
|
isLoading.value = false
|
||||||
isLoading.value = true
|
}
|
||||||
error.value = null
|
}
|
||||||
val inAt = if (editableCheckIn) {
|
|
||||||
checkInDate.value?.let { formatBookingIso(it, checkInTime.value) }
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
val outAt = checkOutDate.value?.let { formatBookingIso(it, checkOutTime.value) }
|
|
||||||
scope.launch {
|
|
||||||
try {
|
|
||||||
val api = ApiClient.create()
|
|
||||||
val response = api.updateExpectedDates(
|
|
||||||
propertyId = propertyId,
|
|
||||||
bookingId = bookingId,
|
|
||||||
body = BookingExpectedDatesRequest(
|
|
||||||
expectedCheckInAt = inAt,
|
|
||||||
expectedCheckOutAt = outAt
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if (response.isSuccessful) {
|
|
||||||
onDone()
|
|
||||||
} else {
|
|
||||||
error.value = "Update failed: ${response.code()}"
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
error.value = e.localizedMessage ?: "Update failed"
|
|
||||||
} finally {
|
|
||||||
isLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
enabled = !isLoading.value
|
|
||||||
) {
|
|
||||||
Icon(Icons.Default.Done, contentDescription = "Save")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors = TopAppBarDefaults.topAppBarColors()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
) { padding ->
|
) { padding ->
|
||||||
Column(
|
PaddedScreenColumn(padding = padding) {
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.padding(padding)
|
|
||||||
.padding(24.dp),
|
|
||||||
verticalArrangement = Arrangement.Top
|
|
||||||
) {
|
|
||||||
if (editableCheckIn) {
|
if (editableCheckIn) {
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = checkInDate.value?.let {
|
value = checkInDate.value?.let {
|
||||||
|
|||||||
@@ -3,23 +3,12 @@ package com.android.trisolarispms.ui.guest
|
|||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
|
||||||
import androidx.compose.material.icons.filled.Done
|
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
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
|
||||||
@@ -27,9 +16,10 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import com.android.trisolarispms.ui.common.PaddedScreenColumn
|
||||||
|
import com.android.trisolarispms.ui.common.SaveTopBarScaffold
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
fun GuestInfoScreen(
|
fun GuestInfoScreen(
|
||||||
propertyId: String,
|
propertyId: String,
|
||||||
guestId: String,
|
guestId: String,
|
||||||
@@ -47,31 +37,12 @@ fun GuestInfoScreen(
|
|||||||
viewModel.loadGuest(propertyId, guestId, initialPhone)
|
viewModel.loadGuest(propertyId, guestId, initialPhone)
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
SaveTopBarScaffold(
|
||||||
topBar = {
|
title = "Guest Info",
|
||||||
TopAppBar(
|
onBack = onBack,
|
||||||
title = { Text("Guest Info") },
|
onSave = { viewModel.submit(propertyId, guestId, onSave) }
|
||||||
navigationIcon = {
|
|
||||||
IconButton(onClick = onBack) {
|
|
||||||
Icon(Icons.AutoMirrored.Default.ArrowBack, contentDescription = "Back")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions = {
|
|
||||||
IconButton(onClick = { viewModel.submit(propertyId, guestId, onSave) }) {
|
|
||||||
Icon(Icons.Default.Done, contentDescription = "Save")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors = TopAppBarDefaults.topAppBarColors()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { padding ->
|
) { padding ->
|
||||||
Column(
|
PaddedScreenColumn(padding = padding) {
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.padding(padding)
|
|
||||||
.padding(24.dp),
|
|
||||||
verticalArrangement = Arrangement.Top
|
|
||||||
) {
|
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = state.phoneE164,
|
value = state.phoneE164,
|
||||||
onValueChange = viewModel::onPhoneChange,
|
onValueChange = viewModel::onPhoneChange,
|
||||||
|
|||||||
@@ -8,24 +8,17 @@ import androidx.compose.foundation.gestures.drag
|
|||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
|
||||||
import androidx.compose.material.icons.filled.Done
|
import androidx.compose.material.icons.filled.Done
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
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
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
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
|
||||||
@@ -48,9 +41,10 @@ import androidx.compose.ui.unit.IntSize
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import com.android.trisolarispms.ui.common.BackTopBarScaffold
|
||||||
|
import com.android.trisolarispms.ui.common.PaddedScreenColumn
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
fun GuestSignatureScreen(
|
fun GuestSignatureScreen(
|
||||||
propertyId: String,
|
propertyId: String,
|
||||||
guestId: String,
|
guestId: String,
|
||||||
@@ -66,43 +60,28 @@ fun GuestSignatureScreen(
|
|||||||
viewModel.reset()
|
viewModel.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
BackTopBarScaffold(
|
||||||
topBar = {
|
title = "Guest Signature",
|
||||||
TopAppBar(
|
onBack = onBack,
|
||||||
title = { Text("Guest Signature") },
|
actions = {
|
||||||
navigationIcon = {
|
IconButton(
|
||||||
IconButton(onClick = onBack) {
|
onClick = {
|
||||||
Icon(Icons.AutoMirrored.Default.ArrowBack, contentDescription = "Back")
|
val svg = buildSignatureSvg(strokes, canvasSize.value)
|
||||||
|
if (!svg.isNullOrBlank()) {
|
||||||
|
viewModel.uploadSignature(propertyId, guestId, svg, onDone)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions = {
|
enabled = strokes.isNotEmpty() && !state.isLoading
|
||||||
IconButton(
|
) {
|
||||||
onClick = {
|
if (state.isLoading) {
|
||||||
val svg = buildSignatureSvg(strokes, canvasSize.value)
|
CircularProgressIndicator(modifier = Modifier.size(18.dp), strokeWidth = 2.dp)
|
||||||
if (!svg.isNullOrBlank()) {
|
} else {
|
||||||
viewModel.uploadSignature(propertyId, guestId, svg, onDone)
|
Icon(Icons.Default.Done, contentDescription = "Upload")
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
enabled = strokes.isNotEmpty() && !state.isLoading
|
|
||||||
) {
|
|
||||||
if (state.isLoading) {
|
|
||||||
CircularProgressIndicator(modifier = Modifier.size(18.dp), strokeWidth = 2.dp)
|
|
||||||
} else {
|
|
||||||
Icon(Icons.Default.Done, contentDescription = "Upload")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors = TopAppBarDefaults.topAppBarColors()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
) { padding ->
|
) { padding ->
|
||||||
Column(
|
PaddedScreenColumn(padding = padding) {
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.padding(padding)
|
|
||||||
.padding(24.dp),
|
|
||||||
verticalArrangement = Arrangement.Top
|
|
||||||
) {
|
|
||||||
Text(
|
Text(
|
||||||
text = "Please draw the guest signature below.",
|
text = "Please draw the guest signature below.",
|
||||||
style = MaterialTheme.typography.bodyMedium
|
style = MaterialTheme.typography.bodyMedium
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import androidx.compose.foundation.clickable
|
|||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
@@ -14,14 +13,10 @@ import androidx.compose.material.icons.filled.MoreVert
|
|||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.DropdownMenu
|
import androidx.compose.material3.DropdownMenu
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
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
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
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
|
||||||
@@ -36,9 +31,10 @@ import androidx.lifecycle.viewmodel.compose.viewModel
|
|||||||
import com.android.trisolarispms.core.auth.Role
|
import com.android.trisolarispms.core.auth.Role
|
||||||
import com.android.trisolarispms.ui.property.PropertyListViewModel
|
import com.android.trisolarispms.ui.property.PropertyListViewModel
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import com.android.trisolarispms.ui.common.BackTopBarScaffold
|
||||||
|
import com.android.trisolarispms.ui.common.PaddedScreenColumn
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
fun HomeScreen(
|
fun HomeScreen(
|
||||||
userId: String?,
|
userId: String?,
|
||||||
userName: String?,
|
userName: String?,
|
||||||
@@ -78,66 +74,57 @@ fun HomeScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
BackTopBarScaffold(
|
||||||
topBar = {
|
title = "Trisolaris PMS",
|
||||||
TopAppBar(
|
onBack = {},
|
||||||
title = { Text("Trisolaris PMS") },
|
showBack = false,
|
||||||
colors = TopAppBarDefaults.topAppBarColors(),
|
actions = {
|
||||||
actions = {
|
if (isSuperAdmin) {
|
||||||
if (isSuperAdmin) {
|
IconButton(onClick = onUserDirectory) {
|
||||||
IconButton(onClick = onUserDirectory) {
|
Icon(Icons.Default.People, contentDescription = "User Directory")
|
||||||
Icon(Icons.Default.People, contentDescription = "User Directory")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IconButton(onClick = { menuExpanded = true }) {
|
|
||||||
Icon(Icons.Default.MoreVert, contentDescription = "Menu")
|
|
||||||
}
|
|
||||||
DropdownMenu(
|
|
||||||
expanded = menuExpanded,
|
|
||||||
onDismissRequest = { menuExpanded = false }
|
|
||||||
) {
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text("Add Property") },
|
|
||||||
onClick = {
|
|
||||||
menuExpanded = false
|
|
||||||
onAddProperty()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text("Logout") },
|
|
||||||
onClick = {
|
|
||||||
menuExpanded = false
|
|
||||||
onLogout()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
if (isSuperAdmin) {
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text("Update Tags") },
|
|
||||||
onClick = {
|
|
||||||
menuExpanded = false
|
|
||||||
onImageTags()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text("Modify Amenities") },
|
|
||||||
onClick = {
|
|
||||||
menuExpanded = false
|
|
||||||
onAmenities()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
IconButton(onClick = { menuExpanded = true }) {
|
||||||
|
Icon(Icons.Default.MoreVert, contentDescription = "Menu")
|
||||||
|
}
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = menuExpanded,
|
||||||
|
onDismissRequest = { menuExpanded = false }
|
||||||
|
) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text("Add Property") },
|
||||||
|
onClick = {
|
||||||
|
menuExpanded = false
|
||||||
|
onAddProperty()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text("Logout") },
|
||||||
|
onClick = {
|
||||||
|
menuExpanded = false
|
||||||
|
onLogout()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (isSuperAdmin) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text("Update Tags") },
|
||||||
|
onClick = {
|
||||||
|
menuExpanded = false
|
||||||
|
onImageTags()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text("Modify Amenities") },
|
||||||
|
onClick = {
|
||||||
|
menuExpanded = false
|
||||||
|
onAmenities()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
) { padding ->
|
) { padding ->
|
||||||
Column(
|
PaddedScreenColumn(padding = padding) {
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.padding(padding)
|
|
||||||
.padding(24.dp),
|
|
||||||
verticalArrangement = Arrangement.Top
|
|
||||||
) {
|
|
||||||
val title = if (!userName.isNullOrBlank()) "Welcome, $userName" else "Welcome"
|
val title = if (!userName.isNullOrBlank()) "Welcome, $userName" else "Welcome"
|
||||||
Text(text = title, style = MaterialTheme.typography.headlineMedium)
|
Text(text = title, style = MaterialTheme.typography.headlineMedium)
|
||||||
if (isSuperAdmin) {
|
if (isSuperAdmin) {
|
||||||
|
|||||||
@@ -3,27 +3,18 @@ package com.android.trisolarispms.ui.property
|
|||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
import androidx.compose.material3.ExposedDropdownMenuBox
|
import androidx.compose.material3.ExposedDropdownMenuBox
|
||||||
import androidx.compose.material3.ExposedDropdownMenuDefaults
|
import androidx.compose.material3.ExposedDropdownMenuDefaults
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
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
|
||||||
@@ -44,6 +35,8 @@ import kotlinx.coroutines.Job
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
import com.android.trisolarispms.ui.common.BackTopBarScaffold
|
||||||
|
import com.android.trisolarispms.ui.common.PaddedScreenColumn
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@@ -70,120 +63,105 @@ fun AddPropertyScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
BackTopBarScaffold(
|
||||||
topBar = {
|
title = "Add Property",
|
||||||
TopAppBar(
|
onBack = onBack
|
||||||
title = { Text("Add Property") },
|
|
||||||
navigationIcon = {
|
|
||||||
IconButton(onClick = onBack) {
|
|
||||||
Icon(Icons.Default.ArrowBack, contentDescription = "Back")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors = TopAppBarDefaults.topAppBarColors()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { padding ->
|
) { padding ->
|
||||||
Column(
|
PaddedScreenColumn(padding = padding) {
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.padding(padding)
|
|
||||||
.padding(24.dp),
|
|
||||||
verticalArrangement = Arrangement.Top
|
|
||||||
) {
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
ExposedDropdownMenuBox(
|
ExposedDropdownMenuBox(
|
||||||
expanded = expanded,
|
|
||||||
onExpandedChange = { expanded = it }
|
|
||||||
) {
|
|
||||||
OutlinedTextField(
|
|
||||||
value = state.name,
|
|
||||||
onValueChange = { value ->
|
|
||||||
viewModel.onNameChange(value)
|
|
||||||
val query = value.trim()
|
|
||||||
searchJob?.cancel()
|
|
||||||
placesError = null
|
|
||||||
if (query.length >= 4) {
|
|
||||||
searchJob = coroutineScope.launch {
|
|
||||||
delay(300)
|
|
||||||
isSearching = true
|
|
||||||
try {
|
|
||||||
predictions = PlacesRestClient.autocomplete(
|
|
||||||
apiKey = apiKey,
|
|
||||||
input = query,
|
|
||||||
sessionToken = sessionToken,
|
|
||||||
regionCode = "IN"
|
|
||||||
)
|
|
||||||
expanded = predictions.isNotEmpty()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
predictions = emptyList()
|
|
||||||
expanded = false
|
|
||||||
placesError = e.localizedMessage ?: "Places search failed"
|
|
||||||
} finally {
|
|
||||||
isSearching = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
predictions = emptyList()
|
|
||||||
expanded = false
|
|
||||||
isSearching = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
label = { Text("Name") },
|
|
||||||
isError = state.nameError != null,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.menuAnchor(),
|
|
||||||
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }
|
|
||||||
)
|
|
||||||
ExposedDropdownMenu(
|
|
||||||
expanded = expanded,
|
expanded = expanded,
|
||||||
onDismissRequest = { expanded = false }
|
onExpandedChange = { expanded = it }
|
||||||
) {
|
) {
|
||||||
predictions.forEach { prediction ->
|
OutlinedTextField(
|
||||||
DropdownMenuItem(
|
value = state.name,
|
||||||
text = { Text(prediction.text) },
|
onValueChange = { value ->
|
||||||
onClick = {
|
viewModel.onNameChange(value)
|
||||||
expanded = false
|
val query = value.trim()
|
||||||
predictions = emptyList()
|
searchJob?.cancel()
|
||||||
coroutineScope.launch {
|
placesError = null
|
||||||
|
if (query.length >= 4) {
|
||||||
|
searchJob = coroutineScope.launch {
|
||||||
|
delay(300)
|
||||||
|
isSearching = true
|
||||||
try {
|
try {
|
||||||
val details = PlacesRestClient.placeDetails(
|
predictions = PlacesRestClient.autocomplete(
|
||||||
apiKey = apiKey,
|
apiKey = apiKey,
|
||||||
placeId = prediction.placeId,
|
input = query,
|
||||||
sessionToken = sessionToken
|
sessionToken = sessionToken,
|
||||||
|
regionCode = "IN"
|
||||||
)
|
)
|
||||||
viewModel.applyPlace(details.name, details.address)
|
expanded = predictions.isNotEmpty()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
placesError = e.localizedMessage ?: "Place lookup failed"
|
predictions = emptyList()
|
||||||
|
expanded = false
|
||||||
|
placesError = e.localizedMessage ?: "Places search failed"
|
||||||
|
} finally {
|
||||||
|
isSearching = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
predictions = emptyList()
|
||||||
|
expanded = false
|
||||||
|
isSearching = false
|
||||||
}
|
}
|
||||||
)
|
},
|
||||||
|
label = { Text("Name") },
|
||||||
|
isError = state.nameError != null,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.menuAnchor(),
|
||||||
|
trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }
|
||||||
|
)
|
||||||
|
ExposedDropdownMenu(
|
||||||
|
expanded = expanded,
|
||||||
|
onDismissRequest = { expanded = false }
|
||||||
|
) {
|
||||||
|
predictions.forEach { prediction ->
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(prediction.text) },
|
||||||
|
onClick = {
|
||||||
|
expanded = false
|
||||||
|
predictions = emptyList()
|
||||||
|
coroutineScope.launch {
|
||||||
|
try {
|
||||||
|
val details = PlacesRestClient.placeDetails(
|
||||||
|
apiKey = apiKey,
|
||||||
|
placeId = prediction.placeId,
|
||||||
|
sessionToken = sessionToken
|
||||||
|
)
|
||||||
|
viewModel.applyPlace(details.name, details.address)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
placesError = e.localizedMessage ?: "Place lookup failed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
state.nameError?.let {
|
||||||
state.nameError?.let {
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Text(text = it, color = MaterialTheme.colorScheme.error)
|
||||||
Text(text = it, color = MaterialTheme.colorScheme.error)
|
}
|
||||||
}
|
if (isSearching) {
|
||||||
if (isSearching) {
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Text(text = "Searching…", style = MaterialTheme.typography.bodySmall)
|
||||||
Text(text = "Searching…", style = MaterialTheme.typography.bodySmall)
|
}
|
||||||
}
|
placesError?.let {
|
||||||
placesError?.let {
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Text(text = it, color = MaterialTheme.colorScheme.error)
|
||||||
Text(text = it, color = MaterialTheme.colorScheme.error)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = state.addressText,
|
value = state.addressText,
|
||||||
onValueChange = viewModel::onAddressChange,
|
onValueChange = viewModel::onAddressChange,
|
||||||
label = { Text("Address") },
|
label = { Text("Address") },
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
|
||||||
|
|||||||
@@ -4,27 +4,19 @@ import androidx.compose.foundation.clickable
|
|||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
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.filled.ArrowBack
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.android.trisolarispms.ui.common.BackTopBarScaffold
|
||||||
|
import com.android.trisolarispms.ui.common.PaddedScreenColumn
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
fun PropertyHomeScreen(
|
fun PropertyHomeScreen(
|
||||||
propertyId: String,
|
propertyId: String,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
@@ -33,26 +25,11 @@ fun PropertyHomeScreen(
|
|||||||
onRoomTypes: () -> Unit,
|
onRoomTypes: () -> Unit,
|
||||||
canManageRooms: Boolean
|
canManageRooms: Boolean
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
BackTopBarScaffold(
|
||||||
topBar = {
|
title = "Property",
|
||||||
TopAppBar(
|
onBack = onBack
|
||||||
title = { Text("Property") },
|
|
||||||
navigationIcon = {
|
|
||||||
IconButton(onClick = onBack) {
|
|
||||||
Icon(Icons.Default.ArrowBack, contentDescription = "Back")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors = TopAppBarDefaults.topAppBarColors()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { padding ->
|
) { padding ->
|
||||||
Column(
|
PaddedScreenColumn(padding = padding) {
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.padding(padding)
|
|
||||||
.padding(24.dp),
|
|
||||||
verticalArrangement = Arrangement.Top
|
|
||||||
) {
|
|
||||||
PropertyTile(title = "Checked-in Rooms", subtitle = "Active stays", onClick = onActiveStays)
|
PropertyTile(title = "Checked-in Rooms", subtitle = "Active stays", onClick = onActiveStays)
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
PropertyTile(title = "Available Rooms", subtitle = "Room list", onClick = onRooms)
|
PropertyTile(title = "Available Rooms", subtitle = "Room list", onClick = onRooms)
|
||||||
|
|||||||
@@ -16,19 +16,14 @@ import androidx.compose.foundation.verticalScroll
|
|||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
|
||||||
import androidx.compose.material.icons.filled.Delete
|
import androidx.compose.material.icons.filled.Delete
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
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
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -49,9 +44,9 @@ import com.android.trisolarispms.BuildConfig
|
|||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import com.android.trisolarispms.ui.common.BackTopBarScaffold
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
fun RazorpayQrScreen(
|
fun RazorpayQrScreen(
|
||||||
propertyId: String,
|
propertyId: String,
|
||||||
bookingId: String,
|
bookingId: String,
|
||||||
@@ -93,23 +88,14 @@ fun RazorpayQrScreen(
|
|||||||
exitAndRefresh()
|
exitAndRefresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
BackTopBarScaffold(
|
||||||
topBar = {
|
title = "Generate Payment Links | QR",
|
||||||
TopAppBar(
|
onBack = {
|
||||||
title = { Text("Generate Payment Links | QR") },
|
if (isViewingQr) {
|
||||||
navigationIcon = {
|
exitAndRefresh()
|
||||||
IconButton(onClick = {
|
} else {
|
||||||
if (isViewingQr) {
|
onBack()
|
||||||
exitAndRefresh()
|
}
|
||||||
} else {
|
|
||||||
onBack()
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
Icon(Icons.AutoMirrored.Default.ArrowBack, contentDescription = "Back")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors = TopAppBarDefaults.topAppBarColors()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
) { padding ->
|
) { padding ->
|
||||||
if (state.isCredited) {
|
if (state.isCredited) {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package com.android.trisolarispms.ui.roomstay
|
|||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
@@ -13,7 +12,6 @@ import androidx.compose.foundation.lazy.grid.items
|
|||||||
import androidx.compose.foundation.combinedClickable
|
import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Add
|
import androidx.compose.material.icons.filled.Add
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
|
||||||
import androidx.compose.material.icons.filled.People
|
import androidx.compose.material.icons.filled.People
|
||||||
import androidx.compose.material.icons.filled.MeetingRoom
|
import androidx.compose.material.icons.filled.MeetingRoom
|
||||||
import androidx.compose.material.icons.filled.Payment
|
import androidx.compose.material.icons.filled.Payment
|
||||||
@@ -23,15 +21,11 @@ import androidx.compose.material3.Card
|
|||||||
import androidx.compose.material3.CardDefaults
|
import androidx.compose.material3.CardDefaults
|
||||||
import androidx.compose.material3.FloatingActionButton
|
import androidx.compose.material3.FloatingActionButton
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
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
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.material3.LinearProgressIndicator
|
import androidx.compose.material3.LinearProgressIndicator
|
||||||
@@ -43,11 +37,12 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import com.android.trisolarispms.data.api.model.BookingListItem
|
import com.android.trisolarispms.data.api.model.BookingListItem
|
||||||
|
import com.android.trisolarispms.ui.common.BackTopBarScaffold
|
||||||
|
import com.android.trisolarispms.ui.common.PaddedScreenColumn
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.time.OffsetDateTime
|
import java.time.OffsetDateTime
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
fun ActiveRoomStaysScreen(
|
fun ActiveRoomStaysScreen(
|
||||||
propertyId: String,
|
propertyId: String,
|
||||||
propertyName: String,
|
propertyName: String,
|
||||||
@@ -73,37 +68,27 @@ fun ActiveRoomStaysScreen(
|
|||||||
viewModel.load(propertyId)
|
viewModel.load(propertyId)
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
BackTopBarScaffold(
|
||||||
topBar = {
|
title = propertyName,
|
||||||
TopAppBar(
|
onBack = onBack,
|
||||||
title = { Text(propertyName) },
|
showBack = showBack,
|
||||||
navigationIcon = {
|
actions = {
|
||||||
if (showBack) {
|
IconButton(onClick = onViewRooms) {
|
||||||
IconButton(onClick = onBack) {
|
Icon(Icons.Default.MeetingRoom, contentDescription = "Available Rooms")
|
||||||
Icon(Icons.Default.ArrowBack, contentDescription = "Back")
|
}
|
||||||
}
|
IconButton(onClick = onOpenSettings) {
|
||||||
}
|
Icon(Icons.Default.Settings, contentDescription = "Settings")
|
||||||
},
|
}
|
||||||
actions = {
|
if (showRazorpaySettings) {
|
||||||
IconButton(onClick = onViewRooms) {
|
IconButton(onClick = onRazorpaySettings) {
|
||||||
Icon(Icons.Default.MeetingRoom, contentDescription = "Available Rooms")
|
Icon(Icons.Default.Payment, contentDescription = "Razorpay Settings")
|
||||||
}
|
}
|
||||||
IconButton(onClick = onOpenSettings) {
|
}
|
||||||
Icon(Icons.Default.Settings, contentDescription = "Settings")
|
if (showUserAdmin) {
|
||||||
}
|
IconButton(onClick = onUserAdmin) {
|
||||||
if (showRazorpaySettings) {
|
Icon(Icons.Default.People, contentDescription = "Property Users")
|
||||||
IconButton(onClick = onRazorpaySettings) {
|
}
|
||||||
Icon(Icons.Default.Payment, contentDescription = "Razorpay Settings")
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
if (showUserAdmin) {
|
|
||||||
IconButton(onClick = onUserAdmin) {
|
|
||||||
Icon(Icons.Default.People, contentDescription = "Property Users")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors = TopAppBarDefaults.topAppBarColors()
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
if (canCreateBooking) {
|
if (canCreateBooking) {
|
||||||
@@ -113,13 +98,7 @@ fun ActiveRoomStaysScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
) { padding ->
|
) { padding ->
|
||||||
Column(
|
PaddedScreenColumn(padding = padding) {
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.padding(padding)
|
|
||||||
.padding(24.dp),
|
|
||||||
verticalArrangement = Arrangement.Top
|
|
||||||
) {
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
if (state.isLoading) {
|
if (state.isLoading) {
|
||||||
|
|||||||
@@ -5,25 +5,16 @@ import androidx.compose.foundation.layout.Arrangement
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
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.automirrored.filled.ArrowBack
|
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
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
|
||||||
@@ -36,9 +27,10 @@ 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
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import com.android.trisolarispms.ui.common.BackTopBarScaffold
|
||||||
|
import com.android.trisolarispms.ui.common.PaddedScreenColumn
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
fun ManageRoomStayRatesScreen(
|
fun ManageRoomStayRatesScreen(
|
||||||
propertyId: String,
|
propertyId: String,
|
||||||
bookingId: String,
|
bookingId: String,
|
||||||
@@ -57,18 +49,9 @@ fun ManageRoomStayRatesScreen(
|
|||||||
viewModel.setItems(selectedRooms)
|
viewModel.setItems(selectedRooms)
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
BackTopBarScaffold(
|
||||||
topBar = {
|
title = "Selected Rooms",
|
||||||
TopAppBar(
|
onBack = onBack,
|
||||||
title = { Text("Selected Rooms") },
|
|
||||||
navigationIcon = {
|
|
||||||
IconButton(onClick = onBack) {
|
|
||||||
Icon(Icons.AutoMirrored.Default.ArrowBack, contentDescription = "Back")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors = TopAppBarDefaults.topAppBarColors()
|
|
||||||
)
|
|
||||||
},
|
|
||||||
bottomBar = {
|
bottomBar = {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -102,16 +85,13 @@ fun ManageRoomStayRatesScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
) { padding ->
|
) { padding ->
|
||||||
Column(
|
PaddedScreenColumn(
|
||||||
modifier = Modifier
|
padding = padding,
|
||||||
.fillMaxSize()
|
contentPadding = 16.dp
|
||||||
.padding(padding)
|
|
||||||
.padding(16.dp),
|
|
||||||
verticalArrangement = Arrangement.Top
|
|
||||||
) {
|
) {
|
||||||
if (state.items.isEmpty()) {
|
if (state.items.isEmpty()) {
|
||||||
Text(text = "No rooms selected.")
|
Text(text = "No rooms selected.")
|
||||||
return@Column
|
return@PaddedScreenColumn
|
||||||
}
|
}
|
||||||
state.items.forEach { item ->
|
state.items.forEach { item ->
|
||||||
Row(
|
Row(
|
||||||
|
|||||||
@@ -17,18 +17,10 @@ import androidx.compose.foundation.lazy.items
|
|||||||
import androidx.compose.foundation.lazy.grid.GridCells
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
import androidx.compose.foundation.lazy.grid.items
|
import androidx.compose.foundation.lazy.grid.items
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
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
|
||||||
@@ -41,11 +33,13 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import com.android.trisolarispms.data.api.model.RoomAvailableRateResponse
|
import com.android.trisolarispms.data.api.model.RoomAvailableRateResponse
|
||||||
|
import com.android.trisolarispms.ui.common.BackTopBarScaffold
|
||||||
|
import com.android.trisolarispms.ui.common.LoadingAndError
|
||||||
|
import com.android.trisolarispms.ui.common.PaddedScreenColumn
|
||||||
import java.time.OffsetDateTime
|
import java.time.OffsetDateTime
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
fun ManageRoomStaySelectScreen(
|
fun ManageRoomStaySelectScreen(
|
||||||
propertyId: String,
|
propertyId: String,
|
||||||
bookingFromAt: String,
|
bookingFromAt: String,
|
||||||
@@ -76,18 +70,9 @@ fun ManageRoomStaySelectScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
BackTopBarScaffold(
|
||||||
topBar = {
|
title = "Select Rooms",
|
||||||
TopAppBar(
|
onBack = onBack,
|
||||||
title = { Text("Select Rooms") },
|
|
||||||
navigationIcon = {
|
|
||||||
IconButton(onClick = onBack) {
|
|
||||||
Icon(Icons.AutoMirrored.Default.ArrowBack, contentDescription = "Back")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors = TopAppBarDefaults.topAppBarColors()
|
|
||||||
)
|
|
||||||
},
|
|
||||||
bottomBar = {
|
bottomBar = {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -112,23 +97,14 @@ fun ManageRoomStaySelectScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
) { padding ->
|
) { padding ->
|
||||||
Column(
|
PaddedScreenColumn(
|
||||||
modifier = Modifier
|
padding = padding,
|
||||||
.fillMaxSize()
|
contentPadding = 16.dp
|
||||||
.padding(padding)
|
|
||||||
.padding(16.dp)
|
|
||||||
) {
|
) {
|
||||||
if (state.isLoading) {
|
LoadingAndError(isLoading = state.isLoading, error = state.error)
|
||||||
CircularProgressIndicator()
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
|
||||||
}
|
|
||||||
state.error?.let {
|
|
||||||
Text(text = it, color = MaterialTheme.colorScheme.error)
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
|
||||||
}
|
|
||||||
if (fromDate == null || fallbackToDate == null) {
|
if (fromDate == null || fallbackToDate == null) {
|
||||||
Text(text = "Booking dates not available.", color = MaterialTheme.colorScheme.error)
|
Text(text = "Booking dates not available.", color = MaterialTheme.colorScheme.error)
|
||||||
return@Column
|
return@PaddedScreenColumn
|
||||||
}
|
}
|
||||||
LazyVerticalGrid(
|
LazyVerticalGrid(
|
||||||
columns = GridCells.Fixed(2),
|
columns = GridCells.Fixed(2),
|
||||||
|
|||||||
@@ -16,22 +16,16 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
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.Delete
|
import androidx.compose.material.icons.filled.Delete
|
||||||
import androidx.compose.material.icons.filled.Done
|
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.Checkbox
|
import androidx.compose.material3.Checkbox
|
||||||
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
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
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
|
||||||
@@ -45,9 +39,9 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import com.android.trisolarispms.data.api.core.ApiConstants
|
import com.android.trisolarispms.data.api.core.ApiConstants
|
||||||
|
import com.android.trisolarispms.ui.common.SaveTopBarScaffold
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
fun RoomTypeFormScreen(
|
fun RoomTypeFormScreen(
|
||||||
title: String,
|
title: String,
|
||||||
propertyId: String,
|
propertyId: String,
|
||||||
@@ -68,27 +62,16 @@ fun RoomTypeFormScreen(
|
|||||||
amenityViewModel.load()
|
amenityViewModel.load()
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
SaveTopBarScaffold(
|
||||||
topBar = {
|
title = title,
|
||||||
TopAppBar(
|
onBack = onBack,
|
||||||
title = { Text(title) },
|
onSave = onSave,
|
||||||
navigationIcon = {
|
actions = {
|
||||||
IconButton(onClick = onBack) {
|
if (onDelete != null) {
|
||||||
Icon(Icons.Default.ArrowBack, contentDescription = "Back")
|
IconButton(onClick = onDelete) {
|
||||||
}
|
Icon(Icons.Default.Delete, contentDescription = "Delete Room Type")
|
||||||
},
|
}
|
||||||
actions = {
|
}
|
||||||
IconButton(onClick = onSave) {
|
|
||||||
Icon(Icons.Default.Done, contentDescription = "Save")
|
|
||||||
}
|
|
||||||
if (onDelete != null) {
|
|
||||||
IconButton(onClick = onDelete) {
|
|
||||||
Icon(Icons.Default.Delete, contentDescription = "Delete Room Type")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors = TopAppBarDefaults.topAppBarColors()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
) { padding ->
|
) { padding ->
|
||||||
Column(
|
Column(
|
||||||
|
|||||||
@@ -3,36 +3,30 @@ package com.android.trisolarispms.ui.users
|
|||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
|
||||||
import androidx.compose.material.icons.filled.Search
|
import androidx.compose.material.icons.filled.Search
|
||||||
import androidx.compose.material.icons.filled.VpnKey
|
import androidx.compose.material.icons.filled.VpnKey
|
||||||
import androidx.compose.material3.AlertDialog
|
import androidx.compose.material3.AlertDialog
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
|
||||||
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
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.android.trisolarispms.ui.common.BackTopBarScaffold
|
||||||
|
import com.android.trisolarispms.ui.common.LoadingAndError
|
||||||
|
import com.android.trisolarispms.ui.common.PaddedScreenColumn
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
fun UserDirectoryScaffold(
|
fun UserDirectoryScaffold(
|
||||||
title: String,
|
title: String,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
@@ -47,48 +41,29 @@ fun UserDirectoryScaffold(
|
|||||||
beforeListContent: @Composable () -> Unit = {},
|
beforeListContent: @Composable () -> Unit = {},
|
||||||
itemContent: @Composable (PropertyUserUi) -> Unit
|
itemContent: @Composable (PropertyUserUi) -> Unit
|
||||||
) {
|
) {
|
||||||
Scaffold(
|
BackTopBarScaffold(
|
||||||
topBar = {
|
title = title,
|
||||||
TopAppBar(
|
onBack = onBack,
|
||||||
title = { Text(title) },
|
actions = {
|
||||||
navigationIcon = {
|
if (showAccessCodeIcon) {
|
||||||
IconButton(onClick = onBack) {
|
IconButton(onClick = onAccessCodeClick) {
|
||||||
Icon(Icons.AutoMirrored.Default.ArrowBack, contentDescription = "Back")
|
Icon(Icons.Default.VpnKey, contentDescription = "Generate access code")
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
actions = {
|
if (showSearchIcon) {
|
||||||
if (showAccessCodeIcon) {
|
IconButton(onClick = onSearchClick) {
|
||||||
IconButton(onClick = onAccessCodeClick) {
|
Icon(Icons.Default.Search, contentDescription = "Search users")
|
||||||
Icon(Icons.Default.VpnKey, contentDescription = "Generate access code")
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (showSearchIcon) {
|
|
||||||
IconButton(onClick = onSearchClick) {
|
|
||||||
Icon(Icons.Default.Search, contentDescription = "Search users")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors = TopAppBarDefaults.topAppBarColors()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
) { padding ->
|
) { padding ->
|
||||||
Column(
|
PaddedScreenColumn(
|
||||||
modifier = Modifier
|
padding = padding,
|
||||||
.fillMaxSize()
|
contentPadding = 16.dp
|
||||||
.padding(padding)
|
|
||||||
.padding(16.dp),
|
|
||||||
verticalArrangement = Arrangement.Top
|
|
||||||
) {
|
) {
|
||||||
beforeListContent()
|
beforeListContent()
|
||||||
|
|
||||||
if (isLoading) {
|
LoadingAndError(isLoading = isLoading, error = error)
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
|
||||||
CircularProgressIndicator()
|
|
||||||
}
|
|
||||||
error?.let {
|
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
|
||||||
Text(text = it, color = MaterialTheme.colorScheme.error)
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
LazyColumn(verticalArrangement = Arrangement.spacedBy(12.dp)) {
|
LazyColumn(verticalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user