Last active
February 2, 2023 14:39
-
-
Save Jalson1982/83f482230ef1c68ae7a775f5459aef3c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@HiltViewModel | |
internal class HealthStudyQuestionsViewModel @Inject constructor( | |
savedStateHandle: SavedStateHandle, | |
private val getSurvey: GetSurvey, | |
private val updateQuestion: UpdateQuestion, | |
) : ViewModel() { | |
private val survey = savedStateHandle.get<String>("survey") | |
private val _state = MutableStateFlow(HealthStudyViewState()) | |
val state = _state.asStateFlow() | |
init { | |
val parsedSurvey = survey?.let { parser.jsonToObject<SurveyResponse>(it) } | |
survey?.let { | |
parsedSurvey?.survey?.let { it1 -> setSurveyData(it1, parsedSurvey.backgroundImageUrl) } | |
} ?: run { | |
viewModelScope.launch { | |
getSurvey(GetSurvey.Params(parsedSurvey?.surveyId)).collectLatest { result -> | |
result?.let { setSurveyData(it) } | |
} | |
} | |
} | |
} | |
private fun setSurveyData(survey: Survey, backgroundImageUrl: URL? = null) { | |
survey.questions?.let { populateAnswersData(it) } | |
_state.value = _state.value.copy( | |
survey = Survey( | |
bookmark = survey.bookmark, | |
completedData = survey.completedData, | |
completedMessage = survey.completedMessage, | |
id = survey.id, | |
questions = survey.questions, | |
title = survey.title, | |
backgroundImageUrl = backgroundImageUrl | |
), | |
currentIndex = survey.bookmark ?: 0 | |
) | |
} | |
fun singleSelectionQuestionSelected(id: String, questionId: String) { | |
val questionId = state.value.survey?.questions?.get(state.value.currentIndex)?.id ?: "" | |
val updatedAnswerData = _state.value.answerData.toMutableMap().apply { | |
put(questionId, AnswerData.SingleSelectionInputValue(id = id)) | |
} | |
_state.value = _state.value.copy(answerData = updatedAnswerData) | |
} | |
fun multiSelectionQuestionSelected(id: String) { | |
val currentQuestionId = | |
state.value.survey?.questions?.get(state.value.currentIndex)?.id ?: "" | |
val updatedAnswerData = state.value.answerData.toMutableMap().apply { | |
when (val currentAnswerData = get(currentQuestionId)) { | |
is AnswerData.MultiSelectionInputValue -> { | |
val updatedIds = currentAnswerData.ids.toMutableList().apply { | |
if (contains(id)) { | |
remove(id) | |
} else { | |
add(id) | |
} | |
} | |
put(currentQuestionId, AnswerData.MultiSelectionInputValue(ids = updatedIds)) | |
} | |
else -> { | |
put(currentQuestionId, AnswerData.MultiSelectionInputValue(ids = listOf(id))) | |
} | |
} | |
} | |
_state.value = _state.value.copy(answerData = updatedAnswerData) | |
} | |
fun updateFreeTextQuestion(text: String) { | |
val questionId = state.value.survey?.questions?.get(state.value.currentIndex)?.id ?: "" | |
val updatedAnswerData = _state.value.answerData.toMutableMap().apply { | |
put(questionId, AnswerData.FreeTextInputValue(value = text)) | |
} | |
_state.value = _state.value.copy(answerData = updatedAnswerData) | |
} | |
fun updateLikertScaleQuestion(id: String) { | |
val questionId = state.value.survey?.questions?.get(state.value.currentIndex)?.id ?: "" | |
val updatedAnswerData = _state.value.answerData.toMutableMap().apply { | |
put(questionId, AnswerData.LikertScaleQuestion(id = id)) | |
} | |
_state.value = _state.value.copy(answerData = updatedAnswerData) | |
} | |
fun updateMonthYearQuestion(month: Int, year: Int, skipped: Boolean = false) { | |
val questionId = state.value.survey?.questions?.get(state.value.currentIndex)?.id ?: "" | |
val updatedAnswerData = _state.value.answerData.toMutableMap().apply { | |
put( | |
questionId, | |
AnswerData.MonthYearQuestion(month = month, year = year, skipped = skipped) | |
) | |
} | |
_state.value = _state.value.copy(answerData = updatedAnswerData) | |
} | |
fun updateNumericQuestion(value: String, skipped: Boolean = false) { | |
val questionId = state.value.survey?.questions?.get(state.value.currentIndex)?.id ?: "" | |
val updatedAnswerData = _state.value.answerData.toMutableMap().apply { | |
put(questionId, AnswerData.NumericQuestionInputValue(value = value, skipped = skipped)) | |
} | |
_state.value = _state.value.copy(answerData = updatedAnswerData) | |
} | |
fun updateContactFormQuestion( | |
email: String = "", | |
phoneNumber: String = "", | |
) { | |
val questionId = state.value.survey?.questions?.get(state.value.currentIndex)?.id ?: "" | |
val updatedAnswerData = _state.value.answerData.toMutableMap().apply { | |
put( | |
questionId, | |
AnswerData.ContactFormQuestion(email = email, phoneNumber = phoneNumber) | |
) | |
} | |
_state.value = _state.value.copy(answerData = updatedAnswerData) | |
} | |
fun updateEmojiQuestion(id: String, skipped: Boolean = false) { | |
val questionId = state.value.survey?.questions?.get(state.value.currentIndex)?.id ?: "" | |
val updatedAnswerData = _state.value.answerData.toMutableMap().apply { | |
put( | |
questionId, | |
AnswerData.EmojiQuestion(value = EmojiQuestionInput(id = id, skipped = skipped)) | |
) | |
} | |
_state.value = _state.value.copy(answerData = updatedAnswerData) | |
} | |
fun updateQuestionHandler() { | |
viewModelScope.launch { | |
val currentQuestion = | |
_state.value.survey?.questions?.get(state.value.currentIndex) ?: return@launch | |
val currentAnswer = _state.value.answerData[currentQuestion.id] ?: return@launch | |
goNext() | |
val params = UpdateQuestion.Params( | |
id = _state.value.survey?.id ?: "", | |
questionId = currentQuestion.id, | |
body = when (currentQuestion.rawType) { | |
"single-selection" -> { | |
val answer = currentAnswer as AnswerData.SingleSelectionInputValue | |
AnswerBody( | |
value = SingleSelectionInputValue(id = answer.id), | |
type = currentQuestion.rawType, | |
lastQuestion = false | |
) | |
} | |
"multiple-selection" -> { | |
val answer = currentAnswer as AnswerData.MultiSelectionInputValue | |
AnswerBody( | |
value = MultiSelectionInputValue(ids = answer.ids), | |
type = currentQuestion.rawType, | |
lastQuestion = false | |
) | |
} | |
"free-text" -> { | |
val answer = currentAnswer as AnswerData.FreeTextInputValue | |
AnswerBody( | |
value = FreeTextInputValue(value = answer.value), | |
type = currentQuestion.rawType, | |
lastQuestion = false | |
) | |
} | |
"likert-scale" -> { | |
val answer = currentAnswer as AnswerData.LikertScaleQuestion | |
AnswerBody( | |
value = LikertScaleQuestion(id = answer.id), | |
type = currentQuestion.rawType, | |
lastQuestion = false | |
) | |
} | |
"month-and-year-selection" -> { | |
val answer = currentAnswer as AnswerData.MonthYearQuestion | |
AnswerBody( | |
value = MonthYearQuestion( | |
month = answer.month, | |
year = answer.year, | |
skipped = answer.skipped | |
), | |
type = currentQuestion.rawType, | |
lastQuestion = false | |
) | |
} | |
"emoji" -> { | |
val answer = currentAnswer as AnswerData.EmojiQuestion | |
AnswerBody( | |
value = EmojiQuestionInput( | |
id = answer.value.id, | |
skipped = answer.skipped | |
), | |
type = currentQuestion.rawType, | |
lastQuestion = false | |
) | |
} | |
"contact-form" -> { | |
val answer = currentAnswer as AnswerData.ContactFormQuestion | |
AnswerBody( | |
value = ContactFormQuestion( | |
email = answer.email, | |
phoneNumber = answer.phoneNumber | |
), | |
type = currentQuestion.rawType, | |
lastQuestion = false | |
) | |
} | |
else -> { | |
val answer = currentAnswer as AnswerData.NumericQuestionInputValue | |
AnswerBody( | |
value = NumericQuestionInputValue(value = answer.value), | |
type = currentQuestion.rawType, | |
lastQuestion = false | |
) | |
} | |
} | |
) | |
updateQuestion(params).collect() | |
} | |
} | |
private fun populateAnswersData(questions: List<Question>) { | |
questions.forEach { question -> | |
val answerData = _state.value.answerData | |
when (question.rawType) { | |
"single-selection" -> { | |
answerData[question.id] = | |
AnswerData.SingleSelectionInputValue(id = question.selected) | |
} | |
"multiple-selection" -> { | |
val selectedAnswers = question.answers | |
?.filter { it.selected == true } | |
?.map { it.id } | |
answerData[question.id] = | |
selectedAnswers?.let { AnswerData.MultiSelectionInputValue(ids = it) }!! | |
} | |
"free-text" -> { | |
val value = question.value.toString() | |
answerData[question.id] = AnswerData.FreeTextInputValue(value = value) | |
} | |
"likert-scale" -> { | |
val selected = question.selected ?: "" | |
answerData[question.id] = AnswerData.LikertScaleQuestion(id = selected) | |
} | |
"month-and-year-selection" -> { | |
val parsedData = question.value as? Map<String, Double> ?: mapOf() | |
val month = parsedData["month"]?.toInt() ?: 0 | |
val year = parsedData["year"]?.toInt() ?: 0 | |
answerData[question.id] = AnswerData.MonthYearQuestion(month = month, year = year) | |
} | |
"numeric" -> { | |
answerData[question.id] = AnswerData.NumericQuestionInputValue(value = "") | |
} | |
"contact-form" -> { | |
val parsedData = question.value as? Map<String, String> ?: mapOf() | |
val email = parsedData["email"].toString() | |
val phoneNumber = parsedData["phoneNumber"].toString() | |
answerData[question.id] = | |
AnswerData.ContactFormQuestion(email = email, phoneNumber = phoneNumber) | |
} | |
"emoji" -> { | |
val parsedData = question.value as? Map<String, Boolean> ?: mapOf() | |
val value = parsedData["id"].toString() | |
val skipped = parsedData["skipped"] ?: false | |
answerData[question.id] = AnswerData.EmojiQuestion( | |
value = EmojiQuestionInput( | |
id = value, | |
skipped = skipped | |
) | |
) | |
} | |
} | |
} | |
} | |
fun goBack() { | |
_state.update { it.copy(currentIndex = _state.value.currentIndex - 1) } | |
} | |
private fun goNext() { | |
_state.update { it.copy(currentIndex = _state.value.currentIndex + 1) } | |
} | |
fun isNextButtonEnabled(): Boolean { | |
val question = _state.value.survey?.questions?.get(_state.value.currentIndex) | |
return when (val answer = _state.value.answerData[question?.id]) { | |
is AnswerData.SingleSelectionInputValue -> answer.id?.isNotEmpty() ?: false | |
is AnswerData.MultiSelectionInputValue -> answer.ids.isNotEmpty() | |
is AnswerData.FreeTextInputValue -> answer.value.isNotEmpty() | |
is AnswerData.LikertScaleQuestion -> answer.id.isNotEmpty() | |
is AnswerData.MonthYearQuestion -> (answer.month != 0 && answer.year != 0) || answer.skipped | |
is AnswerData.NumericQuestionInputValue -> answer.value.isNotEmpty() || answer.skipped | |
is AnswerData.ContactFormQuestion -> answer.email.isNotEmpty() && isValidEmail(answer.email) && answer.phoneNumber.isNotEmpty() | |
is AnswerData.EmojiQuestion -> answer.value.id.isNotEmpty() || answer.skipped | |
else -> false | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment