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
import com.nto.data.models.QRDTO
import java.time.LocalDateTime
enum class VisitType {
PHONE_ENTRY, CARD_ENTRY
}
data class VisitCardDTO(
val name: String = "",
val id: String = "",
val dateString: String = "",
val isCode: Boolean = false
val id: Long = Long.MAX_VALUE,
val dateString: LocalDateTime = LocalDateTime.now(),
val visitType: VisitType = VisitType.CARD_ENTRY,
val qrCode: QRDTO = QRDTO()
)

View File

@ -1,10 +1,11 @@
package com.nto.data.repository
import com.nto.data.models.LoginResult
import com.nto.data.models.UserDTO
interface DataRepository {
suspend fun auth(login: String, password: String): LoginResult
suspend fun saveToken(token: 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.MODE_PRIVATE
import com.nto.data.models.LoginResult
import com.nto.data.models.UserDTO
import com.nto.data.utils.Provider
import dagger.hilt.android.qualifiers.ApplicationContext
import okhttp3.Credentials
@ -27,8 +28,10 @@ class DataRepositoryImpl @Inject constructor(@ApplicationContext private val con
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
import com.nto.data.models.UserDTO
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Header
interface RetrofitApi {
@GET("auth")
@GET("employee/auth")
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
import com.nto.data.models.LoginResult
import com.nto.data.models.UserDTO
interface DomainRepository {
suspend fun auth(email: String, password: String): LoginResult
suspend fun saveToken(token: String)
suspend fun getToken(): String
suspend fun getInfo()
suspend fun getInfo(): UserDTO
}

View File

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

View File

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

View File

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

View File

@ -1,12 +1,37 @@
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.presentation.R
import java.time.format.DateTimeFormatter
data class ProfileState(
val firstName: String = "",
val secondName: String = "",
val thirdName: String = "",
val lastOpen: String = "",
val job: String = "",
var firstName: String = "",
var secondName: String = "",
var thirdName: String = "",
var lastOpen: String = "",
var job: String = "",
var isUnauthorized: Boolean = false,
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
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.navigation.NavController
import com.nto.data.models.Position
import com.nto.data.utils.Destinations
import com.nto.domain.usecase.ProfileUseCase
import com.nto.presentation.R
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@ -14,15 +18,19 @@ import kotlinx.coroutines.launch
import javax.inject.Inject
@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())
val state: StateFlow<ProfileState>
get() = _state.asStateFlow()
fun updateInfo(){
fun updateInfo() {
viewModelScope.launch(Dispatchers.IO) {
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 {
updateInfo()
}
}

View File

@ -10,7 +10,12 @@
<string name="title_profile">Профиль</string>
<string name="label_qr_login">Вход по коду</string>
<string name="label_card_login">Вход по карте</string>
<string name="lablel_last_visit">Последний вход:</string>
<string name="lablel_visits">Посещения</string>
<string name="lablel_scan">Сканировать код</string>
<string name="label_last_visit">Последний вход:</string>
<string name="label_visits">Посещения</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>