Обработка нескольких ответов на викторины в приложении MERN

#javascript #reactjs #mongoose #mern

Вопрос:

Я создаю приложение MERN, которое выполняет операции CRUD с базой данных вопросов викторины.

Интерфейс не будет иметь функций для записи ответов на эти вопросы, он предназначен исключительно для просмотра, редактирования и удаления вопросов.

Вопросы бывают трех типов — один ответ, несколько ответов (два или более «варианта ответа» являются правильными) и множественный выбор (один из нескольких «вариантов ответа» является правильным).

Схема вопроса выглядит так:

 const optionSchema = new mongoose.Schema({
  optionText: { type: String, required: true },
  isAnswer: { type: Boolean, required: true },
});

const locationSchema = new mongoose.Schema({
  locationName: { type: String, required: true },
});

const questionSchema = mongoose.Schema(
  {
    content: {
      type: String,
      required: true,
      maxLength: 1000,
    },
    answerOptions: [optionSchema],
    author: {
      type: mongoose.Schema.Types.ObjectId,
      required: true,
      ref: "User",
    },
    locations: [locationSchema],
    category: {
      type: String,
      required: true,
    },
    questionType: {
      type: String,
    },
    isFlagged: {
      type: Boolean,
      default: false,
    },
    flagReason: {
      type: String,
    },
    isPublic: {
      type: Boolean,
      default: true,
    },
    checkDate: {
      type: Date,
    },
    qualityVoteTotal: {
      type: Number,
    },
    difficultyVoteTotal: {
      type: Number,
    },
    isDeprecated: {
      type: Boolean,
    },
  },
  {
    timestamps: true,
  }
);

const Question = mongoose.model("Question", questionSchema);
 

У меня есть экран интерфейса, на котором отображается список вопросов из базы данных. Они отправляются из магазина redux с использованием:

 function QuestionBrowser({ history }) {
  const dispatch = useDispatch();

  const questionList = useSelector((state) => state.questionList);
  const { loading, error, questions } = questionList;
 

И я пытаюсь отобразить каждый вопрос с его ответами и некоторой другой информацией в аккордеоне начальной загрузки:

 return (
    <MainScreen title={`Have a browse ${userInfo amp;amp; userInfo.name}..`}>
      <Link to="/createquestion">
        <Button style={{ marginLeft: 10, marginBottom: 6 }} size="lg">
          Create new question
        </Button>
      </Link>
      {error amp;amp; <ErrorMessage variant="danger">{error}</ErrorMessage>}
      {/* {errorDelete amp;amp; (
        <ErrorMessage variant="danger">{errorDelete}</ErrorMessage>
      )} */}
      {loading amp;amp; <Loading />}
      {/* {loadingDelete amp;amp; <Loading />} */}
      {questions amp;amp;
        questions.reverse().map((question) => (
          <Accordion>
            <Card style={{ margin: 10 }} key={question._id}>
              <Card.Header style={{ display: "flex" }}>
                <span
                  // onClick={() => ModelShow(question)}
                  style={{
                    color: "black",
                    textDecoration: "none",
                    flex: 1,
                    cursor: "pointer",
                    alignSelf: "center",
                    fontSize: 18,
                  }}
                >
                  <Accordion.Toggle as={Card.Text} variant="link" eventKey="0">
                    {question.content}
                  </Accordion.Toggle>
                </span>

                <div>
                  <Button href={`/question/${question._id}`}>Edit</Button>
                  <Button
                    variant="danger"
                    className="mx-2"
                    // onClick={() => deleteHandler(question._id)}
                  >
                    Delete
                  </Button>
                </div>
              </Card.Header>
              <Accordion.Collapse eventKey="0">
                <Card.Body>
                  <h4>
                      Category - {question.category}
                  </h4>

                  <blockquote className="blockquote mb-0">
                    {/* Hard coding displays the answer options... */}
                    {/* {question.answerOptions[0].optionText}
                    {question.answerOptions[1].optionText}
                    {question.answerOptions[2].optionText} */}

                    <footer className="blockquote-footer">
                      Created on{" "}
                      <cite title="Source Title">
                        {question.createdAt.substring(0, 10)}
                      </cite>
                    </footer>
                  </blockquote>
                </Card.Body>
              </Accordion.Collapse>
            </Card>
          </Accordion>
        ))}
    </MainScreen>
  );
 

An example question, returned from the database currently looks like:

 {
        "_id": "61464a067b9b883824daeeeb",
        "content": "Where was E.T. trying to phone in a class 1980s movie?",
        "answerOptions": [
            {
                "optionText": "The International Space Station",
                "isAnswer": false,
                "_id": "6146530f7b22de77fb129e4f"
            },
            {
                "optionText": "Home",
                "isAnswer": true,
                "_id": "6146530f7b22de77fb129e50"
            },
            {
                "optionText": "The Chinese takeaway",
                "isAnswer": false,
                "_id": "6146530f7b22de77fb129e51"
            }
        ],
        "author": "614647baff6a022c04218203",
        "locations": [],
        "category": "Entertainment",
        "questionType": "Multiple Choice",
        "isFlagged": false,
        "flagReason": "",
        "isPublic": true,
        "checkDate": null,
        "qualityVoteTotal": 0,
        "difficultyVoteTotal": 0,
        "isDeprecated": false,
        "createdAt": "2021-09-18T20:20:22.298Z",
        "updatedAt": "2021-09-18T20:58:55.075Z",
        "__v": 1
    }
 

I’m able to output the answer options by hardcoding the following into my QuestionBrowser’s return, by using the following:

 <blockquote className="blockquote mb-0">
  {question.answerOptions[0].optionText}
  {question.answerOptions[1].optionText}
  {question.answerOptions[2].optionText}
 

But given the number of answerOptions in each question document can vary (only one answerOption for a single answer question, up to six options for multiple answer and multiple choice questions), this isn’t practical.

For each question I’m trying to find a way to:

  • Display the question.content in the accordion toggle (this is working at the moment)
  • Iterate through the answerOptions array, and for each option, output the text in the accordion body, making the text bold (for example) if the isAnswer property is true.