From fd8309521ddba38d2e9c5d06e306bcfb0706f944 Mon Sep 17 00:00:00 2001 From: imglmd Date: Mon, 1 Dec 2025 16:53:39 +0300 Subject: [PATCH] yo --- .../work/data/dto/AvailableBookingResponse.kt | 14 ++++ .../myitschool/work/data/dto/BookRequest.kt | 9 +++ .../work/data/dto/UserInfoResponse.kt | 16 +++++ .../work/data/repo/AuthRepository.kt | 9 +-- .../work/data/source/NetworkDataSource.kt | 32 +++++++-- .../ru/myitschool/work/domain/MyResult.kt | 6 ++ .../auth/CheckAndSaveAuthCodeUseCase.kt | 26 +++---- .../work/domain/user/GetUserUseCase.kt | 4 ++ .../ru/myitschool/work/domain/user/User.kt | 6 ++ .../myitschool/work/ui/auth/AuthViewModel.kt | 72 ++++++++++--------- 10 files changed, 139 insertions(+), 55 deletions(-) create mode 100644 app/src/main/java/ru/myitschool/work/data/dto/AvailableBookingResponse.kt create mode 100644 app/src/main/java/ru/myitschool/work/data/dto/BookRequest.kt create mode 100644 app/src/main/java/ru/myitschool/work/data/dto/UserInfoResponse.kt create mode 100644 app/src/main/java/ru/myitschool/work/domain/MyResult.kt create mode 100644 app/src/main/java/ru/myitschool/work/domain/user/GetUserUseCase.kt create mode 100644 app/src/main/java/ru/myitschool/work/domain/user/User.kt diff --git a/app/src/main/java/ru/myitschool/work/data/dto/AvailableBookingResponse.kt b/app/src/main/java/ru/myitschool/work/data/dto/AvailableBookingResponse.kt new file mode 100644 index 0000000..e67dc6b --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/data/dto/AvailableBookingResponse.kt @@ -0,0 +1,14 @@ +package ru.myitschool.work.data.dto + +import kotlinx.serialization.Serializable + +@Serializable +data class AvailableBookingResponse( + val dates: Map> = emptyMap() +) + +@Serializable +data class AvailablePlace( + val id: Int, + val place: String +) diff --git a/app/src/main/java/ru/myitschool/work/data/dto/BookRequest.kt b/app/src/main/java/ru/myitschool/work/data/dto/BookRequest.kt new file mode 100644 index 0000000..1b93d30 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/data/dto/BookRequest.kt @@ -0,0 +1,9 @@ +package ru.myitschool.work.data.dto + +import kotlinx.serialization.Serializable + +@Serializable +data class BookRequest( + val date: String, + val placeID: Int +) \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/data/dto/UserInfoResponse.kt b/app/src/main/java/ru/myitschool/work/data/dto/UserInfoResponse.kt new file mode 100644 index 0000000..0edc9d8 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/data/dto/UserInfoResponse.kt @@ -0,0 +1,16 @@ +package ru.myitschool.work.data.dto + +import kotlinx.serialization.Serializable + +@Serializable +data class UserInfoResponse( + val name: String, + val photoUrl: String, + val booking: Map = emptyMap() +) + +@Serializable +data class BookingItem( + val id: Int, + val place: String +) \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/data/repo/AuthRepository.kt b/app/src/main/java/ru/myitschool/work/data/repo/AuthRepository.kt index 3ef28f1..5babf1a 100644 --- a/app/src/main/java/ru/myitschool/work/data/repo/AuthRepository.kt +++ b/app/src/main/java/ru/myitschool/work/data/repo/AuthRepository.kt @@ -1,16 +1,13 @@ package ru.myitschool.work.data.repo import ru.myitschool.work.data.source.NetworkDataSource +import ru.myitschool.work.domain.MyResult object AuthRepository { private var codeCache: String? = null - suspend fun checkAndSave(text: String): Result { - return NetworkDataSource.checkAuth(text).onSuccess { success -> - if (success) { - codeCache = text - } - } + suspend fun checkAndSave(code: String): MyResult { + return NetworkDataSource.checkAuth(code) } } \ No newline at end of file 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 fbdfef5..e571623 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,16 +1,18 @@ package ru.myitschool.work.data.source import io.ktor.client.HttpClient +import io.ktor.client.call.body import io.ktor.client.engine.cio.CIO import io.ktor.client.plugins.contentnegotiation.ContentNegotiation import io.ktor.client.request.get -import io.ktor.client.statement.bodyAsText import io.ktor.http.HttpStatusCode import io.ktor.serialization.kotlinx.json.json import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import kotlinx.serialization.json.Json import ru.myitschool.work.core.Constants +import ru.myitschool.work.data.dto.UserInfoResponse +import ru.myitschool.work.domain.MyResult object NetworkDataSource { private val client by lazy { @@ -28,15 +30,35 @@ object NetworkDataSource { } } - suspend fun checkAuth(code: String): Result = withContext(Dispatchers.IO) { - return@withContext runCatching { + suspend fun checkAuth(code: String): MyResult = withContext(Dispatchers.IO) { + try { val response = client.get(getUrl(code, Constants.AUTH_URL)) when (response.status) { - HttpStatusCode.OK -> true - else -> error(response.bodyAsText()) + HttpStatusCode.OK -> MyResult.Success(true) + else -> { + MyResult.Error("Неверный код или ошибка сервера") + } } + } catch (e: Exception) { + MyResult.Error("Сетевая ошибка") } } + suspend fun getUserInfo(code: String): MyResult = withContext(Dispatchers.IO){ + try { + val response = client.get(getUrl(code, Constants.INFO_URL)) + when (response.status) { + HttpStatusCode.OK -> { + val userInfo: UserInfoResponse = response.body() + MyResult.Success(userInfo) + } + else -> { + MyResult.Error("Ошибка получения данных пользователя") + } + } + } catch (e: Exception){ + MyResult.Error("Сетевая ошибка") + } + } private fun getUrl(code: String, targetUrl: String) = "${Constants.HOST}/api/$code$targetUrl" } \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/domain/MyResult.kt b/app/src/main/java/ru/myitschool/work/domain/MyResult.kt new file mode 100644 index 0000000..43ce82f --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/domain/MyResult.kt @@ -0,0 +1,6 @@ +package ru.myitschool.work.domain + +sealed class MyResult { + data class Success(val data: T): MyResult() + data class Error(val error: String): MyResult() +} diff --git a/app/src/main/java/ru/myitschool/work/domain/auth/CheckAndSaveAuthCodeUseCase.kt b/app/src/main/java/ru/myitschool/work/domain/auth/CheckAndSaveAuthCodeUseCase.kt index e308ad2..48d846c 100644 --- a/app/src/main/java/ru/myitschool/work/domain/auth/CheckAndSaveAuthCodeUseCase.kt +++ b/app/src/main/java/ru/myitschool/work/domain/auth/CheckAndSaveAuthCodeUseCase.kt @@ -1,23 +1,25 @@ package ru.myitschool.work.domain.auth -import androidx.datastore.dataStore import ru.myitschool.work.data.repo.AuthRepository +import ru.myitschool.work.domain.MyResult import ru.myitschool.work.util.DataStoreManager class CheckAndSaveAuthCodeUseCase( private val repository: AuthRepository, ) { - suspend operator fun invoke( - code: String - ): Result = try { - val response = repository.checkAndSave(code) - if (response.isSuccess) { - DataStoreManager.saveAuthCode(code) - Result.success(Unit) - } else { - Result.failure(Exception("Неверный код")) + suspend operator fun invoke(code: String): MyResult { + return when (val repoResult = repository.checkAndSave(code)) { + is MyResult.Success -> { + if (repoResult.data) { + DataStoreManager.saveAuthCode(code) + MyResult.Success(Unit) + } else { + MyResult.Error("Неверный код") + } + } + is MyResult.Error -> { + MyResult.Error(repoResult.error) + } } - } catch (e: Exception){ - Result.failure(e) } } \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/domain/user/GetUserUseCase.kt b/app/src/main/java/ru/myitschool/work/domain/user/GetUserUseCase.kt new file mode 100644 index 0000000..e85f569 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/domain/user/GetUserUseCase.kt @@ -0,0 +1,4 @@ +package ru.myitschool.work.domain.user + +class GetUserUseCase { +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/domain/user/User.kt b/app/src/main/java/ru/myitschool/work/domain/user/User.kt new file mode 100644 index 0000000..9155712 --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/domain/user/User.kt @@ -0,0 +1,6 @@ +package ru.myitschool.work.domain.user + +data class User( + val name: String, + val imageUrl: String +) diff --git a/app/src/main/java/ru/myitschool/work/ui/auth/AuthViewModel.kt b/app/src/main/java/ru/myitschool/work/ui/auth/AuthViewModel.kt index 79628f6..4160a4a 100644 --- a/app/src/main/java/ru/myitschool/work/ui/auth/AuthViewModel.kt +++ b/app/src/main/java/ru/myitschool/work/ui/auth/AuthViewModel.kt @@ -8,6 +8,7 @@ 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.MyResult import ru.myitschool.work.domain.auth.CheckAndSaveAuthCodeUseCase class AuthViewModel : ViewModel() { @@ -17,41 +18,48 @@ class AuthViewModel : ViewModel() { fun onIntent(intent: AuthIntent) { when (intent) { - is AuthIntent.Send -> { - viewModelScope.launch { + AuthIntent.Send -> sendCode() + is AuthIntent.TextInput -> updateCode(intent.text) + } + } + + + private fun updateCode(newCode: String) { + val trimmed = newCode.trim() + val isValid = trimmed.length == 4 && trimmed.matches(Regex("^[a-zA-Z0-9]{4}$")) + + _uiState.update { + it.copy( + code = trimmed, + isButtonEnabled = isValid, + error = null + ) + } + } + + private fun sendCode() { + val currentCode = _uiState.value.code + if (currentCode.length != 4 || !currentCode.matches(Regex("^[a-zA-Z0-9]{4}$"))) return + + viewModelScope.launch { + _uiState.update { it.copy(isLoading = true, error = null) } + + when (val result = checkAndSaveAuthCodeUseCase(currentCode)){ + is MyResult.Success<*> -> { _uiState.update { - it.copy(isLoading = true) + it.copy(isLoading = false, isAuthenticated = true) + } + } + + is MyResult.Error -> { + _uiState.update { + it.copy( + isLoading = false, + error = result.error, + isAuthenticated = false + ) } - - checkAndSaveAuthCodeUseCase(_uiState.value.code).fold( - onSuccess = { - _uiState.update { - it.copy( - isLoading = false, - isAuthenticated = true - ) - } - - }, - onFailure = { error -> - _uiState.update { - it.copy( - isLoading = false, - error = error.message ?: "Ошибка", - isAuthenticated = false - ) - } - } - ) } - } - is AuthIntent.TextInput -> _uiState.update { - it.copy( - code = intent.text, - isButtonEnabled = intent.text.length == 4 && - uiState.value.code.matches(Regex("^[a-zA-Z0-9]+$")), - error = null - ) } } }