Half-implement user retrieving logic

This commit is contained in:
Nymos 2025-02-19 13:57:05 +03:00
parent 5c3e7bcdee
commit ddbb5fdf8a
13 changed files with 115 additions and 27 deletions

View File

@ -0,0 +1,6 @@
package com.nto.data.models
data class QRDTO(
val id: Long = Long.MAX_VALUE,
val name: String = ""
)

View File

@ -0,0 +1,18 @@
package com.nto.data.models
import java.time.LocalDateTime
enum class Position {
DEVELOPER, DESIGNER, TESTER, ANALYST, ADMINISTRATOR
}
data class UserDTO(
val firstName: String = "",
val secondName: String = "",
val thirdName: String = "",
val position: Position = Position.DEVELOPER,
val lastVisit: LocalDateTime = LocalDateTime.now(),
val isError: Boolean = false,
val isUnauthorized: Boolean = false,
val localizedName: String = ""
)

View File

@ -1,8 +1,16 @@
package com.nto.data.models.cards package com.nto.data.models.cards
import com.nto.data.models.QRDTO
import java.time.LocalDateTime
enum class VisitType {
PHONE_ENTRY, CARD_ENTRY
}
data class VisitCardDTO( data class VisitCardDTO(
val name: String = "", val name: String = "",
val id: String = "", val id: Long = Long.MAX_VALUE,
val dateString: String = "", val dateString: LocalDateTime = LocalDateTime.now(),
val isCode: Boolean = false val visitType: VisitType = VisitType.CARD_ENTRY,
val qrCode: QRDTO = QRDTO()
) )

View File

@ -1,10 +1,11 @@
package com.nto.data.repository package com.nto.data.repository
import com.nto.data.models.LoginResult import com.nto.data.models.LoginResult
import com.nto.data.models.UserDTO
interface DataRepository { interface DataRepository {
suspend fun auth(login: String, password: String): LoginResult suspend fun auth(login: String, password: String): LoginResult
suspend fun saveToken(token: String) suspend fun saveToken(token: String)
suspend fun getToken(): String suspend fun getToken(): String
suspend fun getInfo() suspend fun getInfo(): UserDTO
} }

View File

@ -3,6 +3,7 @@ package com.nto.data.repository
import android.content.Context import android.content.Context
import android.content.Context.MODE_PRIVATE import android.content.Context.MODE_PRIVATE
import com.nto.data.models.LoginResult import com.nto.data.models.LoginResult
import com.nto.data.models.UserDTO
import com.nto.data.utils.Provider import com.nto.data.utils.Provider
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import okhttp3.Credentials import okhttp3.Credentials
@ -27,8 +28,10 @@ class DataRepositoryImpl @Inject constructor(@ApplicationContext private val con
return context.getSharedPreferences("auth", MODE_PRIVATE).getString("token", "")!! return context.getSharedPreferences("auth", MODE_PRIVATE).getString("token", "")!!
} }
override suspend fun getInfo(){ override suspend fun getInfo(): UserDTO {
val result = Provider.provideRetrofit().getInfo(getToken()).execute()
return if (result.isSuccessful) result.body()!!
else UserDTO(isError = true, isUnauthorized = result.code() == 403)
} }
} }

View File

@ -1,11 +1,15 @@
package com.nto.data.utils package com.nto.data.utils
import com.nto.data.models.UserDTO
import okhttp3.ResponseBody import okhttp3.ResponseBody
import retrofit2.Call import retrofit2.Call
import retrofit2.http.GET import retrofit2.http.GET
import retrofit2.http.Header import retrofit2.http.Header
interface RetrofitApi { interface RetrofitApi {
@GET("auth") @GET("employee/auth")
fun auth(@Header("Authorization") token: String): Call<ResponseBody> fun auth(@Header("Authorization") token: String): Call<ResponseBody>
@GET("employee/info")
fun getInfo(@Header("Authorization") token: String): Call<UserDTO>
} }

View File

