Search code examples
phplaravellaravel-livewire

how to get result from dynamic questionary in Laravel/Livewire


i've been building a dynamic qiestion project, that should give certain questions and answers depending on user's answers(yes or no). Here's code that gives question from table and gives to user. And i wrote it in Livewire

Question controller

 public $currentQuestion = 1;
  public $question;

  public function render()
    {
        $this->question = $this->getQuestionId($this->currentQuestion);
        return view('livewire.question');
    }

 public function answer($answer)
    {
        if ($answer == 1) {
            $this->currentQuestion = $this->nextYesQuestion($this->currentQuestion);
        } elseif ($answer == 0) {
            $this->currentQuestion = $this->nextNoQuestion($this->currentQuestion);
        }
    }

 private function getQuestionId($questionNumber)
    {
        $questions = [
            1 => 'Question 1: ' . Query::where("id", "1")->pluck('question')->implode(""),
            2 => 'Question 2: ' . Query::where("id", "2")->pluck('question')->implode(""),
            3 => 'Question 3: ' . Query::where("id", "3")->pluck('question')->implode(""),
            4 => 'Question 4: ' . Query::where("id", "4")->pluck('question')->implode(""),
            5 => 'Question 5: ' . Query::where("id", "5")->pluck('question')->implode(""),
            6 => 'Question 6: ' . Query::where("id", "5")->pluck('question')->implode(""),
            7 => 'Question 7: ' . Query::where("id", "6")->pluck('question')->implode(""),
        ];

        return $questions[$questionNumber] ?? null;
    }

   private function nextYesQuestion($questionNumber)
    {
        $nextQuestion = [
            1 => 2,
            2 => 4,
            3 => 6,
        ];

        return $nextQuestion[$questionNumber] ?? null;
    }

  private function nextNoQuestion($questionNumber)
    {
        $nextQuestion = [
            1 => 3,
            2 => 5,
            3 => 7,
        ];

        return $nextQuestion[$questionNumber] ?? null;
    }

  public function refresh()
    {
        $this->currentQuestion = 1;
        $this->result = null;
    }

 public function previousQuestion()
    {
        unset($this->answeredQuestions[$this->currentQuestion]);
        $this->currentQuestion = $this->getPreviousQuestion($this->currentQuestion);
    }

    private function getPreviousQuestion($questionNumber)
    {
        $previousQuestion = null;
        foreach (array_reverse($this->answeredQuestions, true) as $q => $answer) {
            if ($q < $questionNumber) {
                $previousQuestion = $q;
                break;
            }
        }
        return $previousQuestion ?? 1;
    }

Question blade file

<div class="gap-6 lg:gap-8">
    <!-- 1 question -->
    <div
        class="scale-100 p-6 bg-white dark:bg-gray-800/50 dark:bg-gradient-to-bl from-gray-700/50 via-transparent dark:ring-1 dark:ring-inset dark:ring-white/5 rounded-lg shadow-2xl shadow-gray-500/20 dark:shadow-none flex motion-safe:hover:scale-[1.01] transition-all duration-250 focus:outline focus:outline-2 focus:outline-red-500">
        <div>
            <div class="h-16 w-16 bg-red-50 dark:bg-red-800/20 flex items-center justify-center rounded-full">
                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
                     class="w-7 h-7 stroke-red-500">
                    <path stroke-linecap="round" stroke-linejoin="round"
                          d="M6.115 5.19l.319 1.913A6 6 0 008.11 10.36L9.75 12l-.387.775c-.217.433-.132.956.21 1.298l1.348 1.348c.21.21.329.497.329.795v1.089c0 .426.24.815.622 1.006l.153.076c.433.217.956.132 1.298-.21l.723-.723a8.7 8.7 0 002.288-4.042 1.087 1.087 0 00-.358-1.099l-1.33-1.108c-.251-.21-.582-.299-.905-.245l-1.17.195a1.125 1.125 0 01-.98-.314l-.295-.295a1.125 1.125 0 010-1.591l.13-.132a1.125 1.125 0 011.3-.21l.603.302a.809.809 0 001.086-1.086L14.25 7.5l1.256-.837a4.5 4.5 0 001.528-1.732l.146-.292M6.115 5.19A9 9 0 1017.18 4.64M6.115 5.19A8.965 8.965 0 0112 3c1.929 0 3.716.607 5.18 1.64"/>
                </svg>
            </div>

            <h2 class="mt-6 text-xl font-semibold text-gray-900 dark:text-white">Question </h2>

            <p class="mt-4 text-gray-500 dark:text-gray-400 text-sm leading-relaxed">
                {{ $question }}
            </p>
            <button wire:click.prevent="answer(1)"
                    class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full">
                Yes
            </button>
            <button wire:click.prevent="answer(0)"
                    class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full">
                No
            </button>
            <button wire:click.prevent="refresh"
                    class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-full">
                Refresh
            </button>
        </div>
    </div>
    
</div>

So the code so far works fine, it give accoring questions dependin on user's answers. But the feature i want to add is result - i coulnt do that. The idea is, for example, user chooses "No" to 7th question and it should pop up result saying "7th question No result", if user chooses yes, it should say "7th question yes question". so how can i do that? Consider that there are many results, and if you could show me around 3-4 results of how can i do that, i would be pleased.


Solution

  • So, i've answer by myself, but i think still it needs some changes, cuz for my it looks like it wokrs slow, so pls if you have any suggestion write it in comments.

    Solution: we need to create 2 arrays and 2 functions for that

     public $results = [3 => 0, 6 => 1]; //this array for checking yes or no answer from user
    
    public $answers = [3 => "Result for question 3", 6 => "Result for question 6"]; //this array is for answers
    

    so now we can add 2 new functions to our backend

     public function getKey($questionId)
     {
        return $this->results[$questionId];
     }
    
    public function getAnswer($question)
     {
        return $this->answers[$question];
     }
    

    and some new lines to answer function

     public function answer($answer)
    {
        if (Arr::exists($this->results, $this->currentQuestion)) {
            if ($answer == $this->getKey($this->currentQuestion)) {
                $this->result = $this->getAnswer($this->currentQuestion);
            }
        }
    
        if ($answer == 1) {
            $this->currentQuestion = $this->nextYesQuestion($this->currentQuestion);
        } elseif ($answer == 0) {
            $this->currentQuestion = $this->nextNoQuestion($this->currentQuestion);
        }
    }