Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion xpeapp_android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -215,5 +215,5 @@ dependencies {
implementation("com.google.accompanist:accompanist-permissions:0.31.1-alpha")

//XpehoUI
implementation "com.xpeho.packages:xpeho_ui_android:1.5.0"
implementation "com.xpeho.packages:xpeho_ui_android:1.6.0"
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ enum class FeatureFlippingEnum(val value: String) {
EXPENSE_REPORT("expenseReport"),
COLLEAGUES("colleagues"),
QVST("campaign"),
PROFILE("profile")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.xpeho.xpeapp.data.entity.user

import com.google.gson.annotations.SerializedName

data class UserEditPassword(
@SerializedName("initial_password") val initialPassword: String,
val password: String,
@SerializedName("password_repeat")val passwordRepeat: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.xpeho.xpeapp.data.model.user

sealed interface UpdatePasswordResult{
object IncorrectInitialPassword : UpdatePasswordResult
object PasswordMismatch : UpdatePasswordResult
object Success : UpdatePasswordResult
object NetworkError : UpdatePasswordResult
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.xpeho.xpeapp.data.model.user

data class UserInfos(
val id: String,
val email: String,
val firstname: String,
val lastname: String,
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ import androidx.annotation.VisibleForTesting
import com.xpeho.xpeapp.data.entity.AuthentificationBody
import com.xpeho.xpeapp.data.entity.QvstAnswerBody
import com.xpeho.xpeapp.data.entity.QvstCampaignEntity
import com.xpeho.xpeapp.data.entity.user.UserEditPassword
import com.xpeho.xpeapp.data.model.AuthResult
import com.xpeho.xpeapp.data.model.user.UserInfos
import com.xpeho.xpeapp.data.model.WordpressToken
import com.xpeho.xpeapp.data.model.qvst.QvstCampaign
import com.xpeho.xpeapp.data.model.qvst.QvstProgress
import com.xpeho.xpeapp.data.model.qvst.QvstQuestion
import com.xpeho.xpeapp.data.model.user.UpdatePasswordResult
import retrofit2.HttpException
import java.net.ConnectException
import java.net.SocketTimeoutException
Expand All @@ -25,6 +28,8 @@ class WordpressRepository(

companion object {
private const val HTTPFORBIDDEN = 403
private const val INTERNAL_SERVER_ERROR = 500
private const val NO_CONTENT = 204

private const val DATETIME_FORMATTER_PATTERN = "yyyy-MM-dd"
}
Expand Down Expand Up @@ -186,6 +191,78 @@ class WordpressRepository(
)
}

suspend fun fetchUserInfos(): UserInfos? {
handleServiceExceptions(
tryBody = {
return api.fetchUserInfos()
},
catchBody = { e ->
Log.e("WordpressRepository: fetchUserInfos", "Network error: ${e.message}")
return null
}
)
}

suspend fun updatePassword(
editPassword: UserEditPassword
): UpdatePasswordResult {
var updatePasswordResult: UpdatePasswordResult = UpdatePasswordResult.NetworkError

handleServiceExceptions(
tryBody = {
val result = api.updatePassword(editPassword)
updatePasswordResult = when (result.code()) {
NO_CONTENT -> UpdatePasswordResult.Success
INTERNAL_SERVER_ERROR -> {
val errorBody = result.errorBody()?.string()
when {
errorBody?.contains("incorrect_password") == true -> {
Log.d(
"WordpressRepository: updatePasswordIncorrectInitialPassword",
"Incorrect initial password"
)
UpdatePasswordResult.IncorrectInitialPassword
}

errorBody?.contains("password_mismatch") == true -> {
Log.d(
"WordpressRepository: updatePasswordPasswordMismatch",
"Password mismatch"
)
UpdatePasswordResult.PasswordMismatch
}

else -> {
Log.e(
"WordpressRepository: updatePasswordUnknownError",
"Unknown error: ${result.code()}"
)
UpdatePasswordResult.NetworkError
}
}
}

else -> {
Log.e(
"WordpressRepository: updatePasswordUnknownError",
"Unknown error: ${result.code()}"
)
UpdatePasswordResult.NetworkError
}
}
},
catchBody = {
Log.e(
"WordpressRepository: updatePasswordNetworkError",
"Network error: ${it.message}"
)
updatePasswordResult = UpdatePasswordResult.NetworkError
}
)

return updatePasswordResult
}

// Exceptions handling

@Suppress("ReturnCount")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@ package com.xpeho.xpeapp.data.service

import com.xpeho.xpeapp.data.entity.AuthentificationBody
import com.xpeho.xpeapp.data.entity.QvstAnswerBody
import com.xpeho.xpeapp.data.entity.user.UserEditPassword
import com.xpeho.xpeapp.data.model.user.UserInfos
import com.xpeho.xpeapp.data.model.WordpressToken
import com.xpeho.xpeapp.data.model.qvst.QvstCampaign
import com.xpeho.xpeapp.data.model.qvst.QvstProgress
import com.xpeho.xpeapp.data.model.qvst.QvstQuestion
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Headers
import retrofit2.http.POST
import retrofit2.http.PUT
import retrofit2.http.Path
import retrofit2.http.Query

Expand Down Expand Up @@ -59,5 +63,17 @@ interface WordpressService {
@Header("userId") userId: String,
@Body answers: List<QvstAnswerBody>,
): Boolean

// Fetch the user infos
@Headers("Content-Type: application/json")
@GET("xpeho/v1/user-infos")
suspend fun fetchUserInfos(): UserInfos

// Update the user infos
@Headers("Content-Type: application/json")
@PUT("xpeho/v1/update-password")
suspend fun updatePassword(
@Body editPassword: UserEditPassword
): Response<String>
}

Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class MainAppModule(

private val gson = GsonBuilder().setLenient().create()

private val logging = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY }
private val logging = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BASIC }
private val authorization by lazy {
AuthorizationHeaderInterceptor(
tokenProvider = tokenProvider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ enum class Screens {
Vacation,
Colleague,
Qvst,
Profile
}
10 changes: 10 additions & 0 deletions xpeapp_android/app/src/main/java/com/xpeho/xpeapp/ui/Navigation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.xpeho.xpeapp.ui.page.LoginPage
import com.xpeho.xpeapp.ui.page.NewsletterPage
import com.xpeho.xpeapp.ui.page.qvst.QvstCampaignDetailPage
import com.xpeho.xpeapp.ui.page.qvst.QvstPage
import com.xpeho.xpeapp.ui.page.user.ProfilePage

fun NavGraphBuilder.navigationBuilder(
navigationController: NavHostController,
Expand Down Expand Up @@ -70,4 +71,13 @@ fun NavGraphBuilder.navigationBuilder(
}
}
}
composable(route = Screens.Profile.name) {
Layout(navigationController) {
if (ffManager.isFeatureEnabled(FeatureFlippingEnum.PROFILE)) {
ProfilePage(navigationController = navigationController)
} else {
DisabledFeaturePlaceHolder()
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class Resources {
featureFlippingId = FeatureFlippingEnum.EXPENSE_REPORT,
),
Menu(
idImage = XpehoRes.contactfill,
idImage = XpehoRes.account,
title = "Collègues",
redirection = Screens.Colleague.name,
featureFlippingId = FeatureFlippingEnum.COLLEAGUES,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.xpeho.xpeapp.ui.components.layout

import SidebarItemProfile
import android.content.Intent
import android.net.Uri
import androidx.compose.animation.AnimatedVisibility
Expand All @@ -11,6 +12,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
Expand Down Expand Up @@ -90,15 +92,17 @@ fun Sidebar(
) {
Column(
modifier = Modifier
.fillMaxHeight()
.padding(top = 18.dp, bottom = 20.dp, start = 18.dp, end = 18.dp),
.fillMaxHeight(),
verticalArrangement = Arrangement.SpaceBetween
) {

Column {
IconButton(
onClick = {
sidebarVisible.value = !sidebarVisible.value
}
},
modifier = Modifier
.padding(top = 18.dp, start = 18.dp)
) {
Icon(
painter = painterResource(id = XpehoRes.crossclose),
Expand All @@ -108,39 +112,62 @@ fun Sidebar(
.size(60.dp)
)
}

Spacer(
modifier = Modifier
.height(20.dp)
)
SidebarItem(
navigationController = navigationController,
icon = painterResource(id = R.drawable.home),
label = "Accueil",
route = Screens.Home.name
.height(15.dp)
)

Box(
modifier = Modifier
.fillMaxWidth()
.background(Color.Black.copy(alpha = 0.1f)) // Arrière-plan noir avec 10% d'opacité
) {
SidebarItemProfile(
navigationController = navigationController,
)
}

Spacer(
modifier = Modifier
.height(20.dp)
)
for (menuItem in Resources().listOfMenu) {
if (ffManager.isFeatureEnabled(menuItem.featureFlippingId)) {
SidebarItem(
navigationController = navigationController,
icon = painterResource(id = menuItem.idImage),
label = menuItem.title,
route = menuItem.redirection
)
Spacer(
modifier = Modifier
.height(20.dp)
)
}
}

Column (
modifier = Modifier
.padding(horizontal = 18.dp),
) {
SidebarItem(
navigationController = navigationController,
icon = painterResource(id = R.drawable.home),
label = "Accueil",
route = Screens.Home.name
)
Spacer(
modifier = Modifier
.height(20.dp)
)
for (menuItem in Resources().listOfMenu) {
if (ffManager.isFeatureEnabled(menuItem.featureFlippingId)) {
SidebarItem(
navigationController = navigationController,
icon = painterResource(id = menuItem.idImage),
label = menuItem.title,
route = menuItem.redirection
)
Spacer(
modifier = Modifier
.height(20.dp)
)
}
} }

}
Column(
horizontalAlignment = Alignment.CenterHorizontally
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.padding(bottom = 20.dp, start = 18.dp, end = 18.dp),
) {
SidebarLogoutButtonSection(navigationController)
HorizontalDivider(
color = Color.White,
thickness = 1.dp,
Expand All @@ -151,39 +178,14 @@ fun Sidebar(
SidebarInfoSection(context)
SidebarConfidentialityButton(context)
}
}
}
}
}

@Composable
fun SidebarLogoutButtonSection(
navigationController: NavController
) {
Row(
modifier = Modifier
.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
) {
ClickyButton(
label = "Déconnexion",
size = 16.sp,
verticalPadding = 5.dp,
horizontalPadding = 15.dp,
backgroundColor = Color.White,
labelColor = XpehoColors.CONTENT_COLOR
) {
CoroutineScope(Dispatchers.IO).launch {
XpeApp.appModule.authenticationManager.logout()
}
// Return to login page and clear the backstack
navigationController.navigate(route = Screens.Login.name) {
popUpTo(Screens.Home.name) { inclusive = true }

}
}
}
}


@Composable
fun SidebarInfoSection(
context: android.content.Context
Expand Down
Loading
Loading