@ -1,10 +1,11 @@
package com.nto.domain.repository package com.nto.domain.repository
import com.nto.data.models.LoginResult import com.nto.data.models.LoginResult
import com.nto.data.models.UserDTO
interface DomainRepository { interface DomainRepository {
suspend fun auth(email: String, password: String): LoginResult suspend fun auth(email: String, password: String): LoginResult
suspend fun saveToken(token: String) suspend fun saveToken(token: String)
suspend fun getToken(): String suspend fun getToken(): String
suspend fun getInfo() suspend fun getInfo(): UserDTO
} }

View File

@ -1,6 +1,7 @@
package com.nto.domain.repository package com.nto.domain.repository
import com.nto.data.models.LoginResult import com.nto.data.models.LoginResult
import com.nto.data.models.UserDTO
import com.nto.data.repository.DataRepositoryImpl import com.nto.data.repository.DataRepositoryImpl
import java.io.IOException import java.io.IOException
import javax.inject.Inject import javax.inject.Inject
@ -26,7 +27,7 @@ class DomainRepositoryImpl @Inject constructor(private val dataRepositoryImpl: D
return dataRepositoryImpl.getToken() return dataRepositoryImpl.getToken()
} }
override suspend fun getInfo(){ override suspend fun getInfo(): UserDTO{
val result = dataRepositoryImpl.getInfo() return dataRepositoryImpl.getInfo()
} }
} }

View File

@ -1,10 +1,11 @@
package com.nto.domain.usecase package com.nto.domain.usecase
import com.nto.data.models.UserDTO
import com.nto.domain.repository.DomainRepositoryImpl import com.nto.domain.repository.DomainRepositoryImpl
import javax.inject.Inject import javax.inject.Inject
class ProfileUseCase @Inject constructor(private val domainRepositoryImpl: DomainRepositoryImpl) { class ProfileUseCase @Inject constructor(private val domainRepositoryImpl: DomainRepositoryImpl) {
suspend fun getInfo(){ suspend fun getInfo(): UserDTO{
domainRepositoryImpl.getInfo() return domainRepositoryImpl.getInfo()
} }
} }

View File

