diff --git a/api-core/src/main/java/com/example/api/core/data/core/ApiService.kt b/api-core/src/main/java/com/example/api/core/data/core/ApiService.kt index 212d4b3..e298ed4 100644 --- a/api-core/src/main/java/com/example/api/core/data/core/ApiService.kt +++ b/api-core/src/main/java/com/example/api/core/data/core/ApiService.kt @@ -1,8 +1,9 @@ package com.example.api.core.data.core import com.example.api.core.data.dto.AuthUserResponseDto -import com.example.api.core.data.dto.RegisterUserDto import com.example.api.core.data.dto.ProjectsDto +import com.example.api.core.data.dto.RegisterUserDto +import com.example.api.core.data.dto.SalesAndNewsDto import com.example.api.core.data.dto.SignInUserDto import com.example.api.core.data.dto.UserResponseDto import retrofit2.http.Body @@ -25,6 +26,6 @@ internal interface ApiService { @GET("collections/project/records") suspend fun projects(): ProjectsDto -// @GET("collections/products/records") -// suspend fun products(): + @GET("collections/news/records") + suspend fun salesAndNews(): SalesAndNewsDto } \ No newline at end of file diff --git a/api-core/src/main/java/com/example/api/core/data/dto/SalesAndNewsDto.kt b/api-core/src/main/java/com/example/api/core/data/dto/SalesAndNewsDto.kt new file mode 100644 index 0000000..c30fdc4 --- /dev/null +++ b/api-core/src/main/java/com/example/api/core/data/dto/SalesAndNewsDto.kt @@ -0,0 +1,12 @@ +package com.example.api.core.data.dto + +import kotlinx.serialization.Serializable + +@Serializable +internal data class SalesAndNewsDto( + val items: List, + val page: Int, + val perPage: Int, + val totalItems: Int, + val totalPages: Int +) diff --git a/api-core/src/main/java/com/example/api/core/data/dto/SalesAndNewsItemDto.kt b/api-core/src/main/java/com/example/api/core/data/dto/SalesAndNewsItemDto.kt new file mode 100644 index 0000000..0f35070 --- /dev/null +++ b/api-core/src/main/java/com/example/api/core/data/dto/SalesAndNewsItemDto.kt @@ -0,0 +1,13 @@ +package com.example.api.core.data.dto + +import kotlinx.serialization.Serializable + +@Serializable +internal data class SalesAndNewsItemDto( + val collectionId: String, + val collectionName: String, + val created: String, + val id: String, + val newsImage: String, + val updated: String +) diff --git a/api-core/src/test/java/com/example/api/core/ServiceTest.kt b/api-core/src/test/java/com/example/api/core/ServiceTest.kt index b4c9463..aaf3ab2 100644 --- a/api-core/src/test/java/com/example/api/core/ServiceTest.kt +++ b/api-core/src/test/java/com/example/api/core/ServiceTest.kt @@ -169,6 +169,49 @@ class ServiceTest { assertEquals("/collections/project/records", request.path) } + @Test + fun test_sales_and_news() = runBlocking { + val response = """ + { + "items": [ + { + "collectionId": "pbc_2599178718", + "collectionName": "News", + "created": "2025-05-26 14:21:46.284Z", + "id": "yxe08bp4woz996w", + "newsImage": "banner_u9uqsy4sf9.png", + "updated": "2025-05-26 15:29:41.083Z" + }, + { + "collectionId": "pbc_2599178718", + "collectionName": "News", + "created": "2025-05-26 15:29:50.831Z", + "id": "lqg3hpgn46efgmz", + "newsImage": "banner_2_10pjar2fq7.png", + "updated": "2025-05-26 15:29:50.831Z" + } + ], + "page": 1, + "perPage": 30, + "totalItems": 2, + "totalPages": 1 + } + """.trimIndent() + + mockWebServer.enqueue(MockResponse().setResponseCode(200).setBody(response)) + + val responseResult = service.salesAndNews() + + val request = mockWebServer.takeRequest() + + assertEquals(2, responseResult.items.size) + assertEquals("News", responseResult.items.first().collectionName) + assertEquals("lqg3hpgn46efgmz", responseResult.items[1].id) + + assertEquals("GET", request.method) + assertEquals("/collections/news/records", request.path) + } + @After fun teardown() { mockWebServer.shutdown() diff --git a/app/src/main/java/com/example/api/BaseViewModel.kt b/app/src/main/java/com/example/api/BaseViewModel.kt new file mode 100644 index 0000000..19ba93b --- /dev/null +++ b/app/src/main/java/com/example/api/BaseViewModel.kt @@ -0,0 +1,25 @@ +package com.example.api + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +/** + * Автор: Манякин Дмитрий (user5) + * Дата создания: 27.05.2025 + * */ + +abstract class BaseViewModel : ViewModel() { + + protected fun handle(action: suspend () -> T, ui: (T) -> Unit) { + viewModelScope.launch(Dispatchers.IO) { + val result = action.invoke() + + withContext(Dispatchers.Main) { + ui.invoke(result) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/api/MainViewModel.kt b/app/src/main/java/com/example/api/MainViewModel.kt index f221c2b..6939f97 100644 --- a/app/src/main/java/com/example/api/MainViewModel.kt +++ b/app/src/main/java/com/example/api/MainViewModel.kt @@ -1,18 +1,13 @@ package com.example.api -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope import com.example.api.core.domain.ApiRepository import com.example.api.core.domain.AuthUserResponse -import com.example.api.core.domain.RegisterUser import com.example.api.core.domain.Projects +import com.example.api.core.domain.RegisterUser import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext import javax.inject.Inject /** @@ -23,41 +18,39 @@ import javax.inject.Inject @HiltViewModel class MainViewModel @Inject constructor( private val apiRepository: ApiRepository -) : ViewModel() { +) : BaseViewModel() { private val _authUiState = MutableStateFlow>(FetchResultUiState.Initial()) val authUiState: StateFlow> get() = _authUiState.asStateFlow() - private val _ProjectsUiState = + private val _projectsUiState = MutableStateFlow>(FetchResultUiState.Initial()) val projectsUiState: StateFlow> - get() = _ProjectsUiState.asStateFlow() + get() = _projectsUiState.asStateFlow() fun auth(email: String, password: String) { - viewModelScope.launch(Dispatchers.IO) { - val result = apiRepository.auth( - RegisterUser( - email = email, - password = password, - passwordConfirm = password + handle( + action = { + apiRepository.auth( + RegisterUser( + email = email, + password = password, + passwordConfirm = password + ) ) - ) - - withContext(Dispatchers.Main) { - _authUiState.value = result.map(FetchResultMapper()) } + ) { + _authUiState.value = it.map(FetchResultMapper()) } } fun salesAndProjects() { - viewModelScope.launch(Dispatchers.IO) { - val result = apiRepository.projects() - - withContext(Dispatchers.Main) { - _ProjectsUiState.value = result.map(FetchResultMapper()) - } + handle( + action = { apiRepository.projects() } + ) { + _projectsUiState.value = it.map(FetchResultMapper()) } } } \ No newline at end of file diff --git a/app/src/main/java/com/example/api/SalesAndNews.kt b/app/src/main/java/com/example/api/SalesAndNews.kt new file mode 100644 index 0000000..ccf2a53 --- /dev/null +++ b/app/src/main/java/com/example/api/SalesAndNews.kt @@ -0,0 +1,9 @@ +package com.example.api + +data class SalesAndNews( + val items: List, + val page: Int, + val perPage: Int, + val totalItems: Int, + val totalPages: Int +) diff --git a/app/src/main/java/com/example/api/SalesAndNewsItem.kt b/app/src/main/java/com/example/api/SalesAndNewsItem.kt new file mode 100644 index 0000000..5a502b0 --- /dev/null +++ b/app/src/main/java/com/example/api/SalesAndNewsItem.kt @@ -0,0 +1,10 @@ +package com.example.api + +data class SalesAndNewsItem( + val collectionId: String, + val collectionName: String, + val created: String, + val id: String, + val newsImage: String, + val updated: String +)