diff --git a/app/src/main/java/ru/myitschool/work/data/UserRepositoryImpl.kt b/app/src/main/java/ru/myitschool/work/data/UserRepositoryImpl.kt index 8c86cd6..c5b1ddb 100644 --- a/app/src/main/java/ru/myitschool/work/data/UserRepositoryImpl.kt +++ b/app/src/main/java/ru/myitschool/work/data/UserRepositoryImpl.kt @@ -1,6 +1,5 @@ package ru.myitschool.work.data -import android.util.Log import ru.myitschool.work.data.dto.UserDto import ru.myitschool.work.data.local.CredentialsLocalDataSource import ru.myitschool.work.data.local.UserLocalDataSource @@ -19,9 +18,15 @@ class UserRepositoryImpl( return runCatching { networkDataSource.login(credentialsLocalDataSource.updateToken(login, password)) - .onSuccess { dto -> - map(dto).onSuccess { userLocalDataSource.cacheData(it) } - } + .fold( + onSuccess = { dto -> + map(dto).fold( + onSuccess = { userLocalDataSource.cacheData(it) }, + onFailure = { error(it) } + ) + }, + onFailure = { error(it) } + ) } } @@ -45,15 +50,26 @@ class UserRepositoryImpl( return userLocalDataSource.getUser()!! } - private fun map(userDto: UserDto): Result { + private suspend fun map(userDto: UserDto): Result { return runCatching { UserEntity( - id = userDto.id ?: error("Null user id"), name = userDto.name ?: error("Null user name"), lastVisit = userDto.lastVisit ?: error("Null user lastVisit"), photoUrl = userDto.photoUrl ?: error("Null user photoUrl"), - position = userDto.position ?: error("Null user position") + position = userDto.position ?: error("Null user position"), + isAdmin = userDto.roleId?.let { it -> + networkDataSource.isRoleHasAdminPermissions( + it, + credentialsLocalDataSource.getToken() + ).fold(onSuccess = { it }, onFailure = { error(it) }) + } ?: error("Null user roleId") ) } } + + override suspend fun getUserByLogin(login: String): Result { + return networkDataSource.getUserByLogin(login, credentialsLocalDataSource.getToken()).fold( + onSuccess = { map(it) }, onFailure = { error(it) } + ) + } } \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/data/dto/UserDto.kt b/app/src/main/java/ru/myitschool/work/data/dto/UserDto.kt index 0e5f2cf..71a90d1 100644 --- a/app/src/main/java/ru/myitschool/work/data/dto/UserDto.kt +++ b/app/src/main/java/ru/myitschool/work/data/dto/UserDto.kt @@ -1,31 +1,22 @@ -package ru.myitschool.work.data.dto; +package ru.myitschool.work.data.dto - -import androidx.annotation.Nullable; - -import com.google.gson.annotations.SerializedName; - -import kotlinx.serialization.Serializable; +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable @Serializable -public class UserDto { - - @Nullable - @SerializedName("id") - public String id; - @Nullable - @SerializedName("name") - public String name; - @Nullable - @SerializedName("lastVisit") - public String lastVisit; - @Nullable - @SerializedName("photo") - public String photoUrl; - @Nullable - @SerializedName("position") - public String position; - @Nullable - @SerializedName("login") - public String login; -} +data class UserDto( + @SerialName("roleId") + val roleId: Int?, + @SerialName("name") + val name: String?, + @SerialName("lastVisit") + val lastVisit: String?, + @SerialName("photo") + val photoUrl: String?, + @SerialName("position") + val position: String?, + @SerialName("login") + val login: String?, + @SerialName("isCardBlocked") + val isCardBlocked: Boolean? +) diff --git a/app/src/main/java/ru/myitschool/work/data/network/UserNetworkDataSource.kt b/app/src/main/java/ru/myitschool/work/data/network/UserNetworkDataSource.kt index 6fb986b..d5024a5 100644 --- a/app/src/main/java/ru/myitschool/work/data/network/UserNetworkDataSource.kt +++ b/app/src/main/java/ru/myitschool/work/data/network/UserNetworkDataSource.kt @@ -14,7 +14,7 @@ object UserNetworkDataSource { suspend fun isUserExist(login: String): Result = withContext(Dispatchers.IO) { runCatching { - val result = KtorClient.client.get("${Constants.SERVER_ADDRESS}/api/users/username/$login") + val result = KtorClient.client.get("${Constants.SERVER_ADDRESS}/api/employees/$login") result.status == HttpStatusCode.OK } } @@ -22,16 +22,45 @@ object UserNetworkDataSource { suspend fun login(token: String): Result = withContext(Dispatchers.IO) { runCatching { - val result = KtorClient.client.get("${Constants.SERVER_ADDRESS}/api/users/login") { - headers { - append(HttpHeaders.Authorization, token) + val result = + KtorClient.client.get("${Constants.SERVER_ADDRESS}/api/employees/login") { + headers { + append(HttpHeaders.Authorization, token) + } } - } if (result.status != HttpStatusCode.OK) error("Status ${result.status}") result.body() } } - suspend fun getUserByLogin() {} + suspend fun isRoleHasAdminPermissions(roleId: Int, token: String): Result = + withContext(Dispatchers.IO) { + runCatching { + val response = + KtorClient.client.get("${Constants.SERVER_ADDRESS}/api/roles/info?$roleId") { + headers { + append(HttpHeaders.Authorization, token) + } + } + + response.status == HttpStatusCode.OK + } + } + + suspend fun getUserByLogin(login: String, token: String): Result = + withContext(Dispatchers.IO) { + runCatching { + val response = + KtorClient.client.get("${Constants.SERVER_ADDRESS}/api/employees/find?${login}") { + headers { + append(HttpHeaders.Authorization, token) + } + } + + if (response.status == HttpStatusCode.OK) + error("Status ${response.status}") + response.body() + } + } } \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/domain/entities/UserEntity.kt b/app/src/main/java/ru/myitschool/work/domain/entities/UserEntity.kt index 2e9d7b7..e453de3 100644 --- a/app/src/main/java/ru/myitschool/work/domain/entities/UserEntity.kt +++ b/app/src/main/java/ru/myitschool/work/domain/entities/UserEntity.kt @@ -1,9 +1,10 @@ package ru.myitschool.work.domain.entities data class UserEntity( - val id: String, + val isAdmin: Boolean, val name: String, val lastVisit: String, val photoUrl: String, val position: String, + ) diff --git a/app/src/main/java/ru/myitschool/work/domain/user/GetUserByLoginUseCase.kt b/app/src/main/java/ru/myitschool/work/domain/user/GetUserByLoginUseCase.kt new file mode 100644 index 0000000..6e6d02b --- /dev/null +++ b/app/src/main/java/ru/myitschool/work/domain/user/GetUserByLoginUseCase.kt @@ -0,0 +1,10 @@ +package ru.myitschool.work.domain.user + +import ru.myitschool.work.domain.entities.UserEntity + +class GetUserByLoginUseCase( + private val repository: UserRepository +) { + + suspend operator fun invoke(login: String): Result = repository.getUserByLogin(login) +} \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/domain/user/UserRepository.kt b/app/src/main/java/ru/myitschool/work/domain/user/UserRepository.kt index 3ea221d..85f356e 100644 --- a/app/src/main/java/ru/myitschool/work/domain/user/UserRepository.kt +++ b/app/src/main/java/ru/myitschool/work/domain/user/UserRepository.kt @@ -5,4 +5,5 @@ import ru.myitschool.work.domain.entities.UserEntity interface UserRepository { suspend fun getCurrentUser(): UserEntity + suspend fun getUserByLogin(login: String) : Result } \ No newline at end of file diff --git a/app/src/main/java/ru/myitschool/work/ui/login/LoginFragment.kt b/app/src/main/java/ru/myitschool/work/ui/login/LoginFragment.kt index 58d6cd7..8b20cfc 100644 --- a/app/src/main/java/ru/myitschool/work/ui/login/LoginFragment.kt +++ b/app/src/main/java/ru/myitschool/work/ui/login/LoginFragment.kt @@ -1,8 +1,9 @@ package ru.myitschool.work.ui.login +import android.graphics.Color import android.os.Bundle -import android.util.Log import android.view.View +import androidx.core.content.ContextCompat import androidx.core.widget.doAfterTextChanged import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels @@ -32,11 +33,18 @@ class LoginFragment : Fragment(R.layout.fragment_login) { binding.error.visibleOrGone(state is LoginViewModel.State.Error) when (state) { - is LoginViewModel.State.Error -> binding.error.text = state.errorMessage - is LoginViewModel.State.Loading -> Unit + is LoginViewModel.State.Error -> { + binding.error.text = state.errorMessage + setButtonActive() + } + is LoginViewModel.State.Loading -> setButtonInactive() is LoginViewModel.State.Waiting -> Unit - is LoginViewModel.State.LoginCheckCompleted -> binding.login.isEnabled = - state.isCompleted + is LoginViewModel.State.LoginCheckCompleted -> { + state.isCompleted.let { + if (it) setButtonActive() else setButtonInactive() + binding.login.isEnabled = it + } + } } } @@ -57,6 +65,18 @@ class LoginFragment : Fragment(R.layout.fragment_login) { } } + private fun setButtonInactive() { + binding.login.setTextColor(Color.BLACK) + binding.login.background = + ContextCompat.getDrawable(requireContext(), R.drawable.inactive_button) + } + + private fun setButtonActive() { + binding.login.setTextColor(Color.WHITE) + binding.login.background = + ContextCompat.getDrawable(requireContext(), R.drawable.main_button) + } + override fun onDestroy() { _binding = null super.onDestroy() diff --git a/app/src/main/java/ru/myitschool/work/ui/profile/UserFragment.kt b/app/src/main/java/ru/myitschool/work/ui/profile/UserFragment.kt index 0add493..bcc4c6a 100644 --- a/app/src/main/java/ru/myitschool/work/ui/profile/UserFragment.kt +++ b/app/src/main/java/ru/myitschool/work/ui/profile/UserFragment.kt @@ -2,10 +2,11 @@ package ru.myitschool.work.ui.profile import android.os.Bundle import android.view.View +import androidx.appcompat.app.AlertDialog import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.navigation.fragment.findNavController -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout +import androidx.paging.LoadState import com.squareup.picasso.Picasso import ru.myitschool.work.R import ru.myitschool.work.databinding.FragmentUserBinding @@ -22,14 +23,17 @@ class UserFragment : Fragment(R.layout.fragment_user) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { _binding = FragmentUserBinding.bind(view) + val adapter = PassesListAdapter() + binding.passes.adapter = adapter + viewModel.state.collectWithLifecycle(this) { state -> - (binding.refresh as SwipeRefreshLayout).isRefreshing = - state is UserViewModel.State.Loading + binding.refresh.isRefreshing = state is UserViewModel.State.Loading binding.content?.visibleOrGone(state is UserViewModel.State.Show) when (state) { is UserViewModel.State.Loading -> Unit is UserViewModel.State.Show -> { val user = state.userEntity + binding.findUser.visibleOrGone(user.isAdmin) binding.fullname.text = user.name binding.position.text = user.position binding.lastEntry.text = user.lastVisit @@ -37,14 +41,38 @@ class UserFragment : Fragment(R.layout.fragment_user) { } } - (binding.refresh as SwipeRefreshLayout).setOnRefreshListener { + viewModel.listState.collectWithLifecycle(this) { listState -> + adapter.submitData(listState) + } + + adapter.loadStateFlow.collectWithLifecycle(this) { data -> + val dataState = data.refresh + binding.refresh.isRefreshing = dataState is LoadState.Loading + binding.error.visibleOrGone(dataState is LoadState.Error) + + if (dataState is LoadState.Error) { + binding.error.text = dataState.error.toString() + } + } + + binding.refresh.setOnRefreshListener { viewModel.onRefresh() + adapter.refresh() } binding.logout.setOnClickListener { - viewModel.onLogout() + AlertDialog.Builder(requireContext()) + .setTitle("Выход") + .setMessage("Вы уверены, что хотите выйти из аккаунта?") + .setIcon(android.R.drawable.ic_dialog_alert) + .setPositiveButton(android.R.string.ok) { _, _ -> viewModel.onLogout() } + .show() findNavController().navigate(R.id.action_userFragment_to_loginFragment) } + + binding.findUser.setOnClickListener { + findNavController().navigate(R.id.find_user) + } } }