Как создать прогресс-бар, который будет меняться в зависимости от разных ответов на вопросы в опроснике при использовании Alpine.js?

Как можно настроить прогресс-бар для ваших вопросов с возможностью каждому объекту присваивать 10% и достижения 100% при всем ответах? Учитывая структуру, где ответы считаются пустыми объектами с choices: [], nextQuestions: [].
  • 13 июня 2024 г. 11:21
Ответы на вопрос 2
Для создания прогресс-бара, меняющегося в зависимости от ответов на вопросы опросника при использовании Alpine.js, можно следующим образом:

1. Сначала создадим структуру данных для опросника. Например, вот как может выглядеть структура объекта с вопросами и ответами:

```javascript
{
  questions: [
    {
      questionText: "Ваш любимый цвет?",
      choices: ["Синий", "Зеленый", "Красный"],
      selectedChoice: null
    },
    {
      questionText: "Ваш любимый вид спорта?",
      choices: ["Футбол", "Баскетбол", "Теннис"],
      selectedChoice: null
    },
    // Добавьте другие вопросы здесь
  ],
  progress: 0
}
```

2. Далее создадим прогресс-бар в HTML, который будет отображать прогресс опроса:

```html
<div x-data="surveyProgress()">
  <div>
    <span x-text="'Progress: ' + progress + '%'"></span>
    <div>
      <div class="bg-gray-200 w-full h-8">
        <div class="bg-blue-500" x-bind:style="'width: ' + progress + '%'"></div>
      </div>
    </div>
  </div>

  <template x-for="(question, index) in questions" :key="index">
    <div>
      <h3 x-text="question.questionText"></h3>
      <template x-for="(choice, choiceIndex) in question.choices" :key="choiceIndex">
        <input type="radio" x-model="question.selectedChoice" :value="choice">
        <label x-text="choice"></label>
      </template>
    </div>
  </template>
</div>
```

3. Далее добавим Alpine.js скрипт, который будет управлять прогресс-баром и обработкой ответов на вопросы:

```javascript
function surveyProgress() {
  return {
    questions: [
      // Вставьте структуру объекта с вопросами и ответами из шага 1
    ],
    get progress() {
      let totalQuestions = this.questions.length;
      let answeredQuestions = this.questions.filter(question => question.selectedChoice !== null).length;
      return Math.round((answeredQuestions / totalQuestions) * 100);
    }
  };
}
```

Теперь прогресс-бар будет автоматически обновляться в зависимости от того, сколько вопросов уже отвечено. Каждый ответ на вопрос будет увеличивать прогресс на 10%.
Добавить счётчик полученных ответов, делать ему +/- 1 при переходах к следующему/предыдущему вопросу. 

При расчёте прогресса проверять, что текущий вопрос последний (т.е., список возможных следующих вопросов пуст), в зависимости от результата проверки возвращать чего там вам надо - сразу 100 или умножаете счётчик ответов на 10 (кстати, уверены, что больше девяти вопросов задано не будет?).

UPD. Как избавиться от этой ерунды с умножением на 10 - давайте будем вычислять максимальное количество вопросов, которые ещё могут быть заданы. Тогда текущий прогресс будет выражаться отношением количества отвеченных вопросов к сумме отвеченных и оставшихся.

А ещё давайте избавимся от поиска вопросов по их id - для этого следующие/предыдущие вопросы надо хранить в виде индексов вместо id, или вместо массива вопросов сделать объект, где ключами будут id.

Как это может выглядеть :

Рекурсия есть:

getMaxQuestionsLeft(question, depth) {
  return Math.max(
    depth,
    ...question.nextQuestions.map(n => {
      return this.getMaxQuestionsLeft(this.questions[n], depth + 1);
    })
  );
},
get progress() {
  const ac = this.answersCount;
  return Math.floor(ac / (ac + this.getMaxQuestionsLeft(this.question, 0)) * 100);
},

Или, рекурсии нет:

get maxQuestionsLeft() {
  let result = 0;

  for (const stack = [ [ this.question, 0 ] ]; stack.length;) {
    const [ q, d ] = stack.pop();
    result = Math.max(result, d);
    stack.push(...q.nextQuestions.map(n => [ this.questions[n], -~d ]));
  }

  return result;
},
get progress() {
  const { answersCount: ac } = this;
  return ac / (ac + this.maxQuestionsLeft) * 100 | 0;
},
Похожие вопросы