Added appearance and basic booking functionality
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
package ru.myitschool.work.domain.entities
|
||||||
|
|
||||||
|
data class BookingEntities (
|
||||||
|
var roomName : String,
|
||||||
|
var time: String
|
||||||
|
)
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package ru.myitschool.work.domain.entities
|
||||||
|
|
||||||
|
data class UserEntities(
|
||||||
|
val name : String,
|
||||||
|
var image : Int,
|
||||||
|
var booking : ArrayList<BookingEntities>
|
||||||
|
)
|
||||||
@@ -15,6 +15,7 @@ import ru.myitschool.work.ui.nav.AuthScreenDestination
|
|||||||
import ru.myitschool.work.ui.nav.BookScreenDestination
|
import ru.myitschool.work.ui.nav.BookScreenDestination
|
||||||
import ru.myitschool.work.ui.nav.MainScreenDestination
|
import ru.myitschool.work.ui.nav.MainScreenDestination
|
||||||
import ru.myitschool.work.ui.screen.auth.AuthScreen
|
import ru.myitschool.work.ui.screen.auth.AuthScreen
|
||||||
|
import ru.myitschool.work.ui.screen.book.BookScreen
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AppNavHost(
|
fun AppNavHost(
|
||||||
@@ -39,11 +40,7 @@ fun AppNavHost(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
composable<BookScreenDestination> {
|
composable<BookScreenDestination> {
|
||||||
Box(
|
BookScreen(navController = navController)
|
||||||
contentAlignment = Alignment.Center
|
|
||||||
) {
|
|
||||||
Text(text = "Hello")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package ru.myitschool.work.ui.screen.book
|
||||||
|
|
||||||
|
sealed interface BookIntent {
|
||||||
|
data class Send(val text: String): BookIntent
|
||||||
|
data class BookingSelect(val text: String): BookIntent
|
||||||
|
}
|
||||||
@@ -0,0 +1,215 @@
|
|||||||
|
package ru.myitschool.work.ui.screen.book;
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.selection.selectableGroup
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
|
import androidx.compose.material3.NavigationBar
|
||||||
|
import androidx.compose.material3.NavigationBarItem
|
||||||
|
import androidx.compose.material3.RadioButton
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable;
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.testTag
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import androidx.navigation.NavController;
|
||||||
|
import ru.myitschool.work.R
|
||||||
|
import ru.myitschool.work.core.TestIds
|
||||||
|
import ru.myitschool.work.domain.entities.BookingEntities
|
||||||
|
import ru.myitschool.work.ui.nav.BookScreenDestination
|
||||||
|
import ru.myitschool.work.ui.nav.MainScreenDestination
|
||||||
|
import ru.myitschool.work.ui.screen.auth.AuthViewModel
|
||||||
|
|
||||||
|
var selectedTime = mutableStateOf(0)
|
||||||
|
var selectedBooking = mutableStateOf(0)
|
||||||
|
var currentTime = mutableStateOf(0)
|
||||||
|
@Composable
|
||||||
|
fun BookScreen(
|
||||||
|
viewModel: BookViewModel = viewModel(),
|
||||||
|
navController: NavController,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
val state by viewModel.uiState.collectAsState()
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
viewModel.actionFlow.collect {
|
||||||
|
navController.navigate(MainScreenDestination)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO брать данные с сервера
|
||||||
|
// Иммитация того, что мы взяли данные с сервера
|
||||||
|
val bookings = arrayListOf(
|
||||||
|
BookingEntities(
|
||||||
|
"Рабочее место у окна",
|
||||||
|
"19.04"
|
||||||
|
),
|
||||||
|
BookingEntities(
|
||||||
|
"Переговорная комната № 1",
|
||||||
|
"19.04"
|
||||||
|
),
|
||||||
|
BookingEntities(
|
||||||
|
"Коворкинг А",
|
||||||
|
"19.04"
|
||||||
|
),
|
||||||
|
BookingEntities(
|
||||||
|
"Кабинет № 33",
|
||||||
|
"20.04"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
val options = toMap(bookings)
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = modifier.fillMaxSize()
|
||||||
|
) {
|
||||||
|
// Text("" + selectedTime.value + "," + currentTime.value + "," + selectedBooking.value)
|
||||||
|
when (val currentState = state) {
|
||||||
|
BookState.Data -> {
|
||||||
|
TabGroup(options.keys)
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
options.keys.forEach {
|
||||||
|
if (i == currentTime.value)
|
||||||
|
SelectBooking(options[it]!!)
|
||||||
|
i ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
// TODO Добавить бронирование
|
||||||
|
viewModel.onIntent(BookIntent.Send("Данные" ))
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.testTag(TestIds.Book.BOOK_BUTTON)
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.to_book))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BookState.Error -> {
|
||||||
|
Text(
|
||||||
|
text = "",
|
||||||
|
modifier = Modifier
|
||||||
|
.testTag(TestIds.Book.ERROR)
|
||||||
|
)
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = { },
|
||||||
|
modifier = Modifier
|
||||||
|
.testTag(TestIds.Book.REFRESH_BUTTON)
|
||||||
|
) {
|
||||||
|
Text("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BookState.Loading -> {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterHorizontally)
|
||||||
|
.size(64.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
BookState.NotData -> {
|
||||||
|
Text(
|
||||||
|
text = "",
|
||||||
|
modifier = Modifier
|
||||||
|
.testTag(TestIds.Book.EMPTY)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
navController.navigate(MainScreenDestination)
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.testTag(TestIds.Book.BACK_BUTTON)
|
||||||
|
) {
|
||||||
|
Text(stringResource(R.string.back))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun TabGroup(options: Set<String>) {
|
||||||
|
NavigationBar(
|
||||||
|
Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
options.forEachIndexed { index, label ->
|
||||||
|
NavigationBarItem(
|
||||||
|
selected = currentTime.value == index,
|
||||||
|
onClick = {
|
||||||
|
currentTime.value = index
|
||||||
|
},
|
||||||
|
icon = {
|
||||||
|
Text(
|
||||||
|
text = label,
|
||||||
|
modifier = Modifier
|
||||||
|
.testTag(TestIds.Book.ITEM_DATE)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.testTag(TestIds.Book.getIdDateItemByPosition(index))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SelectBooking(options: List<String>) {
|
||||||
|
LazyColumn(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
options.forEachIndexed { index, label ->
|
||||||
|
item {
|
||||||
|
Row(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.selectableGroup()
|
||||||
|
.testTag(TestIds.Book.getIdPlaceItemByPosition(index)),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = label,
|
||||||
|
modifier = Modifier
|
||||||
|
.testTag(TestIds.Book.ITEM_PLACE_TEXT)
|
||||||
|
)
|
||||||
|
RadioButton(
|
||||||
|
selected = index == selectedBooking.value && currentTime.value == selectedTime.value,
|
||||||
|
onClick = {
|
||||||
|
selectedBooking.value = index
|
||||||
|
selectedTime.value = currentTime.value
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.testTag(TestIds.Book.ITEM_PLACE_SELECTOR)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toMap(options: List<BookingEntities>) : Map<String, List<String>> {
|
||||||
|
val map : MutableMap<String, MutableList<String>> = mutableMapOf()
|
||||||
|
options.forEach {
|
||||||
|
if (map[it.time] == null) map[it.time] = mutableListOf(it.roomName)
|
||||||
|
else map[it.time]?.add(it.roomName)
|
||||||
|
}
|
||||||
|
return map
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package ru.myitschool.work.ui.screen.book
|
||||||
|
|
||||||
|
sealed interface BookState {
|
||||||
|
object Loading: BookState
|
||||||
|
object Data: BookState
|
||||||
|
object Error: BookState
|
||||||
|
object NotData : BookState
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package ru.myitschool.work.ui.screen.book
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.SharedFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class BookViewModel : ViewModel() {
|
||||||
|
private val _uiState = MutableStateFlow<BookState>(BookState.Data)
|
||||||
|
val uiState: StateFlow<BookState> = _uiState.asStateFlow();
|
||||||
|
|
||||||
|
private val _actionFlow: MutableSharedFlow<Unit> = MutableSharedFlow()
|
||||||
|
val actionFlow: SharedFlow<Unit> = _actionFlow
|
||||||
|
|
||||||
|
fun onIntent(intent: BookIntent) {
|
||||||
|
when (intent) {
|
||||||
|
is BookIntent.Send -> {
|
||||||
|
viewModelScope.launch(Dispatchers.Default) {
|
||||||
|
_uiState.update { BookState.Loading }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is BookIntent.BookingSelect -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,4 +4,6 @@
|
|||||||
<string name="auth_title">Привет! Введи код для авторизации</string>
|
<string name="auth_title">Привет! Введи код для авторизации</string>
|
||||||
<string name="auth_label">Код</string>
|
<string name="auth_label">Код</string>
|
||||||
<string name="auth_sign_in">Войти</string>
|
<string name="auth_sign_in">Войти</string>
|
||||||
|
<string name="to_book">забронировать</string>
|
||||||
|
<string name="back">Назад</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user