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 app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -225,5 +225,5 @@ dependencies {
implementation('com.google.accompanist:accompanist-permissions:0.37.3')

//XpehoUI
implementation "com.xpeho.packages:xpeho_ui_android:1.7.0"
implementation "com.xpeho.packages:xpeho_ui_android:1.7.1"
}
1 change: 1 addition & 0 deletions app/src/main/java/com/xpeho/xpeapp/data/Constants.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ enum class FeatureFlippingEnum(val value: String) {
QVST("campaign"),
PROFILE("profile"),
AGENDA("agenda"),
IDEABOX("ideaBox")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.xpeho.xpeapp.data.model.ideaBox

data class IdeaSubmission (
val context: String,
val description: String,
)

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.xpeho.xpeapp.data.model.WordpressToken
import com.xpeho.xpeapp.data.model.agenda.AgendaBirthday
import com.xpeho.xpeapp.data.model.agenda.AgendaEvent
import com.xpeho.xpeapp.data.model.agenda.AgendaEventType
import com.xpeho.xpeapp.data.model.ideaBox.IdeaSubmission
import com.xpeho.xpeapp.data.model.qvst.QvstCampaign
import com.xpeho.xpeapp.data.model.qvst.QvstProgress
import com.xpeho.xpeapp.data.model.qvst.QvstQuestion
Expand Down Expand Up @@ -344,6 +345,24 @@ class WordpressRepository(
)
}

// Idea Box features methods
// submitIdeas

suspend fun submitIdea(
userIdeaSubmission: IdeaSubmission
): Boolean {
handleServiceExceptions(
tryBody = {
api.submitIdea(userIdeaSubmission)
return true
},
catchBody = { e ->
Log.e("WordpressRepository: submitIdea", "Network error: ${e.message}")
return false
}
)
}


// Exceptions handling

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ 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.model.ideaBox.IdeaSubmission
import com.xpeho.xpeapp.data.entity.user.UserEditPassword
import com.xpeho.xpeapp.data.model.user.UserInfos
import com.xpeho.xpeapp.data.model.WordpressToken
Expand Down Expand Up @@ -113,4 +114,11 @@ interface WordpressService {
suspend fun fetchImageStorage(
@Path("imageName", encoded = true) imageName: String,
): Response<okhttp3.ResponseBody>

// Idea Box Feature
@Headers("Content-Type: application/json")
@POST("xpeho/v1/ideas")
suspend fun submitIdea(
@Body userIdeaSubmission: IdeaSubmission
): Response<Unit>
}
3 changes: 2 additions & 1 deletion app/src/main/java/com/xpeho/xpeapp/enums/Screens.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ enum class Screens {
Qvst,
Profile,
Agenda,
Agency
Agency,
IdeaBox
}
11 changes: 11 additions & 0 deletions 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.HomePage
import com.xpeho.xpeapp.ui.page.LoginPage
import com.xpeho.xpeapp.ui.page.NewsletterPage
import com.xpeho.xpeapp.ui.page.AgendaPage
import com.xpeho.xpeapp.ui.page.IdeaBoxPage
import com.xpeho.xpeapp.ui.page.qvst.QvstCampaignDetailPage
import com.xpeho.xpeapp.ui.page.qvst.QvstPage
import com.xpeho.xpeapp.ui.page.user.ProfilePage
Expand Down Expand Up @@ -92,6 +93,16 @@ fun NavGraphBuilder.navigationBuilder(
}
}

composable(route = Screens.IdeaBox.name) {
Layout(navigationController) {
if (ffManager.isFeatureEnabled(FeatureFlippingEnum.IDEABOX)) {
IdeaBoxPage()
} else {
DisabledFeaturePlaceHolder()
}
}
}

composable(route = Screens.Agency.name) {
Layout(navigationController) {
AgencyPage()
Expand Down
8 changes: 7 additions & 1 deletion app/src/main/java/com/xpeho/xpeapp/ui/Resources.kt
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,13 @@ class Resources {
title = "Agenda",
redirection = Screens.Agenda.name,
featureFlippingId = FeatureFlippingEnum.AGENDA,
)
),
Menu(
idImage = XpehoRes.ideabulb,
title = "Boite à idées",
redirection = Screens.IdeaBox.name,
featureFlippingId = FeatureFlippingEnum.IDEABOX,
),
)

