Added start logic for visits pagination, changed visits logic, changed Dto objects, added password in login, bug fixes,
This commit is contained in:
parent
12c6b6e1c2
commit
961c37d265
@ -39,7 +39,7 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation("androidx.paging:paging-runtime:3.3.2")
|
||||||
val cameraX = "1.3.4"
|
val cameraX = "1.3.4"
|
||||||
implementation("androidx.camera:camera-core:$cameraX")
|
implementation("androidx.camera:camera-core:$cameraX")
|
||||||
implementation("androidx.camera:camera-camera2:$cameraX")
|
implementation("androidx.camera:camera-camera2:$cameraX")
|
||||||
|
@ -6,5 +6,5 @@ data class UserEntity(
|
|||||||
val name: String,
|
val name: String,
|
||||||
val photo: String,
|
val photo: String,
|
||||||
val position: String,
|
val position: String,
|
||||||
val lastVisit: String,
|
// val lastVisit: String,
|
||||||
)
|
)
|
@ -10,7 +10,7 @@ class UserMapper {
|
|||||||
login = userDTO.login,
|
login = userDTO.login,
|
||||||
position = userDTO.position,
|
position = userDTO.position,
|
||||||
name = userDTO.name,
|
name = userDTO.name,
|
||||||
lastVisit = userDTO.lastVisit,
|
// lastVisit = userDTO.lastVisit,
|
||||||
photo = userDTO.photo
|
photo = userDTO.photo
|
||||||
)
|
)
|
||||||
return userEntity
|
return userEntity
|
||||||
@ -22,7 +22,7 @@ class UserMapper {
|
|||||||
name = userEntity.name,
|
name = userEntity.name,
|
||||||
photo = userEntity.photo,
|
photo = userEntity.photo,
|
||||||
position = userEntity.position,
|
position = userEntity.position,
|
||||||
lastVisit = userEntity.lastVisit,
|
// lastVisit = userEntity.lastVisit,
|
||||||
)
|
)
|
||||||
return userDto
|
return userDto
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,9 @@ package com.displaynone.acss.components.auth.models.user
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.displaynone.acss.components.auth.internal_utils.AuthTokenManager
|
import com.displaynone.acss.components.auth.internal_utils.AuthTokenManager
|
||||||
import com.displaynone.acss.components.auth.models.user.repository.UserRepository
|
import com.displaynone.acss.components.auth.models.user.repository.UserRepository
|
||||||
|
import com.displaynone.acss.components.auth.models.user.repository.dto.LastVisitsDto
|
||||||
import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO
|
import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO
|
||||||
|
import com.displaynone.acss.components.auth.models.user.repository.dto.VisitDto
|
||||||
|
|
||||||
|
|
||||||
class UserServiceST(
|
class UserServiceST(
|
||||||
@ -28,13 +30,34 @@ class UserServiceST(
|
|||||||
return instance ?: throw RuntimeException("null instance")
|
return instance ?: throw RuntimeException("null instance")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
suspend fun login(login: String): Result<Unit>{
|
suspend fun login(login: String, password:String): Result<Unit>{
|
||||||
return runCatching {
|
return runCatching {
|
||||||
userRepository.login(login = login).getOrThrow().let { data ->
|
userRepository.login(login = login, password).getOrThrow().let { data ->
|
||||||
tokenManager.saveTokens(data)
|
tokenManager.saveTokens(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
suspend fun getMyLastVisits(pageNum: Int,
|
||||||
|
pageSize: Int): Result<List<VisitDto>> {
|
||||||
|
if (!tokenManager.hasTokens()) {
|
||||||
|
throw RuntimeException("access token is null")
|
||||||
|
}
|
||||||
|
|
||||||
|
return userRepository.getMyLastVisits(
|
||||||
|
pageNum = pageNum,
|
||||||
|
pageSize = pageSize,
|
||||||
|
token = tokenManager.authTokenPair!!.accessToken
|
||||||
|
).map { pagingDto -> pagingDto.content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
suspend fun getLastVisitsByLogin(pageNum: Int,
|
||||||
|
pageSize: Int,
|
||||||
|
login: String): Result<List<VisitDto>> {
|
||||||
|
if (!tokenManager.hasTokens()) {
|
||||||
|
throw RuntimeException("access token is null")
|
||||||
|
}
|
||||||
|
return userRepository.getLastVisitsByLogin(pageNum, pageSize, tokenManager.authTokenPair!!.accessToken, login).map { pagingDto -> pagingDto.content }
|
||||||
|
}
|
||||||
fun logout(){
|
fun logout(){
|
||||||
tokenManager.clear()
|
tokenManager.clear()
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,12 @@ package com.displaynone.acss.components.auth.models.user.repository
|
|||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.displaynone.acss.components.auth.models.AuthTokenPair
|
import com.displaynone.acss.components.auth.models.AuthTokenPair
|
||||||
|
import com.displaynone.acss.components.auth.models.user.repository.dto.LastVisitsDto
|
||||||
import com.displaynone.acss.config.Constants.serverUrl
|
import com.displaynone.acss.config.Constants.serverUrl
|
||||||
import com.displaynone.acss.config.Network
|
import com.displaynone.acss.config.Network
|
||||||
import com.displaynone.acss.components.auth.models.user.repository.dto.RegisterUserDto
|
import com.displaynone.acss.components.auth.models.user.repository.dto.RegisterUserDto
|
||||||
import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO
|
import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO
|
||||||
|
import com.displaynone.acss.components.auth.models.user.repository.dto.UserLoginDto
|
||||||
import io.ktor.client.call.body
|
import io.ktor.client.call.body
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.request.headers
|
import io.ktor.client.request.headers
|
||||||
@ -33,13 +35,14 @@ class UserRepository(
|
|||||||
result.status != HttpStatusCode.OK
|
result.status != HttpStatusCode.OK
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
suspend fun login(login: String): Result<AuthTokenPair> = withContext(Dispatchers.IO) {
|
suspend fun login(login: String, password: String): Result<AuthTokenPair> = withContext(Dispatchers.IO) {
|
||||||
runCatching {
|
runCatching {
|
||||||
val result = Network.client.post("$serverUrl/api/auth/login") {
|
val result = Network.client.post("$serverUrl/api/auth/login") {
|
||||||
headers {
|
headers {
|
||||||
append(HttpHeaders.ContentType, ContentType.Application.Json.toString())
|
append(HttpHeaders.ContentType, ContentType.Application.Json.toString())
|
||||||
}
|
}
|
||||||
setBody("""{ "login": "$login" }""")
|
contentType(ContentType.Application.Json)
|
||||||
|
setBody(UserLoginDto(login, password))
|
||||||
}
|
}
|
||||||
if (result.status != HttpStatusCode.OK) {
|
if (result.status != HttpStatusCode.OK) {
|
||||||
error("Status ${result.status}: ${result.body<String>()}")
|
error("Status ${result.status}: ${result.body<String>()}")
|
||||||
@ -99,6 +102,57 @@ class UserRepository(
|
|||||||
result.body()
|
result.body()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
suspend fun getMyLastVisits(pageNum: Int,
|
||||||
|
pageSize: Int,
|
||||||
|
token: String): Result<LastVisitsDto> = withContext(Dispatchers.IO){
|
||||||
|
runCatching {
|
||||||
|
val result = Network.client.get("$serverUrl/api/acs/visits/me?page=$pageNum&size=$pageSize") {
|
||||||
|
headers {
|
||||||
|
append(HttpHeaders.Authorization, "Bearer $token")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.d("UserRepository", result.bodyAsText())
|
||||||
|
if (result.status != HttpStatusCode.OK) {
|
||||||
|
error("Status ${result.status}: ${result.body<String>()}")
|
||||||
|
}
|
||||||
|
|
||||||
|
result.body()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
suspend fun getLastVisitsByLogin(pageNum: Int,
|
||||||
|
pageSize: Int,
|
||||||
|
token: String, login: String): Result<LastVisitsDto> = withContext(Dispatchers.IO){
|
||||||
|
runCatching {
|
||||||
|
val encodedLogin = login.encodeURLPath()
|
||||||
|
val result = Network.client.get("$serverUrl/api/acs/login/${encodedLogin}?page=$pageNum&size=$pageSize") {
|
||||||
|
headers {
|
||||||
|
append(HttpHeaders.Authorization, "Bearer $token")
|
||||||
|
}
|
||||||
|
setBody("""{ "login": "$encodedLogin" }""")
|
||||||
|
}
|
||||||
|
if (result.status != HttpStatusCode.OK) {
|
||||||
|
error("Status ${result.status}: ${result.body<String>()}")
|
||||||
|
}
|
||||||
|
Log.d("UserRepository", result.bodyAsText())
|
||||||
|
result.body()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
suspend fun getAllLastVisitsAsAdmin(token: String, login: String): Result<UserDTO> = withContext(Dispatchers.IO){
|
||||||
|
runCatching {
|
||||||
|
val encodedLogin = login.encodeURLPath()
|
||||||
|
val result = Network.client.get("$serverUrl/api/users/login/$encodedLogin") {
|
||||||
|
headers {
|
||||||
|
append(HttpHeaders.Authorization, "Bearer $token")
|
||||||
|
}
|
||||||
|
setBody("""{ "code": "$encodedLogin" }""")
|
||||||
|
}
|
||||||
|
if (result.status != HttpStatusCode.OK) {
|
||||||
|
error("Status ${result.status}: ${result.body<String>()}")
|
||||||
|
}
|
||||||
|
Log.d("UserRepository", result.bodyAsText())
|
||||||
|
result.body()
|
||||||
|
}
|
||||||
|
}
|
||||||
suspend fun openDoor(token: String, code: Long): Result<Unit> = withContext(Dispatchers.IO) {
|
suspend fun openDoor(token: String, code: Long): Result<Unit> = withContext(Dispatchers.IO) {
|
||||||
runCatching {
|
runCatching {
|
||||||
val result = Network.client.patch("$serverUrl/api/open") {
|
val result = Network.client.patch("$serverUrl/api/open") {
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
package com.displaynone.acss.components.auth.models.user.repository
|
||||||
|
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.paging.PagingDataAdapter
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.displaynone.acss.components.auth.models.user.repository.dto.VisitDto
|
||||||
|
import com.displaynone.acss.databinding.ItemScannerViewBinding
|
||||||
|
|
||||||
|
class VisitAdapter: PagingDataAdapter<VisitDto, VisitAdapter.ViewHolder>(VisitDiff) {
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
return ViewHolder(
|
||||||
|
ItemScannerViewBinding.inflate(
|
||||||
|
LayoutInflater.from(parent.context),
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
holder.bind(getItem(position) ?:
|
||||||
|
VisitDto(
|
||||||
|
id = -1,
|
||||||
|
userId = -1,
|
||||||
|
gateId = -1,
|
||||||
|
createdAt = "Loading...",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ViewHolder(
|
||||||
|
private val binding: ItemScannerViewBinding
|
||||||
|
): RecyclerView.ViewHolder(binding.root) {
|
||||||
|
fun bind(item: VisitDto){
|
||||||
|
binding.scanTime.text = item.createdAt
|
||||||
|
binding.scannerId.text = item.gateId.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object VisitDiff : DiffUtil.ItemCallback<VisitDto>() {
|
||||||
|
override fun areItemsTheSame(oldItem: VisitDto, newItem: VisitDto): Boolean {
|
||||||
|
return oldItem.id == newItem.id
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: VisitDto, newItem: VisitDto): Boolean {
|
||||||
|
return oldItem == newItem
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.displaynone.acss.components.auth.models.user.repository
|
||||||
|
|
||||||
|
import androidx.paging.PagingSource
|
||||||
|
import androidx.paging.PagingState
|
||||||
|
import com.displaynone.acss.components.auth.models.user.repository.dto.VisitDto
|
||||||
|
|
||||||
|
class VisitListPagingSource(
|
||||||
|
private val request: suspend (pageNum: Int, pageSize: Int) -> Result<List<VisitDto>>
|
||||||
|
) : PagingSource<Int, VisitDto>() {
|
||||||
|
override fun getRefreshKey(state: PagingState<Int, VisitDto>): Int? {
|
||||||
|
return state.anchorPosition?.let {
|
||||||
|
state.closestPageToPosition(it)?.prevKey?.plus(1)
|
||||||
|
?: state.closestPageToPosition(it)?.nextKey?.minus(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, VisitDto> {
|
||||||
|
val pageNum = params.key ?: 0
|
||||||
|
return request.invoke(
|
||||||
|
pageNum,
|
||||||
|
params.loadSize
|
||||||
|
).fold(
|
||||||
|
onSuccess = { value ->
|
||||||
|
LoadResult.Page(
|
||||||
|
data = value,
|
||||||
|
prevKey = (pageNum - 1).takeIf { it >= 0 },
|
||||||
|
nextKey = (pageNum + 1).takeIf { value.size == params.loadSize }
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onFailure = { error ->
|
||||||
|
LoadResult.Error(error)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.displaynone.acss.components.auth.models.user.repository.dto
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class LastVisitsDto(
|
||||||
|
@SerialName("content")
|
||||||
|
val content: List<VisitDto>
|
||||||
|
) {
|
||||||
|
}
|
@ -21,6 +21,6 @@ data class UserDTO (
|
|||||||
@SerialName("position")
|
@SerialName("position")
|
||||||
val position: String,
|
val position: String,
|
||||||
|
|
||||||
@SerialName("lastVisit")
|
// @SerialName("lastVisit")
|
||||||
val lastVisit: String,
|
// val lastVisit: String,
|
||||||
) : java.io.Serializable
|
) : java.io.Serializable
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.displaynone.acss.components.auth.models.user.repository.dto
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class UserLoginDto(
|
||||||
|
@SerialName("login")
|
||||||
|
val login: String,
|
||||||
|
@SerialName("password")
|
||||||
|
val password: String,
|
||||||
|
) {
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.displaynone.acss.components.auth.models.user.repository.dto
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class VisitDto(
|
||||||
|
@SerialName("id")
|
||||||
|
val id: Long,
|
||||||
|
@SerialName("userId")
|
||||||
|
val userId: Long,
|
||||||
|
@SerialName("gateId")
|
||||||
|
val gateId: Long,
|
||||||
|
@SerialName("createdAt")
|
||||||
|
val createdAt: String,
|
||||||
|
) {
|
||||||
|
}
|
@ -40,9 +40,14 @@ class AdminFragment : Fragment(R.layout.fragment_admin) {
|
|||||||
val userDto = state.item
|
val userDto = state.item
|
||||||
val bundle = Bundle().apply{
|
val bundle = Bundle().apply{
|
||||||
putSerializable("user", userDto)
|
putSerializable("user", userDto)
|
||||||
|
putBoolean("isMe", false)
|
||||||
}
|
}
|
||||||
navigateTo(view, R.id.action_adminFragment_to_profileFragment, bundle)
|
navigateTo(view, R.id.action_adminFragment_to_profileFragment, bundle)
|
||||||
}
|
}
|
||||||
|
if (state is AdminViewModel.State.Error){
|
||||||
|
val errorMessage = state.errorMessage
|
||||||
|
binding.loginSearch.setError(errorMessage)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,7 +5,6 @@ import androidx.lifecycle.ViewModel
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.displaynone.acss.components.auth.models.user.UserServiceST
|
import com.displaynone.acss.components.auth.models.user.UserServiceST
|
||||||
import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO
|
import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO
|
||||||
import com.displaynone.acss.ui.profile.ProfileViewModel.State
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -20,7 +19,8 @@ class AdminViewModel: ViewModel() {
|
|||||||
_state.emit(State.Show(item = dto))
|
_state.emit(State.Show(item = dto))
|
||||||
},
|
},
|
||||||
onFailure = { error ->
|
onFailure = { error ->
|
||||||
error.message?.let { error(it) }
|
// error.message?.let { error(it) }
|
||||||
|
_state.emit(State.Error(error.message.toString()))
|
||||||
Log.e("AdminViewModel", error.message.toString()) }
|
Log.e("AdminViewModel", error.message.toString()) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -30,6 +30,9 @@ class AdminViewModel: ViewModel() {
|
|||||||
data class Show(
|
data class Show(
|
||||||
val item: UserDTO
|
val item: UserDTO
|
||||||
): State
|
): State
|
||||||
|
data class Error(
|
||||||
|
val errorMessage: String
|
||||||
|
): State
|
||||||
data object Loading : State
|
data object Loading : State
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -59,6 +59,7 @@ class AuthFragment: Fragment(R.layout.fragment_auth) {
|
|||||||
val username = s.toString()
|
val username = s.toString()
|
||||||
val valid = isUsernameValid(username)
|
val valid = isUsernameValid(username)
|
||||||
|
|
||||||
|
|
||||||
binding.hint.visibility = if(valid) View.INVISIBLE else View.VISIBLE
|
binding.hint.visibility = if(valid) View.INVISIBLE else View.VISIBLE
|
||||||
binding.next.isEnabled = valid
|
binding.next.isEnabled = valid
|
||||||
val color = if (valid) R.color.primary else R.color.secondary
|
val color = if (valid) R.color.primary else R.color.secondary
|
||||||
@ -67,6 +68,35 @@ class AuthFragment: Fragment(R.layout.fragment_auth) {
|
|||||||
|
|
||||||
override fun afterTextChanged(s: Editable?) {}
|
override fun afterTextChanged(s: Editable?) {}
|
||||||
})
|
})
|
||||||
|
// binding.password.addTextChangedListener(object : TextWatcher {
|
||||||
|
// override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||||
|
// @SuppressLint("ResourceAsColor")
|
||||||
|
// override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||||
|
// binding.error.visibility = View.GONE
|
||||||
|
// val username = s.toString()
|
||||||
|
// val valid = isPasswordValid(username)
|
||||||
|
//
|
||||||
|
// binding.hint.visibility = if(valid) View.INVISIBLE else View.VISIBLE
|
||||||
|
// if (!valid){
|
||||||
|
// val errorMessage = getPasswordValidError(s.toString())
|
||||||
|
// binding.password.setError(errorMessage)
|
||||||
|
// }
|
||||||
|
// binding.next.isEnabled = valid
|
||||||
|
// val color = if (valid) R.color.primary else R.color.secondary
|
||||||
|
// binding.next.backgroundTintList = ContextCompat.getColorStateList(requireContext(), color)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun afterTextChanged(s: Editable?) {}
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
private fun getPasswordValidError(password: String): String {
|
||||||
|
if (password.length < 8){ return "LenError" }
|
||||||
|
val letterRegex = Regex("^(?=.*[A-Z]).+$")
|
||||||
|
if(!letterRegex.matches(password)){ return "UpperCaseError"}
|
||||||
|
val digitRegex = Regex("^(?=.*\\\\d).+$")
|
||||||
|
if(!digitRegex.matches(password)){ return "DigitCaseError"}
|
||||||
|
|
||||||
|
return "NoErrors"
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isUsernameValid(username: String): Boolean {
|
private fun isUsernameValid(username: String): Boolean {
|
||||||
@ -76,6 +106,10 @@ class AuthFragment: Fragment(R.layout.fragment_auth) {
|
|||||||
!username[0].isDigit() &&
|
!username[0].isDigit() &&
|
||||||
alf.matches(username)
|
alf.matches(username)
|
||||||
}
|
}
|
||||||
|
private fun isPasswordValid(password: String): Boolean {
|
||||||
|
return password.isNotEmpty() &&
|
||||||
|
password.length >= 8
|
||||||
|
}
|
||||||
// private fun subscribe() {
|
// private fun subscribe() {
|
||||||
// viewModel.state.collectWhenStarted(this) { state ->
|
// viewModel.state.collectWhenStarted(this) { state ->
|
||||||
// binding.login.setOnClickListener(this::onLoginButtonClicked)
|
// binding.login.setOnClickListener(this::onLoginButtonClicked)
|
||||||
@ -84,8 +118,9 @@ class AuthFragment: Fragment(R.layout.fragment_auth) {
|
|||||||
|
|
||||||
private fun onLoginButtonClicked(view: View) {
|
private fun onLoginButtonClicked(view: View) {
|
||||||
val login = binding.login.text.toString()
|
val login = binding.login.text.toString()
|
||||||
|
val password = binding.password.text.toString()
|
||||||
if (login.isEmpty()) return
|
if (login.isEmpty()) return
|
||||||
viewModel.login(login)
|
viewModel.login(login, password)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,10 +22,10 @@ class AuthViewModel(): ViewModel() {
|
|||||||
private val _errorState = MutableStateFlow<String?>(null)
|
private val _errorState = MutableStateFlow<String?>(null)
|
||||||
val errorState: StateFlow<String?> = _errorState.asStateFlow()
|
val errorState: StateFlow<String?> = _errorState.asStateFlow()
|
||||||
|
|
||||||
fun login(login: String){
|
fun login(login: String, password:String){
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
try {
|
try {
|
||||||
UserServiceST.getInstance().login(login).fold(
|
UserServiceST.getInstance().login(login, password).fold(
|
||||||
onSuccess = { openProfile() },
|
onSuccess = { openProfile() },
|
||||||
onFailure = { error ->
|
onFailure = { error ->
|
||||||
Log.e("AuthViewModel", "Login failed: ${error.message ?: "Unknown error"}")
|
Log.e("AuthViewModel", "Login failed: ${error.message ?: "Unknown error"}")
|
||||||
|
@ -10,6 +10,7 @@ import androidx.fragment.app.viewModels
|
|||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.displaynone.acss.R
|
import com.displaynone.acss.R
|
||||||
|
import com.displaynone.acss.components.auth.models.user.repository.VisitAdapter
|
||||||
import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO
|
import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO
|
||||||
import com.displaynone.acss.databinding.FragmentProfileBinding
|
import com.displaynone.acss.databinding.FragmentProfileBinding
|
||||||
import com.displaynone.acss.ui.profile.ProfileViewModel.Action
|
import com.displaynone.acss.ui.profile.ProfileViewModel.Action
|
||||||
@ -27,31 +28,58 @@ class ProfileFragment: Fragment(R.layout.fragment_profile) {
|
|||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
_binding = FragmentProfileBinding.bind(view)
|
_binding = FragmentProfileBinding.bind(view)
|
||||||
|
//
|
||||||
binding.swipeRefresh.setOnRefreshListener {
|
// binding.swipeRefresh.setOnRefreshListener {
|
||||||
refreshData()
|
// if (getIsMe()){
|
||||||
}
|
// refreshData()
|
||||||
|
// } else{
|
||||||
|
// showData(getUserDto()!!)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
binding.logout.setOnClickListener{
|
binding.logout.setOnClickListener{
|
||||||
logout()
|
logout()
|
||||||
}
|
}
|
||||||
binding.scan.setOnClickListener{
|
binding.scan.setOnClickListener{
|
||||||
viewModel.openScan()
|
viewModel.openScan()
|
||||||
}
|
}
|
||||||
val user = getUserDto()
|
val adapter = VisitAdapter()
|
||||||
if (user == null) {
|
binding.recyclerViewLogs.adapter = adapter
|
||||||
|
if (getIsMe()) {
|
||||||
refreshData()
|
refreshData()
|
||||||
|
// viewModel.visitListState.collectWithLifecycle(this) { data ->
|
||||||
|
// adapter.submitData(data)
|
||||||
|
// }
|
||||||
waitForQRScanResult()
|
waitForQRScanResult()
|
||||||
} else{
|
} else{
|
||||||
showData(user) // TODO() не показывать кнопки
|
showData(getUserDto()!!)
|
||||||
|
hideButtons()
|
||||||
|
|
||||||
}
|
}
|
||||||
subscribe()
|
subscribe()
|
||||||
|
|
||||||
|
viewModel.visitListState.collectWithLifecycle(this) { data ->
|
||||||
|
adapter.submitData(data)
|
||||||
|
Log.d("ProfileFragment", "submitted data")
|
||||||
|
}
|
||||||
|
// viewModel.visitListStateFromLogin.collectWithLifecycle(this) { data ->
|
||||||
|
// adapter.submitData(data)
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hideButtons() {
|
||||||
|
binding.logout.visibility = View.INVISIBLE
|
||||||
|
binding.scan.visibility = View.INVISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showData(userDTO: UserDTO){
|
fun showData(userDTO: UserDTO){
|
||||||
binding.fio.text = userDTO.name
|
binding.fio.text = userDTO.name
|
||||||
binding.position.text = userDTO.position
|
binding.position.text = userDTO.position
|
||||||
binding.lastEntry.text = userDTO.lastVisit
|
viewModel.setLogin(login1 = userDTO.login)
|
||||||
|
// binding.lastEntry.text = userDTO.lastVisit
|
||||||
|
// viewModel.visitListStateFromLogin.collectWithLifecycle(this){
|
||||||
|
//
|
||||||
|
// }
|
||||||
setAvatar(userDTO.photo)
|
setAvatar(userDTO.photo)
|
||||||
}
|
}
|
||||||
private fun refreshData() {
|
private fun refreshData() {
|
||||||
@ -72,6 +100,10 @@ class ProfileFragment: Fragment(R.layout.fragment_profile) {
|
|||||||
private fun getUserDto(): UserDTO? {
|
private fun getUserDto(): UserDTO? {
|
||||||
return arguments?.getSerializable("user") as? UserDTO
|
return arguments?.getSerializable("user") as? UserDTO
|
||||||
}
|
}
|
||||||
|
private fun getIsMe(): Boolean {
|
||||||
|
return arguments?.getBoolean("isMe", true) ?: true
|
||||||
|
}
|
||||||
|
|
||||||
private fun waitForQRScanResult() {
|
private fun waitForQRScanResult() {
|
||||||
|
|
||||||
requireActivity().onBackPressedDispatcher.addCallback(
|
requireActivity().onBackPressedDispatcher.addCallback(
|
||||||
|
@ -3,7 +3,12 @@ package com.displaynone.acss.ui.profile
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.paging.Pager
|
||||||
|
import androidx.paging.PagingConfig
|
||||||
|
import androidx.paging.cachedIn
|
||||||
|
import androidx.paging.log
|
||||||
import com.displaynone.acss.components.auth.models.user.UserServiceST
|
import com.displaynone.acss.components.auth.models.user.UserServiceST
|
||||||
|
import com.displaynone.acss.components.auth.models.user.repository.VisitListPagingSource
|
||||||
import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO
|
import com.displaynone.acss.components.auth.models.user.repository.dto.UserDTO
|
||||||
import kotlinx.coroutines.channels.BufferOverflow
|
import kotlinx.coroutines.channels.BufferOverflow
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
@ -17,10 +22,31 @@ class ProfileViewModel(): ViewModel() {
|
|||||||
capacity = Channel.BUFFERED,
|
capacity = Channel.BUFFERED,
|
||||||
onBufferOverflow = BufferOverflow.DROP_OLDEST,
|
onBufferOverflow = BufferOverflow.DROP_OLDEST,
|
||||||
)
|
)
|
||||||
|
private var login: String = "" // FIXME()
|
||||||
|
fun setLogin(login1: String){
|
||||||
|
login = login1
|
||||||
|
}
|
||||||
val action = _action.receiveAsFlow()
|
val action = _action.receiveAsFlow()
|
||||||
val _state = MutableStateFlow<State>(State.Loading)
|
val _state = MutableStateFlow<State>(State.Loading)
|
||||||
val state = _state.asStateFlow()
|
val state = _state.asStateFlow()
|
||||||
|
|
||||||
|
val visitListState = Pager(
|
||||||
|
config = PagingConfig(pageSize = 20,
|
||||||
|
enablePlaceholders = false,
|
||||||
|
maxSize = 100
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
VisitListPagingSource(UserServiceST.getInstance()::getMyLastVisits)
|
||||||
|
}.flow
|
||||||
|
.cachedIn(viewModelScope)
|
||||||
|
|
||||||
|
val visitListStateFromLogin = Pager(
|
||||||
|
config = PagingConfig(pageSize = 20, enablePlaceholders = false, maxSize = 100)
|
||||||
|
) {
|
||||||
|
VisitListPagingSource { pageNum, pageSize ->
|
||||||
|
UserServiceST.getInstance().getLastVisitsByLogin(pageNum,pageSize, login)
|
||||||
|
}
|
||||||
|
}.flow.cachedIn(viewModelScope)
|
||||||
|
|
||||||
fun logout(){
|
fun logout(){
|
||||||
UserServiceST.getInstance().logout()
|
UserServiceST.getInstance().logout()
|
||||||
@ -48,6 +74,7 @@ class ProfileViewModel(): ViewModel() {
|
|||||||
_action.send(Action.GoToScan)
|
_action.send(Action.GoToScan)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed interface State {
|
sealed interface State {
|
||||||
data object Loading : State
|
data object Loading : State
|
||||||
data class Show(
|
data class Show(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user