Henri
12/13/2023, 2:14 PMTimo Drick
12/13/2023, 2:22 PMHenri
12/13/2023, 2:24 PM@Composable
fun Digit(
feedbackId: String,
questionAndResponse: QuestionAndResponse,
onSaveResponse: (String, Question, Any) -> Unit,
onAutomaticSaveResponse: (String, Question, Any) -> Unit,
onRememberState: (String, (Response?) -> Unit) -> Unit,
modifier: Modifier = Modifier
) {
var isDisplayedTextAlreadyChanged by remember {
mutableStateOf(false)
}
val mapper by remember {
mutableStateOf(ResponseValueToString())
}
var displayedText by rememberSaveable {
val response = mapper.map(questionAndResponse.response?.value, questionAndResponse.type)
if (response == "")
mutableStateOf("")
else
mutableStateOf(response)
}
LaunchedEffect(
key1 = questionAndResponse.response?.value,
block = {
if (questionAndResponse.question.isComputed()){
displayedText = mapper.map(questionAndResponse.response?.value, questionAndResponse.type)
}
}
)
val configs by remember {
mutableStateOf(questionAndResponse.configs as Configs.Digit)
}
var isError: Boolean by rememberSaveable {
mutableStateOf(false)
}
LaunchedEffect(
key1 = Unit,
block = {
if (questionAndResponse.question.rememberState == true){
onRememberState(
questionAndResponse.question.id
) { response ->
if (response != null && questionAndResponse.response == null) {
onAutomaticSaveResponse(
feedbackId,
questionAndResponse.question,
response.valueAsString ?: ""
)
}
}
}
}
)
LaunchedEffect(
key1 = displayedText,
block = {
if (!isError && isDisplayedTextAlreadyChanged){
onSaveResponse(
feedbackId,
questionAndResponse.question,
displayedText.evalExpression()?:"0"
)
}
}
)
Column(modifier = modifier) {
OutlinedTextField(
value = displayedText,
onValueChange = { newText ->
//text = it
isDisplayedTextAlreadyChanged = true
if(!questionAndResponse.question.isComputed() && isDisplayedTextAlreadyChanged){
displayedText = newText
}
isError = if (newText.isNotBlank()) {
try {
(newText.toBigDecimal().compareTo(configs.maxValue?.toBigDecimal())) == 1 || (newText.toBigDecimal().compareTo(configs.minValue?.toBigDecimal())) == -1
}catch (e: Exception){
false
}
} else {
false
}
},
keyboardOptions = KeyboardOptions(keyboardType =
if(configs.allowComputations == true)
KeyboardType.Text
else KeyboardType.Number
),
textStyle = MaterialTheme.typography.h6.copy(fontWeight = FontWeight.W400),
modifier = Modifier
.fillMaxWidth()
.height(60.dp)
.background(color = Color.White),
enabled = !questionAndResponse.question.isComputed(),
//.padding(bottom = 7.dp),
trailingIcon = {
if (isError)
Icon(Icons.Default.Warning, "error", tint = MaterialTheme.colors.error)
},
placeholder = {
Text(text = configs.hint ?: "")
},
isError = isError,
shape = RoundedCornerShape(5.dp),
singleLine = true,
colors = TextFieldDefaults.outlinedTextFieldColors(
textColor = Color(0xFF082444),
focusedBorderColor = Color(0xFFCDDBEC),
unfocusedBorderColor = Color(0xFFCDDBEC),
cursorColor = Color(0xFF082444),
backgroundColor = Color.White,
placeholderColor = Color(0xFFBABFCC),
),
)
if (configs.allowComputations == true &&
displayedText.isEval()
) {
Text(
text = displayedText.evalExpression().let {
if(it == null) "Invalid operation"
else "RESULT = $it"
},
color = if(displayedText.evalExpression() == null)
MaterialTheme.colors.error else Color(0xFF259705),
style = MaterialTheme.typography.caption,
modifier = Modifier.padding(start = 16.dp)
)
}
if (isError) {
Text(
text = "The nombre entered must range in ${configs.minValue} et ${configs.maxValue}.",
color = MaterialTheme.colors.error,
style = MaterialTheme.typography.caption,
modifier = Modifier.padding(start = 16.dp)
)
}
}
}
@Immutable
data class QuestionAndResponse(
@Embedded val question: Question,
@Embedded val response: Response?
)
@Immutable
@Entity(primaryKeys = ["id", "form_id"])
data class Question(
override val id: String,
val name: String? = null,
val help: String? = null,
val configs: Configs? = null,
val type: QuestionType,
val position: Int = 0,
@ColumnInfo(name = "is_mandatory") val isMandatory: Boolean? = null,
@ColumnInfo(name = "is_hidden") val isHidden: Boolean? = null,
@ColumnInfo(name = "is_display_question") val isDisplayQuestion: Boolean? = null,
@ColumnInfo(name = "section_id") val sectionId: String? = null,
@ColumnInfo(name = "form_id") val formId: String,
@ColumnInfo(name = "form_version") val formVersion: String? = null,
@ColumnInfo(name = "computed_value") val computedValue: String? = null,
@ColumnInfo(name = "remember_state") val rememberState: Boolean? = null
)
@Immutable
@Entity(
primaryKeys = ["question_id", "feedback_id"],
indices = [
Index(value = ["value", "value_as_string"])
]
)
data class Response(
@ColumnInfo(name = "question_id") val questionId: String,
@ColumnInfo(name = "feedback_id") val feedbackId: String,
@ColumnInfo(name = "response_type") val responseType: QuestionType,
@ColumnInfo(name = "value") val value: String,
@ColumnInfo(name = "value_as_string") val valueAsString: String?,
@ColumnInfo(name = "onlineId") override val onlineId: String? = null,
@ColumnInfo(name = "pending_action") override val pendingAction: PendingAction = PendingAction.NOTHING,
@ColumnInfo(name = "actions_types") override val actionsType: List<ActionType> = emptyList(),
@ColumnInfo(name = "is_valid") val isValid: Boolean = true,
val error: DaggaError? = null,
@ColumnInfo(name = "updated_at") val updateAt: OffsetDateTime = OffsetDateTime.now()
)
Timo Drick
12/13/2023, 2:42 PMHenri
12/13/2023, 2:47 PMTimo Drick
12/13/2023, 2:51 PMHenri
12/13/2023, 2:55 PMTimo Drick
12/13/2023, 2:57 PMTimo Drick
12/13/2023, 2:58 PMHenri
12/13/2023, 3:00 PMTimo Drick
12/13/2023, 3:01 PMTimo Drick
12/13/2023, 3:01 PMHenri
12/13/2023, 3:02 PM