@ -22,6 +22,7 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -35,6 +36,7 @@ import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.nto.data.utils.Destinations
import com.nto.presentation.R import com.nto.presentation.R
import com.nto.presentation.composable.DecoratedButton import com.nto.presentation.composable.DecoratedButton
import com.nto.presentation.composable.cards.VisitCard import com.nto.presentation.composable.cards.VisitCard
@ -48,6 +50,11 @@ fun ProfileScreen(
viewModel: ProfileViewModel = hiltViewModel<ProfileViewModel>(), viewModel: ProfileViewModel = hiltViewModel<ProfileViewModel>(),
) { ) {
val state = viewModel.state.collectAsState().value val state = viewModel.state.collectAsState().value
LaunchedEffect(Unit) {
if (state.isUnauthorized) {
//navController.navigate(Destinations.Login)
}
}
Column( Column(
modifier = modifier.background(NTOTheme.colors.primaryBackground) modifier = modifier.background(NTOTheme.colors.primaryBackground)
@ -184,7 +191,7 @@ fun ProfileScreen(
horizontalArrangement = Arrangement.SpaceBetween horizontalArrangement = Arrangement.SpaceBetween
) { ) {
Text( Text(
stringResource(R.string.lablel_last_visit), stringResource(R.string.label_last_visit),
style = NTOTheme.typography.placeholder, style = NTOTheme.typography.placeholder,
fontSize = 12.sp fontSize = 12.sp
) )
@ -194,7 +201,7 @@ fun ProfileScreen(
} }
Spacer(modifier = Modifier.height(20.dp)) Spacer(modifier = Modifier.height(20.dp))
Text( Text(
stringResource(R.string.lablel_visits), stringResource(R.string.label_visits),
style = NTOTheme.typography.displaySmall, style = NTOTheme.typography.displaySmall,
fontWeight = FontWeight.Bold fontWeight = FontWeight.Bold
) )
@ -207,7 +214,7 @@ fun ProfileScreen(
} }
} }
DecoratedButton( DecoratedButton(
stringResource(R.string.lablel_scan), stringResource(R.string.label_scan),
false, false,
modifier = Modifier modifier = Modifier
.padding(10.dp) .padding(10.dp)

View File

@ -1,12 +1,37 @@
package com.nto.presentation.screens.profileScreen package com.nto.presentation.screens.profileScreen
import android.content.Context
import com.nto.data.models.Position
import com.nto.data.models.UserDTO
import com.nto.data.models.cards.VisitCardDTO import com.nto.data.models.cards.VisitCardDTO
import com.nto.presentation.R
import java.time.format.DateTimeFormatter
data class ProfileState( data class ProfileState(
val firstName: String = "", var firstName: String = "",
val secondName: String = "", var secondName: String = "",
val thirdName: String = "", var thirdName: String = "",
val lastOpen: String = "", var lastOpen: String = "",
val job: String = "", var job: String = "",
var isUnauthorized: Boolean = false,
val visits: List<VisitCardDTO> = listOf() val visits: List<VisitCardDTO> = listOf()
) ){
fun deserialize(o: UserDTO, context: Context){
this.firstName = o.firstName
this.secondName = o.secondName
this.thirdName = o.thirdName
this.lastOpen = o.lastVisit.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
this.job = translatePosition(o.position, context)
this.isUnauthorized = o.isUnauthorized
}
private fun translatePosition(position: Position, context:Context): String {
return when (position) {
Position.TESTER -> context.getString(R.string.label_tester)
Position.DEVELOPER -> context.getString(R.string.label_developer)
Position.DESIGNER -> context.getString(R.string.label_designer)
Position.ANALYST -> context.getString(R.string.label_analyst)
Position.ADMINISTRATOR -> context.getString(R.string.label_administrator)
}
}
}

View File

@ -1,11 +1,15 @@
package com.nto.presentation.screens.profileScreen package com.nto.presentation.screens.profileScreen
import android.content.Context
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.navigation.NavController import androidx.navigation.NavController
import com.nto.data.models.Position
import com.nto.data.utils.Destinations import com.nto.data.utils.Destinations
import com.nto.domain.usecase.ProfileUseCase import com.nto.domain.usecase.ProfileUseCase
import com.nto.presentation.R
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
@ -14,15 +18,19 @@ import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class ProfileViewModel @Inject constructor(private val useCase: ProfileUseCase) : ViewModel() { class ProfileViewModel @Inject constructor(
private val useCase: ProfileUseCase, @ApplicationContext private val context: Context
) : ViewModel() {
private val _state = MutableStateFlow(ProfileState()) private val _state = MutableStateFlow(ProfileState())
val state: StateFlow<ProfileState> val state: StateFlow<ProfileState>
get() = _state.asStateFlow() get() = _state.asStateFlow()
fun updateInfo(){ fun updateInfo() {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
val result = useCase.getInfo() val result = useCase.getInfo()
if (result.isError) return@launch
_state.tryEmit(ProfileState().apply { deserialize(result, context) })
} }
} }
@ -43,6 +51,6 @@ class ProfileViewModel @Inject constructor(private val useCase: ProfileUseCase)
} }
init { init {
updateInfo()
} }
} }

View File

@ -10,7 +10,12 @@
<string name="title_profile">Профиль</string> <string name="title_profile">Профиль</string>
<string name="label_qr_login">Вход по коду</string> <string name="label_qr_login">Вход по коду</string>
<string name="label_card_login">Вход по карте</string> <string name="label_card_login">Вход по карте</string>
<string name="lablel_last_visit">Последний вход:</string> <string name="label_last_visit">Последний вход:</string>
<string name="lablel_visits">Посещения</string> <string name="label_visits">Посещения</string>
<string name="lablel_scan">Сканировать код</string> <string name="label_scan">Сканировать код</string>
<string name="label_tester">Тестировщик</string>
<string name="label_developer">Разработчик</string>
<string name="label_designer">Дизайнер</string>
<string name="label_analyst">Аналитик</string>
<string name="label_administrator">Администратор</string>
</resources> </resources>