Skip to main content

Configuration questionnaire

Thanks to the save and load function from SurveyStorage.kt and some of the classes and functions from ClassSurvey.kt, we are able to define a page to configure the questionnaire in the form of SurveyEntry.kt.

Users can navigate to this screen from the settings screen.

SurveyEntry.kt allows the user to:

  • edit the title and type of each question,
  • add or remove questions,
  • add or remove answer options (for multiple-choice type questions),
  • and finally save the modified questionnaire locally.

The key UI components of this page are:

  • Return button to settings:

    A back arrow button lets the user return to the settings page to cancel any modification of the quesionnaire.

    SurveyEntry.kt
    IconButton(
    onClick = { navController.navigate("settings") },
    modifier = Modifier
    .align(Alignment.Start)
    .padding(top = 1.dp, start = 1.dp),
    ) {
    Icon(
    imageVector = Icons.AutoMirrored.Filled.ArrowBack,
    contentDescription = "Retour aux paramètres",
    tint = PrimaryColor,
    modifier = Modifier.size(50.dp)
    )
    }
  • Page title:

    SurveyEntry.kt
    Text(
    text = "Modifier le Questionnaire",
    style = MaterialTheme.typography.displayLarge,
    fontSize = 40.sp,
    color = MaterialTheme.colorScheme.primary,
    textAlign = TextAlign.Center,
    modifier = Modifier
    .fillMaxWidth()
    .padding(bottom = 24.dp)
    )
  • Dynamic list of questions:

    The key element of this page is this list of questions, where the user is able to edit each question from the questionnaire.
    On launch, the current configuration for the questionnaire is loaded from the application's internal storage with the loadSurvey() function written in file SurveyStorage.kt.

    SurveyEntry.kt
    LaunchedEffect(Unit) {
    val saved = SurveyStorage.loadSurvey(context)
    questions.clear()
    questions.addAll(
    if (saved.isNotEmpty()) saved.map { it.toUi() } else defaultQuestions
    )
    }

    In this part of the page, each question is displayed in a Card containing the following elements:

    • an editable text field for the question label,
    • a delete button to remove the question,
    • a question type selector to set the question's type.

    If the type is multiple choice (CHOIX_UNIQUE or CHOIX_MULTIPLE), other input fields appear for each option, with the ability to add or remove them dynamically.

    As the list of questions with their label, type, and options is modified, everything is also stored in variable questions, which is a mutableStateListOf<SurveyQuestionUI>.

    SurveyEntry.kt
    questions.forEachIndexed { index, question ->
    Card(...)
    {
    Column(...)
    {
    Row(...)
    {
    // Question label text field
    OutlinedTextField(
    value = question.label,
    onValueChange = { questions[index] = question.copy(label = it) },
    label = { Text("Question") },
    modifier = Modifier.weight(1f)
    )

    // Delete button
    IconButton(onClick = { questions.removeAt(index) }) {
    Icon(Icons.Default.Close, contentDescription = "Supprimer")
    }
    }

    // Question type selector
    QuestionTypeSelector(
    selected = question.type,
    onSelected = { questions[index] = question.copy(type = it) }
    )

    // Adding new input fields for the options for MCQs:
    if (question.type == QuestionType.CHOIX_UNIQUE || question.type == QuestionType.CHOIX_MULTIPLE) {
    question.options.forEachIndexed { optIndex, option ->
    Row(...) {
    // Answer option text field
    OutlinedTextField(
    ...
    label = { Text("Option ${optIndex + 1}") }
    )

    // Button to delete the option
    IconButton(onClick = ...) {
    Icon(
    Icons.Default.Close,
    contentDescription = "Supprimer l'option"
    )
    }
    }
    }

    // Button to add a new option to the MCQ
    Button(onClick = {
    questions[index] =
    question.copy(options = question.options + "")
    }) {
    Text("Ajouter une option")
    }
    }
    }
    }
    }
  • "Add new question" button:

    At the very bottom of the list, users can also add a new question. When adding one, it's type will be text by default.

    SurveyEntry.kt
    Button(onClick = {
    questions.add(SurveyQuestionUI(label = "", type = QuestionType.TEXTE))
    }) {
    Text("Ajouter une nouvelle question")
    }
  • "Save questionnaire configuration" button

    When the user has finished editing, they can save the entire questionnaire locally, in a JSON file via the function saveSurvey defined in SurveyStorage.kt.
    As soon as the questionnaire is saved, the user is redirected back to the home page.

    SurveyEntry.kt
    Button(
    onClick = {
    val success = SurveyStorage.saveSurvey(context, questions.map { it.toData() })
    if (success) {
    val timestamp = System.currentTimeMillis()
    context.getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)
    .edit()
    .putLong("lastSurveyModification", timestamp)
    .apply()
    Toast.makeText(context, "Questionnaire enregistré localement", Toast.LENGTH_SHORT).show()

    } else {
    // error while saving questions
    ...
    }
    navController.navigate("home")
    },
    ...
    ) {
    Text("Enregistrer le questionnaire", fontSize = 18.sp)
    }