From b0e17267442d245120d1dfcc4050dc92362ab8db Mon Sep 17 00:00:00 2001 From: student Date: Thu, 11 Dec 2025 16:52:16 +0300 Subject: [PATCH 1/4] Commit Test --- .../myitschool/work/ui/root/RootActivity.kt | 4 + .../work/ui/screen/NavigationGraph.kt | 104 +++++++++++++++++- .../work/ui/screen/auth/AuthScreen.kt | 8 +- .../work/ui/screen/book/BookIntent.kt | 4 + .../work/ui/screen/book/BookScreen.kt | 75 +++++++++++++ 5 files changed, 189 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/ru/myitschool/work/ui/screen/book/BookIntent.kt create mode 100644 app/src/main/java/ru/myitschool/work/ui/screen/book/BookScreen.kt diff --git a/app/src/main/java/ru/myitschool/work/ui/root/RootActivity.kt b/app/src/main/java/ru/myitschool/work/ui/root/RootActivity.kt index 54b156d..46b463f 100644 --- a/app/src/main/java/ru/myitschool/work/ui/root/RootActivity.kt +++ b/app/src/main/java/ru/myitschool/work/ui/root/RootActivity.kt @@ -8,7 +8,9 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Scaffold import androidx.compose.ui.Modifier +import androidx.lifecycle.viewmodel.compose.viewModel import ru.myitschool.work.ui.screen.AppNavHost +import ru.myitschool.work.ui.screen.auth.AuthViewModel import ru.myitschool.work.ui.theme.WorkTheme class RootActivity : ComponentActivity() { @@ -18,7 +20,9 @@ class RootActivity : ComponentActivity() { setContent { WorkTheme { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> + val viewModel: AuthViewModel = viewModel() AppNavHost( + viewModel, modifier = Modifier .fillMaxSize() .padding(innerPadding) diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/NavigationGraph.kt b/app/src/main/java/ru/myitschool/work/ui/screen/NavigationGraph.kt index 01b0f32..397dd6f 100644 --- a/app/src/main/java/ru/myitschool/work/ui/screen/NavigationGraph.kt +++ b/app/src/main/java/ru/myitschool/work/ui/screen/NavigationGraph.kt @@ -1,26 +1,66 @@ package ru.myitschool.work.ui.screen +import androidx.compose.animation.AnimatedContentScope import androidx.compose.animation.EnterTransition import androidx.compose.animation.ExitTransition +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.text.input.TextFieldLineLimits +import androidx.compose.foundation.text.input.rememberTextFieldState +import androidx.compose.material3.Button +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text +import androidx.compose.material3.TextField import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTag +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController +import ru.myitschool.work.core.TestIds import ru.myitschool.work.ui.nav.AuthScreenDestination import ru.myitschool.work.ui.nav.BookScreenDestination import ru.myitschool.work.ui.nav.MainScreenDestination +import ru.myitschool.work.ui.screen.auth.AuthIntent import ru.myitschool.work.ui.screen.auth.AuthScreen +import ru.myitschool.work.ui.screen.auth.AuthViewModel + @Composable fun AppNavHost( + viewModel: AuthViewModel, modifier: Modifier = Modifier, - navController: NavHostController = rememberNavController() -) { + navController: NavHostController = rememberNavController(), + + ) { + var expanded by remember{ mutableStateOf(false)} + var inputUsername by remember { mutableStateOf("Введите имя") } + val date:String = "" + val username:String = "" + var place:String = "" + NavHost( modifier = modifier, enterTransition = { EnterTransition.None }, @@ -35,8 +75,61 @@ fun AppNavHost( Box( contentAlignment = Alignment.Center ) { - Text(text = "Hello") + Text(text = "") + } + Column() { + Spacer(modifier = Modifier.size(16.dp)) + Text( + modifier = Modifier.testTag("main_name").fillMaxWidth(), + text = username + ) + Spacer(modifier = Modifier.size(10.dp)) + + Spacer(modifier = Modifier.size(10.dp)) + Row (horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth().padding(8.dp)) { + + Button(onClick = { }) { + Text(text = "Выход") + Modifier + .padding(20.dp) + .fillMaxWidth() + .semantics { testTag = "main_logout_button" } + } + Spacer(modifier = Modifier.size(10.dp)) + Button(onClick = { }) { + Text(text = "Обновить") + Modifier + .padding(20.dp) + .fillMaxWidth() + .semantics { testTag = "main_refresh_button" } + } + Spacer(modifier = Modifier.size(10.dp)) + } + Spacer(modifier = Modifier.size(10.dp)) + + Button(onClick = { expanded = true }) { + Text(text = "бронировать") + Modifier + .padding(20.dp) + .fillMaxWidth() + .semantics { testTag = "main_add_button" } + } + Text( + modifier = Modifier.testTag("main_item_date").fillMaxWidth(), + text = date + ) + Spacer(modifier = Modifier.size(10.dp)) + Text( + modifier = Modifier.testTag("main_item_place").fillMaxWidth(), + text = place + ) + Text(text = "ERROR", + modifier = Modifier.testTag("main_error").fillMaxWidth().alpha(0f)) + + } + } composable { Box( @@ -46,4 +139,7 @@ fun AppNavHost( } } } -} \ No newline at end of file +} + + + diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthScreen.kt b/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthScreen.kt index f99978e..2ba59ae 100644 --- a/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthScreen.kt +++ b/app/src/main/java/ru/myitschool/work/ui/screen/auth/AuthScreen.kt @@ -76,7 +76,9 @@ private fun Content( var inputText by remember { mutableStateOf("") } Spacer(modifier = Modifier.size(16.dp)) TextField( - modifier = Modifier.testTag(TestIds.Auth.CODE_INPUT).fillMaxWidth(), + modifier = Modifier + .testTag(TestIds.Auth.CODE_INPUT) + .fillMaxWidth(), value = inputText, onValueChange = { inputText = it @@ -86,7 +88,9 @@ private fun Content( ) Spacer(modifier = Modifier.size(16.dp)) Button( - modifier = Modifier.testTag(TestIds.Auth.SIGN_BUTTON).fillMaxWidth(), + modifier = Modifier + .testTag(TestIds.Auth.SIGN_BUTTON) + .fillMaxWidth(), onClick = { viewModel.onIntent(AuthIntent.Send(inputText)) }, diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/book/BookIntent.kt b/app/src/main/java/ru/myitschool/work/ui/screen/book/BookIntent.kt new file mode 100644 index 0000000..8ca3569 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/screen/book/BookIntent.kt @@ -0,0 +1,4 @@ +package ru.myitschool.work.ui.screen.book + +interface BookIntent { +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/book/BookScreen.kt b/app/src/main/java/ru/myitschool/work/ui/screen/book/BookScreen.kt new file mode 100644 index 0000000..d575ec9 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/screen/book/BookScreen.kt @@ -0,0 +1,75 @@ +package ru.myitschool.work.ui.screen.book + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme +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.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +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.ui.nav.MainScreenDestination +import ru.myitschool.work.ui.screen.auth.AuthState +import ru.myitschool.work.ui.screen.auth.AuthViewModel + +@Composable +fun BookScreen( + viewModel: AuthViewModel = viewModel(), + navController: NavController +) { + val state by viewModel.uiState.collectAsState() + + LaunchedEffect(Unit) { + viewModel.actionFlow.collect { + navController.navigate(MainScreenDestination) + } + } + + Column( + modifier = Modifier + .fillMaxSize() + .padding(all = 24.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Text( + text = stringResource(R.string.auth_title), + style = MaterialTheme.typography.headlineSmall, + textAlign = TextAlign.Center + ) + when (val currentState = state) { + is AuthState.Data -> Content(viewModel, currentState) + is AuthState.Loading -> { + CircularProgressIndicator( + modifier = Modifier.size(64.dp) + ) + } + } + } +} + +@Composable +private fun Content( + viewModel: AuthViewModel, + state: AuthState.Data +) { + var inputText by remember { mutableStateOf("") } + Spacer(modifier = Modifier.size(16.dp)) + +} -- 2.34.1 From f7a2ee8720ae71ff42ae85a983b5e6027cbdd880 Mon Sep 17 00:00:00 2001 From: student Date: Thu, 11 Dec 2025 18:31:23 +0300 Subject: [PATCH 2/4] Finish Commit --- .../work/ui/screen/NavigationGraph.kt | 72 +-------- .../work/ui/screen/book/BookIntent.kt | 3 + .../work/ui/screen/book/BookScreen.kt | 99 +++++++++--- .../work/ui/screen/book/BookState.kt | 8 + .../work/ui/screen/book/BookViewModel.kt | 43 +++++ .../work/ui/screen/book/MainState.kt | 4 + .../work/ui/screen/main/MainIntent.kt | 7 + .../work/ui/screen/main/MainScreen.kt | 153 ++++++++++++++++++ .../work/ui/screen/main/MainState.kt | 8 + .../work/ui/screen/main/MainViewModel.kt | 43 +++++ 10 files changed, 351 insertions(+), 89 deletions(-) create mode 100644 app/src/main/java/ru/myitschool/work/ui/screen/book/BookState.kt create mode 100644 app/src/main/java/ru/myitschool/work/ui/screen/book/BookViewModel.kt create mode 100644 app/src/main/java/ru/myitschool/work/ui/screen/book/MainState.kt create mode 100644 app/src/main/java/ru/myitschool/work/ui/screen/main/MainIntent.kt create mode 100644 app/src/main/java/ru/myitschool/work/ui/screen/main/MainScreen.kt create mode 100644 app/src/main/java/ru/myitschool/work/ui/screen/main/MainState.kt create mode 100644 app/src/main/java/ru/myitschool/work/ui/screen/main/MainViewModel.kt diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/NavigationGraph.kt b/app/src/main/java/ru/myitschool/work/ui/screen/NavigationGraph.kt index 397dd6f..6d209f4 100644 --- a/app/src/main/java/ru/myitschool/work/ui/screen/NavigationGraph.kt +++ b/app/src/main/java/ru/myitschool/work/ui/screen/NavigationGraph.kt @@ -46,6 +46,8 @@ import ru.myitschool.work.ui.nav.MainScreenDestination import ru.myitschool.work.ui.screen.auth.AuthIntent import ru.myitschool.work.ui.screen.auth.AuthScreen import ru.myitschool.work.ui.screen.auth.AuthViewModel +import ru.myitschool.work.ui.screen.book.BookScreen +import ru.myitschool.work.ui.screen.main.MainScreen @Composable @@ -55,11 +57,6 @@ fun AppNavHost( navController: NavHostController = rememberNavController(), ) { - var expanded by remember{ mutableStateOf(false)} - var inputUsername by remember { mutableStateOf("Введите имя") } - val date:String = "" - val username:String = "" - var place:String = "" NavHost( modifier = modifier, @@ -72,71 +69,10 @@ fun AppNavHost( AuthScreen(navController = navController) } composable { - Box( - contentAlignment = Alignment.Center - ) { - Text(text = "") - - } - Column() { - Spacer(modifier = Modifier.size(16.dp)) - Text( - modifier = Modifier.testTag("main_name").fillMaxWidth(), - text = username - ) - Spacer(modifier = Modifier.size(10.dp)) - - Spacer(modifier = Modifier.size(10.dp)) - Row (horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier.fillMaxWidth().padding(8.dp)) { - - Button(onClick = { }) { - Text(text = "Выход") - Modifier - .padding(20.dp) - .fillMaxWidth() - .semantics { testTag = "main_logout_button" } - } - Spacer(modifier = Modifier.size(10.dp)) - Button(onClick = { }) { - Text(text = "Обновить") - Modifier - .padding(20.dp) - .fillMaxWidth() - .semantics { testTag = "main_refresh_button" } - } - Spacer(modifier = Modifier.size(10.dp)) - } - Spacer(modifier = Modifier.size(10.dp)) - - Button(onClick = { expanded = true }) { - Text(text = "бронировать") - Modifier - .padding(20.dp) - .fillMaxWidth() - .semantics { testTag = "main_add_button" } - } - Text( - modifier = Modifier.testTag("main_item_date").fillMaxWidth(), - text = date - ) - Spacer(modifier = Modifier.size(10.dp)) - Text( - modifier = Modifier.testTag("main_item_place").fillMaxWidth(), - text = place - ) - Text(text = "ERROR", - modifier = Modifier.testTag("main_error").fillMaxWidth().alpha(0f)) - - } - + MainScreen(navController = navController) } composable { - Box( - contentAlignment = Alignment.Center - ) { - Text(text = "Hello") - } + BookScreen(navController = navController) } } } diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/book/BookIntent.kt b/app/src/main/java/ru/myitschool/work/ui/screen/book/BookIntent.kt index 8ca3569..f5e1590 100644 --- a/app/src/main/java/ru/myitschool/work/ui/screen/book/BookIntent.kt +++ b/app/src/main/java/ru/myitschool/work/ui/screen/book/BookIntent.kt @@ -1,4 +1,7 @@ package ru.myitschool.work.ui.screen.book + interface BookIntent { + data class Send(val text: String): BookIntent + data class TextInput(val text: String): BookIntent } \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/book/BookScreen.kt b/app/src/main/java/ru/myitschool/work/ui/screen/book/BookScreen.kt index d575ec9..b6de44e 100644 --- a/app/src/main/java/ru/myitschool/work/ui/screen/book/BookScreen.kt +++ b/app/src/main/java/ru/myitschool/work/ui/screen/book/BookScreen.kt @@ -2,12 +2,16 @@ 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.Spacer import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.selection.selectable +import androidx.compose.material3.Button import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -16,23 +20,22 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTag 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.ui.nav.MainScreenDestination -import ru.myitschool.work.ui.screen.auth.AuthState -import ru.myitschool.work.ui.screen.auth.AuthViewModel @Composable fun BookScreen( - viewModel: AuthViewModel = viewModel(), + viewModel: BookViewModel = viewModel(), navController: NavController ) { + val state by viewModel.uiState.collectAsState() LaunchedEffect(Unit) { @@ -45,17 +48,10 @@ fun BookScreen( modifier = Modifier .fillMaxSize() .padding(all = 24.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center ) { - Text( - text = stringResource(R.string.auth_title), - style = MaterialTheme.typography.headlineSmall, - textAlign = TextAlign.Center - ) when (val currentState = state) { - is AuthState.Data -> Content(viewModel, currentState) - is AuthState.Loading -> { + is BookState.Data -> Content(viewModel, currentState) + is BookState.Loading -> { CircularProgressIndicator( modifier = Modifier.size(64.dp) ) @@ -66,10 +62,71 @@ fun BookScreen( @Composable private fun Content( - viewModel: AuthViewModel, - state: AuthState.Data + viewModel: BookViewModel, + state: BookState.Data ) { - var inputText by remember { mutableStateOf("") } - Spacer(modifier = Modifier.size(16.dp)) + val error = false + var selected = false + var input by remember { mutableStateOf("") } + Column() { Row (horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth().padding(8.dp)) { + OutlinedButton(onClick = { }) { + Text("19.04", Modifier.testTag("main_item_place")) + Modifier.semantics { testTag = "main_add_button"}.selectable(selected = selected, onClick = {selected = true }, role = Role.Button) + } + OutlinedButton(onClick = { }) { + Text("20.04", Modifier.testTag("main_item_place")) + Modifier.semantics { testTag = "main_add_button"}.selectable(selected = selected, onClick = {selected = true }, role = Role.Button) + } + OutlinedButton(onClick = { }) { + Text("21.04", Modifier.testTag("main_item_place")) + Modifier.semantics { testTag = "main_add_button"}.selectable(selected = selected, onClick = {selected = true }, role = Role.Button) + } + OutlinedButton(onClick = { }) { + Text("22.04", Modifier.testTag("main_item_place")) + Modifier.semantics { testTag = "main_add_button" }.selectable(selected = selected, onClick = {selected = true }, role = Role.Button) + } + } + Spacer(modifier = Modifier.size(20.dp)) + Text("Рабочее место у окна") + Spacer(modifier = Modifier.size(20.dp)) + Text("Переговорная комната №1") + Spacer(modifier = Modifier.size(20.dp)) + Text("Коворкинг A", Modifier.selectable(selected = selected, onClick = {selected = true}, role = Role.Button)) + Spacer(modifier = Modifier.size(20.dp)) + Row (horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth().padding(8.dp)){ + Button(onClick = { viewModel.onIntent(BookIntent.Send(input)) }) { + Text(text = "Назад") + Modifier + .padding(20.dp) + .fillMaxWidth() + .semantics { testTag = "book_back_button" } + } + Button(onClick = { }) { + Text(text = "Бронировать") + Modifier + .padding(20.dp) + .fillMaxWidth() + .semantics { testTag = "book_book_button" } + } + + } + if (error){ + Spacer(modifier = Modifier.size(20.dp)) + Text("Ошибка", Modifier.testTag("book_error")) + Button(onClick = { }) { + Text(text = "Обновить") + Modifier + .padding(20.dp) + .fillMaxWidth() + .semantics { testTag = "book_refresh_button" } + } + Text("Всё забронировано", Modifier.testTag("book_empty")) + + } + + + } } diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/book/BookState.kt b/app/src/main/java/ru/myitschool/work/ui/screen/book/BookState.kt new file mode 100644 index 0000000..eb69ccd --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/screen/book/BookState.kt @@ -0,0 +1,8 @@ +package ru.myitschool.work.ui.screen.book + +import ru.myitschool.work.ui.screen.auth.AuthState + +interface BookState { + object Loading: BookState + object Data: BookState +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/book/BookViewModel.kt b/app/src/main/java/ru/myitschool/work/ui/screen/book/BookViewModel.kt new file mode 100644 index 0000000..ff9a04f --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/screen/book/BookViewModel.kt @@ -0,0 +1,43 @@ +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 +import ru.myitschool.work.data.repo.AuthRepository +import ru.myitschool.work.domain.auth.CheckAndSaveAuthCodeUseCase + +class BookViewModel: ViewModel() { + private val checkAndSaveAuthCodeUseCase by lazy { CheckAndSaveAuthCodeUseCase(AuthRepository) } + private val _uiState = MutableStateFlow(BookState.Data) + val uiState: StateFlow = _uiState.asStateFlow() + + private val _actionFlow: MutableSharedFlow = MutableSharedFlow() + val actionFlow: SharedFlow = _actionFlow + + fun onIntent(intent: BookIntent) { + when (intent) { + is BookIntent.Send -> { + viewModelScope.launch(Dispatchers.Default) { + _uiState.update { BookState.Loading } + checkAndSaveAuthCodeUseCase.invoke("9999").fold( + onSuccess = { + _actionFlow.emit(Unit) + }, + onFailure = { error -> + error.printStackTrace() + _actionFlow.emit(Unit) + } + ) + } + } + is BookIntent.TextInput -> Unit + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/book/MainState.kt b/app/src/main/java/ru/myitschool/work/ui/screen/book/MainState.kt new file mode 100644 index 0000000..e12c10b --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/screen/book/MainState.kt @@ -0,0 +1,4 @@ +package ru.myitschool.work.ui.screen.book + +interface MainState { +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/main/MainIntent.kt b/app/src/main/java/ru/myitschool/work/ui/screen/main/MainIntent.kt new file mode 100644 index 0000000..40d5c01 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/screen/main/MainIntent.kt @@ -0,0 +1,7 @@ +package ru.myitschool.work.ui.screen.main + + +interface MainIntent { + data class Send(val text: String): MainIntent + data class TextInput(val text: String): MainIntent +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/main/MainScreen.kt b/app/src/main/java/ru/myitschool/work/ui/screen/main/MainScreen.kt new file mode 100644 index 0000000..a0c29f8 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/screen/main/MainScreen.kt @@ -0,0 +1,153 @@ +package ru.myitschool.work.ui.screen.main + + +import androidx.compose.foundation.Image +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.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Button +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +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.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Color.Companion.Gray +import androidx.compose.ui.graphics.painter.ColorPainter +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTag +import androidx.compose.ui.text.style.TextAlign +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.ui.nav.BookScreenDestination +import ru.myitschool.work.ui.nav.MainScreenDestination +import ru.myitschool.work.ui.screen.auth.AuthIntent +import ru.myitschool.work.ui.screen.auth.AuthState +import ru.myitschool.work.ui.screen.auth.AuthViewModel +import ru.myitschool.work.ui.screen.book.BookIntent + +@Composable +fun MainScreen( + viewModel: MainViewModel = viewModel(), + navController: NavController +) { + + val state by viewModel.uiState.collectAsState() + + LaunchedEffect(Unit) { + viewModel.actionFlow.collect { + navController.navigate(BookScreenDestination) + } + } + + Column( + modifier = Modifier + .fillMaxSize() + .padding(all = 24.dp) + ) { + when (val currentState = state) { + is MainState.Data -> Content(viewModel, currentState) + is MainState.Loading -> { + CircularProgressIndicator( + modifier = Modifier.size(64.dp) + ) + } + } + } +} + +@Composable +private fun Content( + viewModel: MainViewModel, + state: MainState.Data +) { + var expanded by remember{ mutableStateOf(false)} + var inputUsername by remember { mutableStateOf("Введите имя") } + var input by remember { mutableStateOf("") } + val date:String = "dd.MM.yyyy" + val username:String = "test" + var place:String = "test" + val error = false + Spacer(modifier = Modifier.size(16.dp)) + Column() { + Spacer(modifier = Modifier.size(16.dp)) + Text( + modifier = Modifier.testTag("main_name").fillMaxWidth(), + text = username + ) + Spacer(modifier = Modifier.size(10.dp)) + Image(painter = ColorPainter(Color.DarkGray), contentDescription = "main_photo", modifier = Modifier.size(50.dp)) + + Spacer(modifier = Modifier.size(10.dp)) + Row (horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth().padding(8.dp)) { + + Button(onClick = { }) { + Text(text = "Выход") + Modifier + .padding(20.dp) + .fillMaxWidth() + .semantics { testTag = "main_logout_button" } + } + Spacer(modifier = Modifier.size(10.dp)) + Button(onClick = { }) { + Text(text = "Обновить") + Modifier + .padding(20.dp) + .fillMaxWidth() + .semantics { testTag = "main_refresh_button" } + } + Spacer(modifier = Modifier.size(10.dp)) + Button(onClick = { + viewModel.onIntent(MainIntent.Send(input)) + }) { + Text(text = "Бронировать") + Modifier + .padding(20.dp) + .fillMaxWidth() + .semantics { testTag = "main_add_button" } + } + Spacer(modifier = Modifier.size(10.dp)) + } + Spacer(modifier = Modifier.size(10.dp)) + + + Text( + modifier = Modifier.testTag("main_item_date").fillMaxWidth(), + text = date + ) + Spacer(modifier = Modifier.size(10.dp)) + Text( + modifier = Modifier.testTag("main_item_place").fillMaxWidth(), + text = place + ) + Text(text = "ERROR", + modifier = Modifier.testTag("main_error").fillMaxWidth().alpha(0f)) + + + } + var inputText by remember { mutableStateOf("") } + Spacer(modifier = Modifier.size(16.dp)) + + +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/main/MainState.kt b/app/src/main/java/ru/myitschool/work/ui/screen/main/MainState.kt new file mode 100644 index 0000000..463915b --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/screen/main/MainState.kt @@ -0,0 +1,8 @@ +package ru.myitschool.work.ui.screen.main + +import ru.myitschool.work.ui.screen.auth.AuthState + +interface MainState { + object Loading: MainState + object Data: MainState +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/main/MainViewModel.kt b/app/src/main/java/ru/myitschool/work/ui/screen/main/MainViewModel.kt new file mode 100644 index 0000000..a69ed85 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/ui/screen/main/MainViewModel.kt @@ -0,0 +1,43 @@ +package ru.myitschool.work.ui.screen.main + +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 +import ru.myitschool.work.data.repo.AuthRepository +import ru.myitschool.work.domain.auth.CheckAndSaveAuthCodeUseCase + +class MainViewModel: ViewModel() { + private val checkAndSaveAuthCodeUseCase by lazy { CheckAndSaveAuthCodeUseCase(AuthRepository) } + private val _uiState = MutableStateFlow(MainState.Data) + val uiState: StateFlow = _uiState.asStateFlow() + private val _actionFlow: MutableSharedFlow = MutableSharedFlow() + val actionFlow: SharedFlow = _actionFlow + + fun onIntent(intent: MainIntent) { + when (intent) { + is MainIntent.Send -> { + viewModelScope.launch(Dispatchers.Default) { + _uiState.update { MainState.Loading } + checkAndSaveAuthCodeUseCase.invoke("9999").fold( + onSuccess = { + _actionFlow.emit(Unit) + }, + onFailure = { error -> + error.printStackTrace() + _actionFlow.emit(Unit) + } + ) + } + } + + is MainIntent.TextInput -> Unit + } + } +} \ No newline at end of file -- 2.34.1 From 2720e410a3d5269382639f158eb9e04a2b5d0960 Mon Sep 17 00:00:00 2001 From: student Date: Thu, 11 Dec 2025 18:48:54 +0300 Subject: [PATCH 3/4] Test Commit --- .../main/java/ru/myitschool/work/ui/screen/main/MainScreen.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/main/MainScreen.kt b/app/src/main/java/ru/myitschool/work/ui/screen/main/MainScreen.kt index a0c29f8..f28f1f4 100644 --- a/app/src/main/java/ru/myitschool/work/ui/screen/main/MainScreen.kt +++ b/app/src/main/java/ru/myitschool/work/ui/screen/main/MainScreen.kt @@ -102,6 +102,7 @@ private fun Content( Row (horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth().padding(8.dp)) { + Button(onClick = { }) { Text(text = "Выход") Modifier -- 2.34.1 From fc7c264b8d342269573ef1a72dd5e8c4fbb5d845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=B3=D0=B0=D1=80=D0=B8=D1=82=D0=B0=20?= =?UTF-8?q?=D0=92=D0=BE=D0=B9=D1=82=D0=BA=D0=B5=D0=B2=D0=B8=D1=87?= Date: Thu, 11 Dec 2025 19:19:36 +0000 Subject: [PATCH 4/4] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20app/src/main/java/ru/myitschool/work/ui/screen/main/Ma?= =?UTF-8?q?inState.kt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/ru/myitschool/work/ui/screen/main/MainState.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/ru/myitschool/work/ui/screen/main/MainState.kt b/app/src/main/java/ru/myitschool/work/ui/screen/main/MainState.kt index 463915b..2692596 100644 --- a/app/src/main/java/ru/myitschool/work/ui/screen/main/MainState.kt +++ b/app/src/main/java/ru/myitschool/work/ui/screen/main/MainState.kt @@ -5,4 +5,5 @@ import ru.myitschool.work.ui.screen.auth.AuthState interface MainState { object Loading: MainState object Data: MainState + } \ No newline at end of file -- 2.34.1