From ddbb5fdf8a41627d1dc4289390b56ccc8f084c55 Mon Sep 17 00:00:00 2001 From: Nymos Date: Wed, 19 Feb 2025 13:57:05 +0300 Subject: [PATCH] Half-implement user retrieving logic --- .../main/java/com/nto/data/models/QRDTO.kt | 6 +++ .../main/java/com/nto/data/models/UserDTO.kt | 18 +++++++++ .../com/nto/data/models/cards/VisitCardDTO.kt | 14 +++++-- .../com/nto/data/repository/DataRepository.kt | 3 +- .../nto/data/repository/DataRepositoryImpl.kt | 7 +++- .../java/com/nto/data/utils/RetrofitApi.kt | 6 ++- .../nto/domain/repository/DomainRepository.kt | 3 +- .../domain/repository/DomainRepositoryImpl.kt | 5 ++- .../com/nto/domain/usecase/ProfileUseCase.kt | 5 ++- .../screens/profileScreen/ProfileScreen.kt | 13 +++++-- .../screens/profileScreen/ProfileState.kt | 37 ++++++++++++++++--- .../screens/profileScreen/ProfileViewModel.kt | 14 +++++-- presentation/src/main/res/values/strings.xml | 11 ++++-- 13 files changed, 115 insertions(+), 27 deletions(-) create mode 100644 data/src/main/java/com/nto/data/models/QRDTO.kt create mode 100644 data/src/main/java/com/nto/data/models/UserDTO.kt diff --git a/data/src/main/java/com/nto/data/models/QRDTO.kt b/data/src/main/java/com/nto/data/models/QRDTO.kt new file mode 100644 index 0000000..1fd82a8 --- /dev/null +++ b/data/src/main/java/com/nto/data/models/QRDTO.kt @@ -0,0 +1,6 @@ +package com.nto.data.models + +data class QRDTO( + val id: Long = Long.MAX_VALUE, + val name: String = "" +) \ No newline at end of file diff --git a/data/src/main/java/com/nto/data/models/UserDTO.kt b/data/src/main/java/com/nto/data/models/UserDTO.kt new file mode 100644 index 0000000..81a3652 --- /dev/null +++ b/data/src/main/java/com/nto/data/models/UserDTO.kt @@ -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 = "" +) diff --git a/data/src/main/java/com/nto/data/models/cards/VisitCardDTO.kt b/data/src/main/java/com/nto/data/models/cards/VisitCardDTO.kt index 298be16..274bf31 100644 --- a/data/src/main/java/com/nto/data/models/cards/VisitCardDTO.kt +++ b/data/src/main/java/com/nto/data/models/cards/VisitCardDTO.kt @@ -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() ) diff --git a/data/src/main/java/com/nto/data/repository/DataRepository.kt b/data/src/main/java/com/nto/data/repository/DataRepository.kt index 886f807..cf12964 100644 --- a/data/src/main/java/com/nto/data/repository/DataRepository.kt +++ b/data/src/main/java/com/nto/data/repository/DataRepository.kt @@ -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 } \ No newline at end of file diff --git a/data/src/main/java/com/nto/data/repository/DataRepositoryImpl.kt b/data/src/main/java/com/nto/data/repository/DataRepositoryImpl.kt index 0d66378..362ca37 100644 --- a/data/src/main/java/com/nto/data/repository/DataRepositoryImpl.kt +++ b/data/src/main/java/com/nto/data/repository/DataRepositoryImpl.kt @@ -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) } } \ No newline at end of file diff --git a/data/src/main/java/com/nto/data/utils/RetrofitApi.kt b/data/src/main/java/com/nto/data/utils/RetrofitApi.kt index ab6fec8..620632d 100644 --- a/data/src/main/java/com/nto/data/utils/RetrofitApi.kt +++ b/data/src/main/java/com/nto/data/utils/RetrofitApi.kt @@ -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 + + @GET("employee/info") + fun getInfo(@Header("Authorization") token: String): Call } \ No newline at end of file diff --git a/domain/src/main/java/com/nto/domain/repository/DomainRepository.kt b/domain/src/main/java/com/nto/domain/repository/DomainRepository.kt index 6198c4a..84bac45 100644 --- a/domain/src/main/java/com/nto/domain/repository/DomainRepository.kt +++ b/domain/src/main/java/com/nto/domain/repository/DomainRepository.kt @@ -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 } \ No newline at end of file diff --git a/domain/src/main/java/com/nto/domain/repository/DomainRepositoryImpl.kt b/domain/src/main/java/com/nto/domain/repository/DomainRepositoryImpl.kt index 42dbbe9..25d1972 100644 --- a/domain/src/main/java/com/nto/domain/repository/DomainRepositoryImpl.kt +++ b/domain/src/main/java/com/nto/domain/repository/DomainRepositoryImpl.kt @@ -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() } } \ No newline at end of file diff --git a/domain/src/main/java/com/nto/domain/usecase/ProfileUseCase.kt b/domain/src/main/java/com/nto/domain/usecase/ProfileUseCase.kt index 1895e1c..fc80b51 100644 --- a/domain/src/main/java/com/nto/domain/usecase/ProfileUseCase.kt +++ b/domain/src/main/java/com/nto/domain/usecase/ProfileUseCase.kt @@ -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() } } \ No newline at end of file diff --git a/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileScreen.kt b/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileScreen.kt index 170576d..dee5739 100644 --- a/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileScreen.kt +++ b/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileScreen.kt @@ -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(), ) { 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) diff --git a/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileState.kt b/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileState.kt index e6f467e..3df1040 100644 --- a/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileState.kt +++ b/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileState.kt @@ -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 = 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) + } + } +} diff --git a/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileViewModel.kt b/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileViewModel.kt index 384b7d2..9d4d17d 100644 --- a/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileViewModel.kt +++ b/presentation/src/main/java/com/nto/presentation/screens/profileScreen/ProfileViewModel.kt @@ -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 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() } } \ No newline at end of file diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index 54b8a3b..f31c39a 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -10,7 +10,12 @@ Профиль Вход по коду Вход по карте - Последний вход: - Посещения - Сканировать код + Последний вход: + Посещения + Сканировать код + Тестировщик + Разработчик + Дизайнер + Аналитик + Администратор \ No newline at end of file