var listOfRequest: Array<RequestLeaveDetail> =
Expand Down
118 changes: 118 additions & 0 deletions app/src/main/java/com/xpeho/xpeapp/ui/page/IdeaBoxPage.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package com.xpeho.xpeapp.ui.page

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.xpeho.xpeapp.ui.components.CustomDialog
import com.xpeho.xpeapp.ui.components.layout.Title
import com.xpeho.xpeapp.ui.viewModel.ideaBox.IdeaBoxState
import com.xpeho.xpeapp.ui.viewModel.ideaBox.IdeaBoxViewModel
import com.xpeho.xpeho_ui_android.ClickyButton
import com.xpeho.xpeho_ui_android.InputText
import java.util.UUID

@Composable
fun IdeaBoxPage(
ideaBoxViewModel: IdeaBoxViewModel = viewModel()
) {
var inputsResetKey by remember { mutableStateOf(UUID.randomUUID().toString()) }

// Quand l’état passe à SAVED, on réinitialise le formulaire
LaunchedEffect(ideaBoxViewModel.state) {
if (ideaBoxViewModel.state is IdeaBoxState.SAVED) {
ideaBoxViewModel.clearInputs()
inputsResetKey = UUID.randomUUID().toString()
}
}

LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 24.dp, vertical = 32.dp),
horizontalAlignment = Alignment.Start
) {
item {
Title(label = "Partage ton idée")
Spacer(modifier = Modifier.height(50.dp))
}

item {
Text("Contexte : ")
Spacer(modifier = Modifier.height(24.dp))

key(inputsResetKey) {
InputText(
label = "Thématique (ex : Agence, en mission, formation)",
labelSize = 14.sp,
inputSize = 16.sp,
defaultInput = ideaBoxViewModel.contextText.value,
onInput = { ideaBoxViewModel.contextText.value = it },
)
}

Spacer(modifier = Modifier.height(24.dp))
}

item {
Text("Description : ")
Spacer(modifier = Modifier.height(24.dp))

key(inputsResetKey) {
InputText(
label = "Mon idée/Ma suggestion",
labelSize = 14.sp,
inputSize = 16.sp,
defaultInput = ideaBoxViewModel.descriptionText.value,
onInput = { ideaBoxViewModel.descriptionText.value = it },
)
}

Spacer(modifier = Modifier.height(62.dp))
}

item {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth()
) {
ClickyButton(
label = "SOUMETTRE",
size = 14.sp,
verticalPadding = 12.dp,
horizontalPadding = 48.dp,
labelColor = Color.White,
enabled = !ideaBoxViewModel.isLoading.value
) {
ideaBoxViewModel.submitIdea()
}

when (val s = ideaBoxViewModel.state) {
is IdeaBoxState.ERROR -> CustomDialog(
title = "Erreur",
message = s.error,
closeDialog = { ideaBoxViewModel.resetState() }
)

IdeaBoxState.SAVED -> CustomDialog(
title = "Merci",
message = "Merci ! Votre idée a bien été envoyée.",
closeDialog = {
ideaBoxViewModel.resetState()
ideaBoxViewModel.clearInputs()
inputsResetKey = UUID.randomUUID().toString()
}
)

else -> Unit
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.xpeho.xpeapp.ui.viewModel.ideaBox

import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.xpeho.xpeapp.XpeApp
import com.xpeho.xpeapp.data.model.ideaBox.IdeaSubmission
import kotlinx.coroutines.launch

class IdeaBoxViewModel : ViewModel() {

private val wordpressRepository = XpeApp.appModule.wordpressRepository

val isLoading: MutableState<Boolean> = mutableStateOf(false)

// Champs de la page
val contextText: MutableState<String> = mutableStateOf("")
val descriptionText: MutableState<String> = mutableStateOf("")

// Etat de la page (vide / loading / saved / error)
var state: IdeaBoxState by mutableStateOf(IdeaBoxState.EMPTY)


fun submitIdea() {
// Validation minimale
if (descriptionText.value.isBlank()) {
state = IdeaBoxState.ERROR("Merci de décrire votre idée")
return
}

isLoading.value = true
state = IdeaBoxState.LOADING

viewModelScope.launch {
val submission = IdeaSubmission(
context = contextText.value.trim(),
description = descriptionText.value.trim()
)

val result = wordpressRepository.submitIdea(submission)

if (result) {
state = IdeaBoxState.SAVED
clearInputs()
} else {
state = IdeaBoxState.ERROR("Oups, une erreur est survenue lors de l'envoi. Réessayez.")
}

isLoading.value = false
}
}

fun clearInputs() {
contextText.value = ""
descriptionText.value = ""
}

fun resetState() {
state = IdeaBoxState.EMPTY
}
}

sealed interface IdeaBoxState {
object EMPTY : IdeaBoxState
object LOADING : IdeaBoxState
data class ERROR(val error: String) : IdeaBoxState
object SAVED : IdeaBoxState
}
Loading