Compare commits

7 Commits

Author SHA1 Message Date
2d9682ebba merge upstream 2025-12-05 18:33:07 +00:00
655baf713f I made the logic for moving between screens and added stubs 2025-12-05 21:32:25 +03:00
32cdc2b3a6 Merge pull request 'add booking to main branch' (#4) from student-15047/NTO-2025-Android-TeamTask:main into main
Reviewed-on: student-18211/NTO-2025-Android-TeamTask#4
2025-12-05 17:24:18 +00:00
f632ddbe2b Merge remote-tracking branch 'origin/main'
# Conflicts:
#	app/src/main/java/ru/myitschool/work/ui/screen/NavigationGraph.kt
#	app/src/main/java/ru/myitschool/work/ui/screen/book/BookIntent.kt
#	app/src/main/java/ru/myitschool/work/ui/screen/book/BookScreen.kt
#	app/src/main/java/ru/myitschool/work/ui/screen/book/BookState.kt
#	app/src/main/java/ru/myitschool/work/ui/screen/book/BookViewModel.kt
#	app/src/main/res/values/strings.xml
2025-12-05 18:31:20 +03:00
f5ff5dbca8 I merge fork 2025-12-05 18:28:06 +03:00
47e9018b67 revert abc0f81356
revert Merge pull request 'Added appearance and basic booking functionality' (#1) from student-15047/NTO-2025-Android-TeamTask:to-book into main

Reviewed-on: student-18211/NTO-2025-Android-TeamTask#1
2025-11-30 16:05:59 +00:00
abc0f81356 Merge pull request 'Added appearance and basic booking functionality' (#1) from student-15047/NTO-2025-Android-TeamTask:to-book into main
Reviewed-on: student-18211/NTO-2025-Android-TeamTask#1
2025-11-30 16:04:45 +00:00
6 changed files with 53 additions and 24 deletions

View File

@@ -1,11 +1,21 @@
package ru.myitschool.work.data.repo
import android.content.Context
import ru.myitschool.work.App
import ru.myitschool.work.data.source.NetworkDataSource
object AuthRepository {
private var codeCache: String? = null
private const val PREF_NAME = "auth_prefs"
private const val KEY_SAVED_CODE = "saved_code"
private val context: Context get() = App.context
private fun loadSavedCode(): String? {
// return context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
// .getString(KEY_SAVED_CODE, null)
return ""
}
fun getSavedCode(): String? = loadSavedCode()
suspend fun checkAndSave(text: String): Result<Boolean> {
return NetworkDataSource.checkAuth(text).onSuccess { success ->
if (success) {

View File

@@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column
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.layout.size
import androidx.compose.material3.Button
@@ -21,7 +22,6 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
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.res.stringResource
import androidx.compose.ui.text.style.TextAlign
@@ -74,6 +74,11 @@ private fun Content(
state: AuthState.Data
) {
var inputText by remember { mutableStateOf("") }
val isValidCode = inputText.length >= 4 && inputText.isNotEmpty() && inputText.none { it.isWhitespace() } && inputText.all { ch ->
ch in '0'..'9' || ch in 'A'..'Z' || ch in 'a'..'z'
}
Spacer(modifier = Modifier.size(16.dp))
TextField(
modifier = Modifier.testTag(TestIds.Auth.CODE_INPUT).fillMaxWidth(),
@@ -82,15 +87,23 @@ private fun Content(
inputText = it
viewModel.onIntent(AuthIntent.TextInput(it))
},
label = { Text(stringResource(R.string.auth_label)) }
label = { Text(stringResource(R.string.auth_label)) },
)
if (state.error != null) {
Text(
text = state.error,
color = MaterialTheme.colorScheme.error,
modifier = Modifier
.testTag(TestIds.Auth.ERROR)
)
}
Spacer(modifier = Modifier.size(16.dp))
Button(
modifier = Modifier.testTag(TestIds.Auth.SIGN_BUTTON).fillMaxWidth(),
onClick = {
viewModel.onIntent(AuthIntent.Send(inputText))
},
enabled = true
enabled = isValidCode
) {
Text(stringResource(R.string.auth_sign_in))
}

View File

@@ -2,5 +2,7 @@ package ru.myitschool.work.ui.screen.auth
sealed interface AuthState {
object Loading: AuthState
object Data: AuthState
data class Data(
val error: String? = null
) : AuthState
}

View File

@@ -15,7 +15,7 @@ import ru.myitschool.work.domain.auth.CheckAndSaveAuthCodeUseCase
class AuthViewModel : ViewModel() {
private val checkAndSaveAuthCodeUseCase by lazy { CheckAndSaveAuthCodeUseCase(AuthRepository) }
private val _uiState = MutableStateFlow<AuthState>(AuthState.Data)
private val _uiState = MutableStateFlow<AuthState>(AuthState.Data())
val uiState: StateFlow<AuthState> = _uiState.asStateFlow()
private val _actionFlow: MutableSharedFlow<Unit> = MutableSharedFlow()
@@ -26,18 +26,21 @@ class AuthViewModel : ViewModel() {
is AuthIntent.Send -> {
viewModelScope.launch(Dispatchers.Default) {
_uiState.update { AuthState.Loading }
checkAndSaveAuthCodeUseCase.invoke("9999").fold(
checkAndSaveAuthCodeUseCase.invoke(intent.text).fold(
onSuccess = {
_actionFlow.emit(Unit)
_actionFlow.emit(Unit)// переход на MainScreen
},
onFailure = { error ->
error.printStackTrace()
_actionFlow.emit(Unit)
_uiState.update {
AuthState.Data(error.message ?: "Неверный код для авторизации")
}
}
)
}
}
is AuthIntent.TextInput -> Unit
is AuthIntent.TextInput -> {
_uiState.update { AuthState.Data() }
}
}
}
}

View File

@@ -49,10 +49,9 @@ fun BookScreen(
LaunchedEffect(Unit) {
Log.d("BookScreen", "1")
viewModel.navigationFlow.collect {
// TODO настроить наконец это переход между экранами
// Log.d("BookScreen", "2")
when (it) {
viewModel.navigationFlow.collect { event ->
Log.d("navigation", "Event received: $event")
when (event) {
BookNavigationEvent.NavigateToMain -> {
Log.d("BookScreen", "3")
navController.navigate(MainScreenDestination)

View File

@@ -8,6 +8,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
@@ -18,21 +19,18 @@ import ru.myitschool.work.ui.screen.Booking
class BookViewModel : ViewModel() {
private val _uiState = MutableStateFlow<BookState>(BookState.Loading)
val uiState: StateFlow<BookState> = _uiState.asStateFlow();
private val _actionFlow: MutableSharedFlow<Unit> = MutableSharedFlow()
val actionFlow: SharedFlow<Unit> = _actionFlow
private val _navigationFlow = MutableSharedFlow<BookNavigationEvent>()
val navigationFlow: SharedFlow<BookNavigationEvent> = _navigationFlow
val navigationFlow: SharedFlow<BookNavigationEvent> = _navigationFlow.asSharedFlow()
init {
loadData()
}
private fun loadData() {
_uiState.update { BookState.Loading }
viewModelScope.launch(Dispatchers.IO) {
_uiState.update { BookState.Loading }
val code = AuthRepository.getSavedCode() ?: run {
onIntent(BookIntent.ToAuthScreen)
_navigationFlow.emit(BookNavigationEvent.NavigateToAuth)
Log.d("", "Go to AuthScreen")
return@launch
}
@@ -90,7 +88,7 @@ class BookViewModel : ViewModel() {
_uiState.update { BookState.Loading }
BookRepository.sendData(intent.code, intent.booking).fold(
onSuccess = {
_actionFlow.emit(Unit)
_navigationFlow.tryEmit(BookNavigationEvent.NavigateToMain)
},
onFailure = { error ->
BookState.Error(error.message ?: "Неизвестная ошибка")
@@ -99,11 +97,15 @@ class BookViewModel : ViewModel() {
}
}
BookIntent.BackToMainScreen -> {
_navigationFlow.tryEmit(BookNavigationEvent.NavigateToMain)
viewModelScope.launch {
_navigationFlow.emit(BookNavigationEvent.NavigateToMain)
}
}
BookIntent.LoadData -> loadData()
BookIntent.ToAuthScreen -> {
_navigationFlow.tryEmit(BookNavigationEvent.NavigateToAuth)
viewModelScope.launch {
_navigationFlow.emit(BookNavigationEvent.NavigateToAuth)
}
}
}
}