From 77f27e52eb4974e414b2958e26e6bd67cc8e1f08 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 5 Dec 2025 21:33:40 +0300 Subject: [PATCH] final --- .../java/ru/myitschool/work/core/Constants.kt | 2 +- .../work/data/source/NetworkDataSource.kt | 7 +-- .../work/ui/screen/book/BookScreen.kt | 46 ++++++++++--------- .../work/ui/screen/book/BookViewModel.kt | 14 +++++- .../work/ui/screen/main/MainScreen.kt | 3 +- .../work/ui/screen/main/MainViewModel.kt | 15 ++---- 6 files changed, 49 insertions(+), 38 deletions(-) diff --git a/app/src/main/java/ru/myitschool/work/core/Constants.kt b/app/src/main/java/ru/myitschool/work/core/Constants.kt index faca25e..5fe3adf 100644 --- a/app/src/main/java/ru/myitschool/work/core/Constants.kt +++ b/app/src/main/java/ru/myitschool/work/core/Constants.kt @@ -1,7 +1,7 @@ package ru.myitschool.work.core object Constants { - const val HOST = "http://10.230.214.96:8080" + const val HOST = "http://192.168.1.39:8080" const val AUTH_URL = "/auth" const val INFO_URL = "/info" const val BOOKING_URL = "/booking" diff --git a/app/src/main/java/ru/myitschool/work/data/source/NetworkDataSource.kt b/app/src/main/java/ru/myitschool/work/data/source/NetworkDataSource.kt index 8bbab74..732dfa5 100644 --- a/app/src/main/java/ru/myitschool/work/data/source/NetworkDataSource.kt +++ b/app/src/main/java/ru/myitschool/work/data/source/NetworkDataSource.kt @@ -1,5 +1,6 @@ package ru.myitschool.work.data.source +import android.annotation.SuppressLint import android.util.Log import io.ktor.client.HttpClient import io.ktor.client.engine.cio.CIO @@ -151,20 +152,20 @@ object NetworkDataSource { } @Serializable - private data class CreateBookingBody(val date: String, val placeID: Long) + private data class CreateBookingBody(val date: String, val placeId: Long) suspend fun createBooking(code: String, date: LocalDate, placeId: Long): Result = withContext(Dispatchers.IO) { return@withContext runCatching { // Формируем тело запроса val requestBody = CreateBookingBody(date.toString(), placeId) - val response = client.post(getUrl(code, Constants.BOOKING_URL)) { // Используем ту же константу BOOKING_URL + val response = client.post(getUrl(code, Constants.BOOK_URL)) { contentType(ContentType.Application.Json) setBody(requestBody) } when (response.status) { - HttpStatusCode.OK -> true + HttpStatusCode.Created -> true else -> { val errorBody = response.bodyAsText() error(if (errorBody.isNotBlank()) App.context.getString(R.string.error_booking, errorBody) else App.context.getString(R.string.error_booking_default)) 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 71c38ca..461cb78 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 @@ -1,19 +1,34 @@ package ru.myitschool.work.ui.screen.book -import androidx.compose.foundation.layout.* +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.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.selection.selectable -import androidx.compose.material3.* -import androidx.compose.runtime.* +import androidx.compose.material3.Button +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.RadioButton +import androidx.compose.material3.ScrollableTabRow +import androidx.compose.material3.Tab +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.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.testTag import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel -import java.time.LocalDate -import java.time.format.DateTimeFormatter import ru.myitschool.work.core.TestIds import ru.myitschool.work.data.entity.Place +import java.time.LocalDate +import java.time.format.DateTimeFormatter @Composable fun BookScreen( @@ -23,23 +38,19 @@ fun BookScreen( val viewModel: BookViewModel = viewModel() val uiState by viewModel.uiState.collectAsState() - // Обработка действий - val event = viewModel.actionFlow.collectAsState(initial = null) - LaunchedEffect(event.value) { - when (event.value) { - is BookAction.BookSuccess -> { + LaunchedEffect(viewModel.actionFlow) { + viewModel.actionFlow.collect { action -> + if (action is BookAction.BookSuccess) { onBookSuccess() } - else -> {} } } - // Загрузка начальных данных LaunchedEffect(Unit) { viewModel.onIntent(BookIntent.LoadData) } - when (uiState) { + when (val state = uiState) { is BookState.Loading -> { Box( modifier = Modifier.fillMaxSize(), @@ -51,7 +62,7 @@ fun BookScreen( is BookState.Data -> { BookContentScreen( - uiState = uiState as BookState.Data, + uiState = state, onSelectDate = { date -> viewModel.onIntent(BookIntent.SelectDate(date)) }, onSelectPlace = { place -> viewModel.onIntent(BookIntent.SelectPlace(place)) }, onBook = { viewModel.onIntent(BookIntent.BookPlace) }, @@ -71,13 +82,10 @@ fun BookContentScreen( onBack: () -> Unit, onRefresh: () -> Unit ) { - // Сортировка дат по порядку val sortedDates = uiState.dates.sorted() - // Фильтрация дат, для которых есть доступные места val availableDates = sortedDates.filter { date -> uiState.places[date]?.isNotEmpty() == true } Column(modifier = Modifier.fillMaxSize().padding(16.dp)) { - // Вкладки для выбора дат if (availableDates.isNotEmpty()) { ScrollableTabRow( selectedTabIndex = availableDates.indexOf(uiState.selectedDate), @@ -100,7 +108,6 @@ fun BookContentScreen( Spacer(modifier = Modifier.height(16.dp)) - // Список мест для выбранной даты val placesForDate = uiState.selectedDate?.let { uiState.places[it] } ?: emptyList() if (placesForDate.isNotEmpty()) { @@ -131,7 +138,6 @@ fun BookContentScreen( } } - // пустой список (все забронировано) if (availableDates.isEmpty() && !uiState.isError) { Text( text = "Всё забронировано", @@ -139,7 +145,6 @@ fun BookContentScreen( ) } - // ошибка if (uiState.isError) { Text( text = uiState.errorMessage ?: "Ошибка загрузки", @@ -157,7 +162,6 @@ fun BookContentScreen( Spacer(modifier = Modifier.weight(1f)) - // Кнопки: Забронировать и Назад if (!uiState.isError && placesForDate.isNotEmpty()) { Button( onClick = onBook, 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 index c91a5eb..b1b6e4f 100644 --- 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 @@ -1,5 +1,6 @@ package ru.myitschool.work.ui.screen.book +import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.Dispatchers @@ -121,11 +122,22 @@ class BookViewModel : ViewModel() { viewModelScope.launch(Dispatchers.IO) { createBookingUseCase (date, placeId).fold( onSuccess = { + Log.d("AnnaKonda", "method is calling") _actionFlow.emit(BookAction.BookSuccess) }, onFailure = { error -> + Log.d("AnnaKonda", "ERROR method is calling") error.printStackTrace() - _actionFlow.emit(BookAction.ShowError(error.message ?: App.context.getString(R.string.error_booking_default))) + _uiState.update { currentState -> + if (currentState is BookState.Data) { + currentState.copy( + isError = true + ) + } else { + currentState + } + } + // _actionFlow.emit(BookAction.ShowError(error.message ?: App.context.getString(R.string.error_booking_default))) } ) } 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 6bc96dc..38da245 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 @@ -13,6 +13,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavController import coil3.compose.AsyncImage import ru.myitschool.work.core.TestIds @@ -25,7 +26,7 @@ import ru.myitschool.work.ui.nav.BookScreenDestination fun MainScreen( navController: NavController, ) { - val viewModel = MainViewModel() + val viewModel: MainViewModel = viewModel() // Состояния val event = viewModel.actionFlow.collectAsState(initial = null) // Функция загрузки данных 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 index 0355811..8a3f5bb 100644 --- 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 @@ -12,14 +12,10 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import ru.myitschool.work.data.repo.AuthRepository import ru.myitschool.work.data.repo.MainRepository -import ru.myitschool.work.domain.auth.CheckAndSaveAuthCodeUseCase import ru.myitschool.work.domain.main.GetUserDataUseCase -import ru.myitschool.work.ui.screen.auth.AuthAction -import ru.myitschool.work.ui.screen.auth.AuthIntent -import ru.myitschool.work.ui.screen.auth.AuthState class MainViewModel : ViewModel() { - private val repository by lazy{ MainRepository() } + private val repository by lazy { MainRepository() } private val getUserDataUseCase by lazy { GetUserDataUseCase(repository) } private val _uiState = MutableStateFlow(MainState.Loading) @@ -28,15 +24,12 @@ class MainViewModel : ViewModel() { private val _actionFlow: MutableSharedFlow = MutableSharedFlow() val actionFlow: SharedFlow = _actionFlow - init { - loadData() - } - fun onIntent(intent: MainIntent) { when (intent) { - is MainIntent.LoadData -> { + is MainIntent.LoadData -> { loadData() } + is MainIntent.LogOut -> { viewModelScope.launch(Dispatchers.IO) { _uiState.update { MainState.Data(null) } @@ -46,7 +39,7 @@ class MainViewModel : ViewModel() { } } - fun loadData() { + private fun loadData() { viewModelScope.launch(Dispatchers.IO) { _uiState.update { MainState.Loading }