guest details: improve room stays ui
This commit is contained in:
@@ -273,15 +273,6 @@ class MainActivity : ComponentActivity() {
|
|||||||
bookingId = booking.id.orEmpty()
|
bookingId = booking.id.orEmpty()
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onExtendBooking = { booking ->
|
|
||||||
route.value = AppRoute.BookingExpectedDates(
|
|
||||||
propertyId = currentRoute.propertyId,
|
|
||||||
bookingId = booking.id.orEmpty(),
|
|
||||||
status = booking.status,
|
|
||||||
expectedCheckInAt = booking.expectedCheckInAt,
|
|
||||||
expectedCheckOutAt = booking.expectedCheckOutAt
|
|
||||||
)
|
|
||||||
},
|
|
||||||
onOpenBookingDetails = { booking ->
|
onOpenBookingDetails = { booking ->
|
||||||
route.value = AppRoute.BookingDetailsTabs(
|
route.value = AppRoute.BookingDetailsTabs(
|
||||||
propertyId = currentRoute.propertyId,
|
propertyId = currentRoute.propertyId,
|
||||||
@@ -413,6 +404,22 @@ class MainActivity : ComponentActivity() {
|
|||||||
currentRoute.propertyId,
|
currentRoute.propertyId,
|
||||||
selectedPropertyName.value ?: "Property"
|
selectedPropertyName.value ?: "Property"
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
onEditCheckout = { expectedCheckInAt, expectedCheckOutAt ->
|
||||||
|
route.value = AppRoute.BookingExpectedDates(
|
||||||
|
propertyId = currentRoute.propertyId,
|
||||||
|
bookingId = currentRoute.bookingId,
|
||||||
|
status = "CHECKED_IN",
|
||||||
|
expectedCheckInAt = expectedCheckInAt,
|
||||||
|
expectedCheckOutAt = expectedCheckOutAt
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onEditSignature = { guestId ->
|
||||||
|
route.value = AppRoute.GuestSignature(
|
||||||
|
currentRoute.propertyId,
|
||||||
|
currentRoute.bookingId,
|
||||||
|
guestId
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
is AppRoute.Rooms -> RoomsScreen(
|
is AppRoute.Rooms -> RoomsScreen(
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ data class BookingListItem(
|
|||||||
val totalGuestCount: Int? = null,
|
val totalGuestCount: Int? = null,
|
||||||
val expectedGuestCount: Int? = null,
|
val expectedGuestCount: Int? = null,
|
||||||
val notes: String? = null
|
val notes: String? = null
|
||||||
|
,
|
||||||
|
val pending: Long? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
data class BookingBulkCheckInRequest(
|
data class BookingBulkCheckInRequest(
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ fun ActiveRoomStaysScreen(
|
|||||||
onCreateBooking: () -> Unit,
|
onCreateBooking: () -> Unit,
|
||||||
onManageRoomStay: (BookingListItem) -> Unit,
|
onManageRoomStay: (BookingListItem) -> Unit,
|
||||||
onViewBookingStays: (BookingListItem) -> Unit,
|
onViewBookingStays: (BookingListItem) -> Unit,
|
||||||
onExtendBooking: (BookingListItem) -> Unit,
|
|
||||||
onOpenBookingDetails: (BookingListItem) -> Unit,
|
onOpenBookingDetails: (BookingListItem) -> Unit,
|
||||||
viewModel: ActiveRoomStaysViewModel = viewModel()
|
viewModel: ActiveRoomStaysViewModel = viewModel()
|
||||||
) {
|
) {
|
||||||
@@ -151,14 +150,6 @@ fun ActiveRoomStaysScreen(
|
|||||||
TextButton(onClick = { selectedBooking.value = null }) {
|
TextButton(onClick = { selectedBooking.value = null }) {
|
||||||
Text("Add photos")
|
Text("Add photos")
|
||||||
}
|
}
|
||||||
TextButton(
|
|
||||||
onClick = {
|
|
||||||
selectedBooking.value = null
|
|
||||||
onExtendBooking(booking)
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
Text("Extend checkout")
|
|
||||||
}
|
|
||||||
TextButton(onClick = { selectedBooking.value = null }) {
|
TextButton(onClick = { selectedBooking.value = null }) {
|
||||||
Text("Checkout")
|
Text("Checkout")
|
||||||
}
|
}
|
||||||
@@ -221,6 +212,15 @@ private fun CheckedInBookingCard(
|
|||||||
Spacer(modifier = Modifier.height(6.dp))
|
Spacer(modifier = Modifier.height(6.dp))
|
||||||
Text(text = notes, style = MaterialTheme.typography.bodySmall)
|
Text(text = notes, style = MaterialTheme.typography.bodySmall)
|
||||||
}
|
}
|
||||||
|
val pending = booking.pending
|
||||||
|
if (pending != null && pending > 0) {
|
||||||
|
Spacer(modifier = Modifier.height(6.dp))
|
||||||
|
Text(
|
||||||
|
text = "₹$pending",
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.error
|
||||||
|
)
|
||||||
|
}
|
||||||
val checkInAt = booking.checkInAt?.takeIf { it.isNotBlank() }
|
val checkInAt = booking.checkInAt?.takeIf { it.isNotBlank() }
|
||||||
val checkOutAt = booking.expectedCheckOutAt?.takeIf { it.isNotBlank() }
|
val checkOutAt = booking.expectedCheckOutAt?.takeIf { it.isNotBlank() }
|
||||||
if (checkInAt != null && checkOutAt != null) {
|
if (checkInAt != null && checkOutAt != null) {
|
||||||
|
|||||||
@@ -3,60 +3,60 @@ package com.android.trisolarispms.ui.roomstay
|
|||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
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.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.foundation.pager.HorizontalPager
|
||||||
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
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.automirrored.filled.ArrowBack
|
||||||
|
import androidx.compose.material.icons.filled.Edit
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.CardDefaults
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
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
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Card
|
|
||||||
import androidx.compose.material3.CardDefaults
|
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Tab
|
import androidx.compose.material3.Tab
|
||||||
import androidx.compose.material3.TabRow
|
import androidx.compose.material3.TabRow
|
||||||
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.foundation.pager.HorizontalPager
|
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
|
||||||
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.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
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.layout.ColumnScope
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import com.android.trisolarispms.data.api.model.BookingDetailsResponse
|
|
||||||
import com.android.trisolarispms.data.api.FirebaseAuthTokenProvider
|
|
||||||
import com.android.trisolarispms.data.api.ApiConstants
|
|
||||||
import com.google.firebase.auth.FirebaseAuth
|
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import coil.decode.SvgDecoder
|
import coil.decode.SvgDecoder
|
||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
|
import com.android.trisolarispms.data.api.ApiConstants
|
||||||
|
import com.android.trisolarispms.data.api.FirebaseAuthTokenProvider
|
||||||
|
import com.android.trisolarispms.data.api.model.BookingDetailsResponse
|
||||||
|
import com.google.firebase.auth.FirebaseAuth
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import okhttp3.Interceptor
|
import okhttp3.Interceptor
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import java.time.OffsetDateTime
|
import java.time.OffsetDateTime
|
||||||
import java.time.ZoneId
|
import java.time.ZoneId
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@@ -65,6 +65,8 @@ fun BookingDetailsTabsScreen(
|
|||||||
bookingId: String,
|
bookingId: String,
|
||||||
guestId: String?,
|
guestId: String?,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
|
onEditCheckout: (String?, String?) -> Unit,
|
||||||
|
onEditSignature: (String) -> Unit,
|
||||||
staysViewModel: BookingRoomStaysViewModel = viewModel(),
|
staysViewModel: BookingRoomStaysViewModel = viewModel(),
|
||||||
detailsViewModel: BookingDetailsViewModel = viewModel()
|
detailsViewModel: BookingDetailsViewModel = viewModel()
|
||||||
) {
|
) {
|
||||||
@@ -117,13 +119,15 @@ fun BookingDetailsTabsScreen(
|
|||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
) { page ->
|
) { page ->
|
||||||
when (page) {
|
when (page) {
|
||||||
0 -> GuestInfoTabContent(
|
0 -> GuestInfoTabContent(
|
||||||
propertyId = propertyId,
|
propertyId = propertyId,
|
||||||
details = detailsState.details,
|
details = detailsState.details,
|
||||||
guestId = guestId,
|
guestId = guestId,
|
||||||
isLoading = detailsState.isLoading,
|
isLoading = detailsState.isLoading,
|
||||||
error = detailsState.error
|
error = detailsState.error,
|
||||||
)
|
onEditCheckout = onEditCheckout,
|
||||||
|
onEditSignature = onEditSignature
|
||||||
|
)
|
||||||
1 -> BookingRoomStaysTabContent(staysState, staysViewModel)
|
1 -> BookingRoomStaysTabContent(staysState, staysViewModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,7 +141,9 @@ private fun GuestInfoTabContent(
|
|||||||
details: BookingDetailsResponse?,
|
details: BookingDetailsResponse?,
|
||||||
guestId: String?,
|
guestId: String?,
|
||||||
isLoading: Boolean,
|
isLoading: Boolean,
|
||||||
error: String?
|
error: String?,
|
||||||
|
onEditCheckout: (String?, String?) -> Unit,
|
||||||
|
onEditSignature: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
val displayZone = remember { ZoneId.of("Asia/Kolkata") }
|
val displayZone = remember { ZoneId.of("Asia/Kolkata") }
|
||||||
val dateFormatter = remember { DateTimeFormatter.ofPattern("dd/MM/yyyy") }
|
val dateFormatter = remember { DateTimeFormatter.ofPattern("dd/MM/yyyy") }
|
||||||
@@ -158,14 +164,13 @@ private fun GuestInfoTabContent(
|
|||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
}
|
}
|
||||||
SectionCard(title = "Details") {
|
SectionCard(title = "Details") {
|
||||||
GuestDetailRow(label = "Name", value = details?.guestName.orEmpty())
|
GuestDetailRow(label = "Name", value = details?.guestName)
|
||||||
GuestDetailRow(label = "Address", value = details?.guestAddressText.orEmpty())
|
GuestDetailRow(label = "Address", value = details?.guestAddressText)
|
||||||
GuestDetailRow(label = "Phone number", value = details?.guestPhone.orEmpty())
|
GuestDetailRow(label = "Phone number", value = details?.guestPhone)
|
||||||
GuestDetailRow(label = "Coming From", value = details?.fromCity.orEmpty())
|
GuestDetailRow(label = "Coming From", value = details?.fromCity)
|
||||||
GuestDetailRow(label = "Going To", value = details?.toCity.orEmpty())
|
GuestDetailRow(label = "Going To", value = details?.toCity)
|
||||||
GuestDetailRow(label = "Relation", value = details?.memberRelation.orEmpty())
|
GuestDetailRow(label = "Relation", value = details?.memberRelation)
|
||||||
GuestDetailRow(label = "Mode of transport", value = details?.transportMode.orEmpty())
|
GuestDetailRow(label = "Mode of transport", value = details?.transportMode)
|
||||||
GuestDetailRow(label = "Vehicle numbers", value = "")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val checkIn = details?.checkInAt ?: details?.expectedCheckInAt
|
val checkIn = details?.checkInAt ?: details?.expectedCheckInAt
|
||||||
@@ -175,55 +180,71 @@ private fun GuestInfoTabContent(
|
|||||||
val parsed = runCatching { OffsetDateTime.parse(checkIn).atZoneSameInstant(displayZone) }.getOrNull()
|
val parsed = runCatching { OffsetDateTime.parse(checkIn).atZoneSameInstant(displayZone) }.getOrNull()
|
||||||
GuestDetailRow(
|
GuestDetailRow(
|
||||||
label = "Check In Time",
|
label = "Check In Time",
|
||||||
value = parsed?.let { "${it.format(dateFormatter)} ${it.format(timeFormatter)}" }.orEmpty()
|
value = parsed?.let { "${it.format(dateFormatter)} ${it.format(timeFormatter)}" }
|
||||||
)
|
)
|
||||||
} else {
|
|
||||||
GuestDetailRow(label = "Check In Time", value = "")
|
|
||||||
}
|
}
|
||||||
if (!checkOut.isNullOrBlank()) {
|
if (!checkOut.isNullOrBlank()) {
|
||||||
val parsed = runCatching { OffsetDateTime.parse(checkOut).atZoneSameInstant(displayZone) }.getOrNull()
|
val parsed = runCatching { OffsetDateTime.parse(checkOut).atZoneSameInstant(displayZone) }.getOrNull()
|
||||||
GuestDetailRow(
|
Row(
|
||||||
label = "Estimated Check Out Time",
|
modifier = Modifier.fillMaxWidth(),
|
||||||
value = parsed?.let { "${it.format(dateFormatter)} ${it.format(timeFormatter)}" }.orEmpty()
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
)
|
verticalAlignment = Alignment.CenterVertically
|
||||||
} else {
|
) {
|
||||||
GuestDetailRow(label = "Estimated Check Out Time", value = "")
|
Column(modifier = Modifier.weight(1f)) {
|
||||||
|
GuestDetailRow(
|
||||||
|
label = "Estimated Check Out Time",
|
||||||
|
value = parsed?.let { "${it.format(dateFormatter)} ${it.format(timeFormatter)}" }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
IconButton(
|
||||||
|
onClick = {
|
||||||
|
onEditCheckout(details?.expectedCheckInAt, details?.expectedCheckOutAt)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Icon(Icons.Default.Edit, contentDescription = "Edit checkout")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
GuestDetailRow(
|
GuestDetailRow(
|
||||||
label = "Rooms Booked",
|
label = "Rooms Booked",
|
||||||
value = details?.roomNumbers?.takeIf { it.isNotEmpty() }?.joinToString(", ").orEmpty()
|
value = details?.roomNumbers?.takeIf { it.isNotEmpty() }?.joinToString(", ")
|
||||||
)
|
)
|
||||||
GuestDetailRow(label = "Total Adults", value = details?.adultCount?.toString().orEmpty())
|
GuestDetailRow(label = "Total Adults", value = details?.adultCount?.toString())
|
||||||
GuestDetailRow(label = "Total Males", value = details?.maleCount?.toString().orEmpty())
|
GuestDetailRow(label = "Total Males", value = details?.maleCount?.toString())
|
||||||
GuestDetailRow(label = "Total Females", value = details?.femaleCount?.toString().orEmpty())
|
GuestDetailRow(label = "Total Females", value = details?.femaleCount?.toString())
|
||||||
GuestDetailRow(label = "Total Children", value = details?.childCount?.toString().orEmpty())
|
GuestDetailRow(label = "Total Children", value = details?.childCount?.toString())
|
||||||
GuestDetailRow(label = "Total Guests", value = details?.totalGuestCount?.toString().orEmpty())
|
GuestDetailRow(label = "Total Guests", value = details?.totalGuestCount?.toString())
|
||||||
GuestDetailRow(label = "Expected Guests", value = details?.expectedGuestCount?.toString().orEmpty())
|
if (details?.totalGuestCount == null) {
|
||||||
|
GuestDetailRow(label = "Expected Guests", value = details?.expectedGuestCount?.toString())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SectionCard(title = "Calculations") {
|
SectionCard(title = "Calculations") {
|
||||||
GuestDetailRow(label = "Amount Collected", value = details?.amountCollected?.toString().orEmpty())
|
GuestDetailRow(label = "Amount Collected", value = details?.amountCollected?.toString())
|
||||||
GuestDetailRow(label = "Rent per day", value = details?.totalNightlyRate?.toString().orEmpty())
|
GuestDetailRow(label = "Rent per day", value = details?.totalNightlyRate?.toString())
|
||||||
GuestDetailRow(label = "Expected pay", value = details?.expectedPay?.toString().orEmpty())
|
GuestDetailRow(label = "Expected pay", value = details?.expectedPay?.toString())
|
||||||
GuestDetailRow(label = "Pending", value = details?.pending?.toString().orEmpty())
|
GuestDetailRow(label = "Pending", value = details?.pending?.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
SectionCard(title = "Registered By") {
|
SectionCard(title = "Registered By") {
|
||||||
GuestDetailRow(label = "Name", value = details?.registeredByName.orEmpty())
|
GuestDetailRow(label = "Name", value = details?.registeredByName)
|
||||||
GuestDetailRow(label = "Phone number", value = details?.registeredByPhone.orEmpty())
|
GuestDetailRow(label = "Phone number", value = details?.registeredByPhone)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
val resolvedGuestId = details?.guestId ?: guestId
|
||||||
SignaturePreview(
|
SignaturePreview(
|
||||||
propertyId = propertyId,
|
propertyId = propertyId,
|
||||||
guestId = details?.guestId ?: guestId,
|
guestId = resolvedGuestId,
|
||||||
signatureUrl = details?.guestSignatureUrl
|
signatureUrl = details?.guestSignatureUrl,
|
||||||
|
onEditSignature = onEditSignature
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun GuestDetailRow(label: String, value: String) {
|
private fun GuestDetailRow(label: String, value: String?) {
|
||||||
|
if (value.isNullOrBlank()) return
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -235,7 +256,7 @@ private fun GuestDetailRow(label: String, value: String) {
|
|||||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = value.ifBlank { "-" },
|
text = value,
|
||||||
style = MaterialTheme.typography.bodyLarge
|
style = MaterialTheme.typography.bodyLarge
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -257,7 +278,12 @@ private fun SectionCard(title: String, content: @Composable ColumnScope.() -> Un
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun SignaturePreview(propertyId: String, guestId: String?, signatureUrl: String?) {
|
private fun SignaturePreview(
|
||||||
|
propertyId: String,
|
||||||
|
guestId: String?,
|
||||||
|
signatureUrl: String?,
|
||||||
|
onEditSignature: (String) -> Unit
|
||||||
|
) {
|
||||||
val resolvedGuestId = guestId
|
val resolvedGuestId = guestId
|
||||||
if (resolvedGuestId.isNullOrBlank() && signatureUrl.isNullOrBlank()) {
|
if (resolvedGuestId.isNullOrBlank() && signatureUrl.isNullOrBlank()) {
|
||||||
Text(text = "Signature", style = MaterialTheme.typography.titleSmall)
|
Text(text = "Signature", style = MaterialTheme.typography.titleSmall)
|
||||||
@@ -314,6 +340,12 @@ private fun SignaturePreview(propertyId: String, guestId: String?, signatureUrl:
|
|||||||
.padding(8.dp)
|
.padding(8.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (signatureUrl.isNullOrBlank() && !resolvedGuestId.isNullOrBlank()) {
|
||||||
|
Spacer(modifier = Modifier.height(6.dp))
|
||||||
|
TextButton(onClick = { onEditSignature(resolvedGuestId) }) {
|
||||||
|
Text("Add signature")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,6 +354,8 @@ private fun BookingRoomStaysTabContent(
|
|||||||
state: BookingRoomStaysState,
|
state: BookingRoomStaysState,
|
||||||
viewModel: BookingRoomStaysViewModel
|
viewModel: BookingRoomStaysViewModel
|
||||||
) {
|
) {
|
||||||
|
val displayZone = remember { ZoneId.of("Asia/Kolkata") }
|
||||||
|
val dateFormatter = remember { DateTimeFormatter.ofPattern("dd/MM/yy HH:mm") }
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
@@ -354,11 +388,17 @@ private fun BookingRoomStaysTabContent(
|
|||||||
state.stays.forEach { stay ->
|
state.stays.forEach { stay ->
|
||||||
val roomLine = "Room ${stay.roomNumber ?: "-"} • ${stay.roomTypeName ?: ""}".trim()
|
val roomLine = "Room ${stay.roomNumber ?: "-"} • ${stay.roomTypeName ?: ""}".trim()
|
||||||
Text(text = roomLine, style = MaterialTheme.typography.titleMedium)
|
Text(text = roomLine, style = MaterialTheme.typography.titleMedium)
|
||||||
val guestLine = listOfNotNull(stay.guestName, stay.guestPhone).joinToString(" • ")
|
val fromAt = stay.fromAt?.let {
|
||||||
if (guestLine.isNotBlank()) {
|
runCatching {
|
||||||
Text(text = guestLine, style = MaterialTheme.typography.bodyMedium)
|
OffsetDateTime.parse(it).atZoneSameInstant(displayZone).format(dateFormatter)
|
||||||
|
}.getOrNull()
|
||||||
}
|
}
|
||||||
val timeLine = listOfNotNull(stay.fromAt, stay.expectedCheckoutAt).joinToString(" → ")
|
val toAt = stay.expectedCheckoutAt?.let {
|
||||||
|
runCatching {
|
||||||
|
OffsetDateTime.parse(it).atZoneSameInstant(displayZone).format(dateFormatter)
|
||||||
|
}.getOrNull()
|
||||||
|
}
|
||||||
|
val timeLine = listOfNotNull(fromAt, toAt).joinToString(" → ")
|
||||||
if (timeLine.isNotBlank()) {
|
if (timeLine.isNotBlank()) {
|
||||||
Text(text = timeLine, style = MaterialTheme.typography.bodySmall)
|
Text(text = timeLine, style = MaterialTheme.typography.bodySmall)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user