Коммит cfa103e8 создал по автору Radch-enko's avatar Radch-enko
Просмотр файлов

Feature: add update event functionality and refactor event management in Main module

- Implemented `UpdateEventComponent` with structured state and intent handling for updating events.
- Added `UpdateBookingUseCase` and `DeleteBookingUseCase` for managing booking changes.
- Introduced mapper utilities (`EventInfoMapper`, `UpdateEventComponentStateToEventInfoMapper`) for transforming state and domain models.
- Enhanced `MainComponent` with `onDeleteEvent`, `onBooking`, and `onUpdateEvent` logic.
- Integrated `Calf-UI` library for improved date picker functionality.
- Replaced `EpicDatePicker` with `AdaptiveDatePicker` for streamlined UI.
- Refactored Gradle dependencies and removed unused `epic-calendar-compose` library.
- Updated `BusyRoomInfoComponent` to use `toFormattedString` for better time display.
- Added reusable `FailureSelectRoomView` for handling room selection errors.
владелец 837136b0
...@@ -22,6 +22,7 @@ kotlin { ...@@ -22,6 +22,7 @@ kotlin {
implementation(libs.findLibrary("kotlin.coroutines.core").get()) implementation(libs.findLibrary("kotlin.coroutines.core").get())
implementation(libs.findBundle("koin").get()) implementation(libs.findBundle("koin").get())
implementation(libs.findLibrary("kotlinx-datetime").get())
} }
androidMain.dependencies { androidMain.dependencies {
implementation(libs.findLibrary("koin-android").get()) implementation(libs.findLibrary("koin-android").get())
......
...@@ -17,6 +17,7 @@ kotlin { ...@@ -17,6 +17,7 @@ kotlin {
implementation(compose.components.uiToolingPreview) implementation(compose.components.uiToolingPreview)
implementation(libs.findLibrary("coil").get()) implementation(libs.findLibrary("coil").get())
implementation(libs.findLibrary("coil.network.ktor").get()) implementation(libs.findLibrary("coil.network.ktor").get())
api("com.mohamedrejeb.calf:calf-ui:0.8.0")
} }
androidMain.dependencies { androidMain.dependencies {
......
package band.effective.office.tablet.core.domain.model package band.effective.office.tablet.core.domain.model
import band.effective.office.tablet.core.domain.util.asInstant
import kotlinx.datetime.LocalDateTime import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
sealed class Slot { sealed class Slot {
abstract val start: LocalDateTime abstract val start: LocalDateTime
abstract val finish: LocalDateTime abstract val finish: LocalDateTime
fun minuteDuration(): Int { fun minuteDuration(): Int {
val startMillis = start.toInstant(TimeZone.currentSystemDefault()).toEpochMilliseconds() val startMillis = start.asInstant.toEpochMilliseconds()
val finishMillis = finish.toInstant(TimeZone.currentSystemDefault()).toEpochMilliseconds() val finishMillis = finish.asInstant.toEpochMilliseconds()
return ((finishMillis - startMillis) / 60000).toInt() return ((finishMillis - startMillis) / 60000).toInt()
} }
......
package band.effective.office.tablet.core.domain.util package band.effective.office.tablet.core.domain.util
import kotlinx.datetime.LocalDateTime import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.LocalTime
import kotlinx.datetime.format.FormatStringsInDatetimeFormats import kotlinx.datetime.format.FormatStringsInDatetimeFormats
import kotlinx.datetime.format.byUnicodePattern import kotlinx.datetime.format.byUnicodePattern
...@@ -21,3 +22,11 @@ fun LocalDateTime.toFormattedString(pattern: String): String { ...@@ -21,3 +22,11 @@ fun LocalDateTime.toFormattedString(pattern: String): String {
} }
return formatter.format(this) return formatter.format(this)
} }
@OptIn(FormatStringsInDatetimeFormats::class)
fun LocalTime.toFormattedString(pattern: String): String {
val formatter = LocalTime.Format {
byUnicodePattern(pattern)
}
return formatter.format(this)
}
...@@ -4,6 +4,7 @@ import kotlin.time.Clock ...@@ -4,6 +4,7 @@ import kotlin.time.Clock
import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.minutes
import kotlin.time.Instant import kotlin.time.Instant
import kotlinx.datetime.LocalDateTime import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.LocalTime
import kotlinx.datetime.TimeZone import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant import kotlinx.datetime.toInstant
import kotlinx.datetime.toLocalDateTime import kotlinx.datetime.toLocalDateTime
...@@ -25,4 +26,41 @@ fun roundUpToNextQuarter(dateTime: LocalDateTime): LocalDateTime { ...@@ -25,4 +26,41 @@ fun roundUpToNextQuarter(dateTime: LocalDateTime): LocalDateTime {
} }
val LocalDateTime.asInstant get() = toInstant(defaultTimeZone) val LocalDateTime.asInstant get() = toInstant(defaultTimeZone)
val Instant.asLocalDateTime get() = this.toLocalDateTime(defaultTimeZone) val Instant.asLocalDateTime get() = this.toLocalDateTime(defaultTimeZone)
\ No newline at end of file
val LocalTime.Companion.Max
get() = LocalTime(
hour = 23,
minute = 59,
second = 59,
nanosecond = 999999999
)
val LocalTime.Companion.Min
get() = LocalTime(
hour = 0,
minute = 0,
second = 0,
nanosecond = 0
)
fun LocalTime.Companion.of(
hour: Int,
minute: Int
) = LocalTime(hour = hour, minute = minute, second = 0, nanosecond = 0)
fun LocalTime.truncatedToMinute() = LocalTime.of(
hour = hour,
minute = minute
)
fun LocalTime.withHour(hour: Int) =
LocalTime(hour = hour, minute = minute, second = second, nanosecond = nanosecond)
fun LocalTime.withMinute(minute: Int) =
LocalTime(hour = hour, minute = minute, second = second, nanosecond = nanosecond)
fun LocalTime.isBefore(other: LocalTime) = this < other
fun LocalTime.isAfter(other: LocalTime) = this > other
\ No newline at end of file
...@@ -5,7 +5,6 @@ plugins { ...@@ -5,7 +5,6 @@ plugins {
kotlin { kotlin {
sourceSets { sourceSets {
commonMain.dependencies { commonMain.dependencies {
implementation("io.github.epicarchitect:epic-calendar-compose:1.0.8")
implementation(libs.kotlinx.datetime) implementation(libs.kotlinx.datetime)
implementation(libs.decompose) implementation(libs.decompose)
implementation(libs.decompose.compose.jetbrains) implementation(libs.decompose.compose.jetbrains)
......
package band.effective.office.tablet.core.ui.date
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import band.effective.office.tablet.core.ui.Res
import band.effective.office.tablet.core.ui.arrow_left
import band.effective.office.tablet.core.ui.theme.LocalCustomColorsPalette
import band.effective.office.tablet.core.ui.theme.header6
import epicarchitect.calendar.compose.basis.BasisDayOfMonthContent
import epicarchitect.calendar.compose.basis.BasisDayOfWeekContent
import epicarchitect.calendar.compose.basis.config.LocalBasisEpicCalendarConfig
import epicarchitect.calendar.compose.basis.contains
import epicarchitect.calendar.compose.basis.localizedBySystem
import epicarchitect.calendar.compose.basis.state.LocalBasisEpicCalendarState
import epicarchitect.calendar.compose.datepicker.EpicDatePicker
import epicarchitect.calendar.compose.datepicker.state.EpicDatePickerState
import epicarchitect.calendar.compose.datepicker.state.LocalEpicDatePickerState
import epicarchitect.calendar.compose.pager.state.EpicCalendarPagerState
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlinx.datetime.LocalDate
import org.jetbrains.compose.resources.painterResource
@Composable
fun DatePickerView(
modifier: Modifier = Modifier,
epicDatePickerState: EpicDatePickerState,
) {
val coroutineScope = rememberCoroutineScope()
Column(modifier = modifier) {
DatePickerTitleView(
epicDatePickerState = epicDatePickerState,
onClickNextMonth = {
scrollMonth(
coroutineScope = coroutineScope,
pagerState = epicDatePickerState.pagerState,
amount = 1
)
},
onClickPreviousMonth = {
scrollMonth(
coroutineScope = coroutineScope,
pagerState = epicDatePickerState.pagerState,
amount = -1
)
}
)
EpicDatePicker(
state = epicDatePickerState,
dayOfWeekContent = CustomDayOfWeekContent,
dayOfMonthContent = CustomDayOfMonthContent,
modifier = Modifier.background(Color.Transparent),
)
}
}
@Composable
private fun DatePickerTitleView(
epicDatePickerState: EpicDatePickerState,
onClickNextMonth: () -> Unit,
onClickPreviousMonth: () -> Unit
) {
Row(
modifier = Modifier
.background(
LocalCustomColorsPalette.current.mountainBackground,
RoundedCornerShape(12.dp)
)
.fillMaxWidth().fillMaxHeight(0.15f)
.clip(RoundedCornerShape(12.dp)),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Button(
modifier = Modifier.fillMaxHeight(),
onClick = { onClickPreviousMonth() },
colors = ButtonDefaults.buttonColors(
containerColor = Color.Transparent,
)
) {
Image(
modifier = Modifier,
painter = painterResource(Res.drawable.arrow_left),
contentDescription = null
)
}
Text(
text = if (epicDatePickerState.selectedDates.isNotEmpty()) {
stringFormat(epicDatePickerState.selectedDates.firstOrNull())
} else {
epicDatePickerState.pagerState.currentMonth.month.toString() // TODO
},
style = header6,
color = LocalCustomColorsPalette.current.primaryTextAndIcon,
)
Button(
modifier = Modifier.fillMaxHeight(),
onClick = { onClickNextMonth() },
colors = ButtonDefaults.buttonColors(
containerColor = Color.Transparent,
)
) {
Image(
modifier = Modifier,
painter = painterResource(Res.drawable.arrow_left),
contentDescription = null
)
}
}
}
private fun scrollMonth(
coroutineScope: CoroutineScope,
pagerState: EpicCalendarPagerState,
amount: Int
) {
coroutineScope.launch {
pagerState.scrollMonths(amount)
}
}
private val CustomDayOfWeekContent: BasisDayOfWeekContent = { dayOfWeek ->
val config = LocalBasisEpicCalendarConfig.current
Text(
text = dayOfWeek.localizedBySystem(),
textAlign = TextAlign.Center,
color = config.contentColor,
style = header6,
maxLines = 1
)
}
private val CustomDayOfMonthContent: BasisDayOfMonthContent = { date ->
val basisState = LocalBasisEpicCalendarState.current!!
val pickerState = LocalEpicDatePickerState.current!!
val selectedDays = pickerState.selectedDates
val selectionMode = pickerState.selectionMode
val isSelected = remember(selectionMode, selectedDays, date) {
when (selectionMode) {
is EpicDatePickerState.SelectionMode.Range -> {
if (selectedDays.isEmpty()) false
else date in selectedDays.min()..selectedDays.max()
}
is EpicDatePickerState.SelectionMode.Single -> {
date in selectedDays
}
}
}
Text(
modifier = Modifier.alpha(
if (date in basisState.currentMonth) 1.0f
else 0.5f
),
text = date.dayOfMonth.toString(),
textAlign = TextAlign.Center,
style = header6,
maxLines = 1,
color = if (isSelected) pickerState.config.selectionContentColor
else pickerState.config.pagerConfig.basisConfig.contentColor
)
}
private fun stringFormat(date: LocalDate?): String {
val monthName = date?.month
return "${date?.dayOfMonth} $monthName".lowercase()
}
\ No newline at end of file
...@@ -2,14 +2,6 @@ plugins { ...@@ -2,14 +2,6 @@ plugins {
id("band.effective.office.client.kmp.feature") id("band.effective.office.client.kmp.feature")
} }
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.epicarchitect:epic-calendar-compose:1.0.8")
}
}
}
compose.resources { compose.resources {
publicResClass = false publicResClass = false
packageOfResClass = "band.effective.office.tablet.feature.main" packageOfResClass = "band.effective.office.tablet.feature.main"
......
...@@ -20,7 +20,7 @@ import androidx.compose.ui.Modifier ...@@ -20,7 +20,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import band.effective.office.tablet.core.domain.model.EventInfo import band.effective.office.tablet.core.domain.model.EventInfo
import band.effective.office.tablet.core.domain.util.timeFormatter import band.effective.office.tablet.core.domain.util.toFormattedString
import band.effective.office.tablet.core.ui.theme.LocalCustomColorsPalette import band.effective.office.tablet.core.ui.theme.LocalCustomColorsPalette
import band.effective.office.tablet.core.ui.theme.h5 import band.effective.office.tablet.core.ui.theme.h5
import band.effective.office.tablet.core.ui.theme.roomInfoColor import band.effective.office.tablet.core.ui.theme.roomInfoColor
...@@ -62,7 +62,7 @@ fun BusyRoomInfoComponent( ...@@ -62,7 +62,7 @@ fun BusyRoomInfoComponent(
isError = isError isError = isError
) { ) {
Text( Text(
text = stringResource(Res.string.room_occupancy_date, timeFormatter.format(event.finishTime)) + text = stringResource(Res.string.room_occupancy_date, event.finishTime.toFormattedString("HH:mm")) +
" " + if (timeToFinish > 0) stringResource(Res.string.room_occupancy_time, timeToFinish.getDuration()) else "", " " + if (timeToFinish > 0) stringResource(Res.string.room_occupancy_time, timeToFinish.getDuration()) else "",
style = MaterialTheme.typography.h5, style = MaterialTheme.typography.h5,
color = roomInfoColor color = roomInfoColor
......
...@@ -40,6 +40,7 @@ fun RoomInfoLeftPanel( ...@@ -40,6 +40,7 @@ fun RoomInfoLeftPanel(
onCancelEventRequest: () -> Unit, onCancelEventRequest: () -> Unit,
timeToNextEvent: Int, timeToNextEvent: Int,
isDisconnect: Boolean, isDisconnect: Boolean,
onOpenDateTimePickerModal: () -> Unit,
) { ) {
val slotState by slotComponent.state.collectAsState() val slotState by slotComponent.state.collectAsState()
Box( Box(
...@@ -64,7 +65,7 @@ fun RoomInfoLeftPanel( ...@@ -64,7 +65,7 @@ fun RoomInfoLeftPanel(
selectDate = selectedDate, selectDate = selectedDate,
increment = onIncrementData, increment = onIncrementData,
decrement = onDecrementData, decrement = onDecrementData,
onOpenDateTimePickerModal = { }, onOpenDateTimePickerModal = onOpenDateTimePickerModal,
currentDate = Clock.System.now(), currentDate = Clock.System.now(),
back = onResetDate, back = onResetDate,
) )
......
package band.effective.office.tablet.feature.main.di package band.effective.office.tablet.feature.main.di
import band.effective.office.tablet.feature.main.domain.CreateFastBookingUseCase import band.effective.office.tablet.feature.main.domain.CreateBookingUseCase
import band.effective.office.tablet.feature.main.domain.DeleteBookingUseCase
import band.effective.office.tablet.feature.main.domain.FreeUpRoomUseCase import band.effective.office.tablet.feature.main.domain.FreeUpRoomUseCase
import band.effective.office.tablet.feature.main.domain.GetRoomIndexUseCase import band.effective.office.tablet.feature.main.domain.GetRoomIndexUseCase
import band.effective.office.tablet.feature.main.domain.GetSlotsByRoomUseCase import band.effective.office.tablet.feature.main.domain.GetSlotsByRoomUseCase
import band.effective.office.tablet.feature.main.domain.GetTimeToNextEventUseCase import band.effective.office.tablet.feature.main.domain.GetTimeToNextEventUseCase
import band.effective.office.tablet.feature.main.domain.RemoveFastBookingUseCase import band.effective.office.tablet.feature.main.domain.UpdateBookingUseCase
import band.effective.office.tablet.feature.main.domain.mapper.SlotUiMapper import band.effective.office.tablet.feature.main.domain.mapper.EventInfoMapper
import band.effective.office.tablet.feature.main.domain.mapper.UpdateEventComponentStateToEventInfoMapper
import band.effective.office.tablet.feature.main.presentation.mapper.SlotUiMapper
import org.koin.dsl.module import org.koin.dsl.module
val mainScreenModule = module { val mainScreenModule = module {
...@@ -14,8 +17,11 @@ val mainScreenModule = module { ...@@ -14,8 +17,11 @@ val mainScreenModule = module {
single { GetTimeToNextEventUseCase() } single { GetTimeToNextEventUseCase() }
single { GetSlotsByRoomUseCase(get()) } single { GetSlotsByRoomUseCase(get()) }
single { FreeUpRoomUseCase(get()) } single { FreeUpRoomUseCase(get()) }
single { CreateFastBookingUseCase(get()) } single { CreateBookingUseCase(get()) }
single { RemoveFastBookingUseCase(get()) } single { DeleteBookingUseCase(get()) }
single { UpdateBookingUseCase(get()) }
single { SlotUiMapper() } single { SlotUiMapper() }
single { EventInfoMapper() }
single { UpdateEventComponentStateToEventInfoMapper() }
} }
\ No newline at end of file
...@@ -3,7 +3,7 @@ package band.effective.office.tablet.feature.main.domain ...@@ -3,7 +3,7 @@ package band.effective.office.tablet.feature.main.domain
import band.effective.office.tablet.core.domain.model.EventInfo import band.effective.office.tablet.core.domain.model.EventInfo
import band.effective.office.tablet.core.domain.repository.EventManagerRepository import band.effective.office.tablet.core.domain.repository.EventManagerRepository
class CreateFastBookingUseCase( class CreateBookingUseCase(
private val eventManagerRepository: EventManagerRepository, private val eventManagerRepository: EventManagerRepository,
) { ) {
suspend operator fun invoke(roomName: String, eventInfo: EventInfo) = suspend operator fun invoke(roomName: String, eventInfo: EventInfo) =
......
...@@ -3,7 +3,7 @@ package band.effective.office.tablet.feature.main.domain ...@@ -3,7 +3,7 @@ package band.effective.office.tablet.feature.main.domain
import band.effective.office.tablet.core.domain.model.EventInfo import band.effective.office.tablet.core.domain.model.EventInfo
import band.effective.office.tablet.core.domain.repository.EventManagerRepository import band.effective.office.tablet.core.domain.repository.EventManagerRepository
class RemoveFastBookingUseCase( class DeleteBookingUseCase(
private val eventManagerRepository: EventManagerRepository, private val eventManagerRepository: EventManagerRepository,
) { ) {
......
package band.effective.office.tablet.feature.main.domain
import band.effective.office.tablet.core.domain.model.EventInfo
import band.effective.office.tablet.core.domain.repository.EventManagerRepository
class UpdateBookingUseCase(
private val eventManagerRepository: EventManagerRepository,
) {
suspend operator fun invoke(
roomName: String,
eventInfo: EventInfo,
) = eventManagerRepository.updateBooking(
roomName = roomName,
eventInfo = eventInfo,
)
}
\ No newline at end of file
package band.effective.office.tablet.feature.main.domain.mapper
import band.effective.office.tablet.core.domain.model.EventInfo
import band.effective.office.tablet.core.domain.model.Slot
import band.effective.office.tablet.core.domain.util.asInstant
import band.effective.office.tablet.feature.main.presentation.updateEvent.State
class EventInfoMapper {
fun mapToSlot(eventInfo: EventInfo): Slot =
Slot.EventSlot(start = eventInfo.startTime, finish = eventInfo.finishTime, eventInfo = eventInfo)
fun mapToUpdateBookingState(eventInfo: EventInfo): State {
val duration = eventInfo.finishTime.asInstant.minus(eventInfo.startTime.asInstant).inWholeMinutes.toInt()
return State.defaultValue.copy(
date = eventInfo.startTime,
duration = duration,
selectOrganizer = eventInfo.organizer,
inputText = eventInfo.organizer.fullName,
event = eventInfo
)
}
}
\ No newline at end of file
package band.effective.office.tablet.feature.main.domain.mapper
import band.effective.office.tablet.core.domain.model.EventInfo
import band.effective.office.tablet.core.domain.util.asInstant
import band.effective.office.tablet.core.domain.util.asLocalDateTime
import band.effective.office.tablet.feature.main.presentation.updateEvent.State
import kotlin.time.Duration.Companion.minutes
class UpdateEventComponentStateToEventInfoMapper {
fun map(state: State): EventInfo = EventInfo(
startTime = state.date,
finishTime = state.date.asInstant.plus(state.duration.minutes).asLocalDateTime,
organizer = state.selectOrganizer,
id = state.event.id,
isLoading = false,
)
}
\ No newline at end of file
package band.effective.office.tablet.feature.main.presentation.common
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
@Composable
fun AlertButton(
modifier: Modifier = Modifier,
onClick: () -> Unit,
content: @Composable RowScope.() -> Unit
) {
Button(
modifier = modifier
.clip(RoundedCornerShape(100.dp)).border(
width = 3.dp,
shape = RoundedCornerShape(100.dp),
color = MaterialTheme.colorScheme.onPrimary
),
colors = ButtonDefaults.buttonColors(containerColor = Color.Transparent),
onClick = { onClick() }
) {
content()
}
}
\ No newline at end of file
package band.effective.office.tablet.feature.main.presentation.common
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import band.effective.office.tablet.core.ui.common.Loader
import band.effective.office.tablet.core.ui.theme.CustomDarkColors
import band.effective.office.tablet.core.ui.theme.LocalCustomColorsPalette
import band.effective.office.tablet.core.ui.theme.h6_button
@Composable
fun BookingButtonView(
modifier: Modifier,
shape: RoundedCornerShape,
text: String,
onClick: () -> Unit,
isLoading: Boolean,
) {
val isPressed = remember { mutableStateOf(false) }
val colorButton =
if (isPressed.value) LocalCustomColorsPalette.current.pressedPrimaryButton else MaterialTheme.colorScheme.primary
Button(
modifier = modifier,
elevation = ButtonDefaults.elevatedButtonElevation(0.dp),
colors = ButtonDefaults.buttonColors(colorButton),
shape = shape,
onClick = {
isPressed.value = !isPressed.value
onClick()
}) {
Box(contentAlignment = Alignment.Center) {
if (isLoading) Loader()
else Text(
text = text,
style = MaterialTheme.typography.h6_button,
color = when (LocalCustomColorsPalette.current) {
CustomDarkColors -> LocalCustomColorsPalette.current.primaryTextAndIcon
else -> MaterialTheme.colorScheme.background
}
)
}
}
}
\ No newline at end of file
package band.effective.office.tablet.feature.main.presentation.common
import androidx.compose.foundation.layout.Box
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import band.effective.office.tablet.core.domain.model.EventInfo
import band.effective.office.tablet.core.domain.util.timeFormatter
import band.effective.office.tablet.core.ui.theme.LocalCustomColorsPalette
import band.effective.office.tablet.core.ui.theme.h5
import band.effective.office.tablet.feature.main.Res
import band.effective.office.tablet.feature.main.date_booking
import kotlinx.datetime.format
import org.jetbrains.compose.resources.stringResource
@Composable
fun DateTimeView(modifier: Modifier, eventInfo: EventInfo) {
Box(
modifier = modifier,
contentAlignment = Alignment.Center
) {
Text(
text = stringResource(
Res.string.date_booking,
eventInfo.startTime,
eventInfo.startTime.format(timeFormatter),
eventInfo.finishTime.format(timeFormatter)
),
style = MaterialTheme.typography.h5,
color = LocalCustomColorsPalette.current.primaryTextAndIcon
)
}
}
\ No newline at end of file
package band.effective.office.tablet.feature.main.presentation.common
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import band.effective.office.tablet.core.ui.Res
import band.effective.office.tablet.core.ui.minus_date_button_string
import band.effective.office.tablet.core.ui.plus_date_button_string
import band.effective.office.tablet.core.ui.select_length_title
import band.effective.office.tablet.core.ui.short_hours
import band.effective.office.tablet.core.ui.short_minuets
import band.effective.office.tablet.core.ui.theme.LocalCustomColorsPalette
import band.effective.office.tablet.core.ui.theme.h4
import band.effective.office.tablet.core.ui.theme.h6
import band.effective.office.tablet.core.ui.theme.h8
import org.jetbrains.compose.resources.stringResource
@Composable
fun EventDurationView(
modifier: Modifier = Modifier,
currentDuration: Int,
increment: () -> Unit,
decrement: () -> Unit
) {
Column(modifier = modifier) {
Text(
text = stringResource(Res.string.select_length_title),
color = LocalCustomColorsPalette.current.secondaryTextAndIcon,
style = MaterialTheme.typography.h8
)
Spacer(modifier = Modifier.height(10.dp))
Row(
modifier = Modifier.fillMaxSize(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Button(
modifier = Modifier.fillMaxHeight().weight(1f).clip(RoundedCornerShape(15.dp)),
onClick = { decrement() },
colors = ButtonDefaults.buttonColors(
containerColor = LocalCustomColorsPalette.current.elevationBackground
)
) {
Text(
text = stringResource(Res.string.minus_date_button_string),
style = MaterialTheme.typography.h6
)
}
Text(
modifier = Modifier.weight(1f),
text = currentDuration.getDurationString(),
color = MaterialTheme.colorScheme.onPrimary,
style = MaterialTheme.typography.h4,
textAlign = TextAlign.Center
)
Button(
modifier = Modifier.fillMaxHeight().weight(1f).clip(RoundedCornerShape(15.dp)),
onClick = {
increment()
},
colors = ButtonDefaults.buttonColors(
containerColor = LocalCustomColorsPalette.current.elevationBackground
)
) {
Text(
text = stringResource(Res.string.plus_date_button_string),
style = MaterialTheme.typography.h6
)
}
}
}
}
@Composable
private fun Int.getDurationString(): String {
val hours = this / 60
val minutes = this % 60
return when {
hours == 0 -> "$minutes${stringResource(Res.string.short_minuets)}"
minutes == 0 -> "$hours${stringResource(Res.string.short_hours)}"
else -> "$hours${Res.string.short_hours} $minutes${Res.string.short_minuets}"
}
}
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать