diff --git a/app/Http/Controllers/FormController.php b/app/Http/Controllers/FormController.php index dd760f2..5ead730 100644 --- a/app/Http/Controllers/FormController.php +++ b/app/Http/Controllers/FormController.php @@ -1,6 +1,7 @@ questions; -foreach ($questions as $question) { - $question->options = json_decode($question->options, true); -} + { + // Questions are already fetched with their options cast to array due to the casts property + $questions = $form->questions; + foreach ($questions as $question) { + $question->options = json_decode($question->options, true); + } -// Pass the questions to the view -return view('forms.edit', compact('form', 'questions')); -} + // Pass the questions to the view + return view('forms.edit', compact('form', 'questions')); + } @@ -72,15 +74,14 @@ return view('forms.edit', compact('form', 'questions')); public function show(Form $form) { $form->load('questions.responses'); - return view('forms.show', compact('form')); } public function preview($id) -{ - $form = Form::findOrFail($id); - return view('forms.previewForm', compact('form')); -} + { + $form = Form::findOrFail($id); + return view('forms.previewForm', compact('form')); + } public function update(Request $request, Form $form) diff --git a/app/Http/Controllers/ResponseController.php b/app/Http/Controllers/ResponseController.php index 85b0ae2..ab2fe34 100644 --- a/app/Http/Controllers/ResponseController.php +++ b/app/Http/Controllers/ResponseController.php @@ -32,9 +32,28 @@ class ResponseController extends Controller // Get all questions for the form $questions = Question::where('form_id', $form->id)->get()->keyBy('id'); - return view('responses.viewResponse', compact('form', 'responses', 'questions')); + // Aggregate data for statistics + $statistics = []; + foreach ($questions as $question) { + $statistics[$question->id] = [ + 'question_text' => $question->question_text, + 'type' => $question->type, + 'options' => json_decode($question->options), + 'responses' => [] + ]; + + foreach ($responses as $response) { + $decodedAnswers = json_decode($response->answers, true); + if (isset($decodedAnswers[$question->id])) { + $statistics[$question->id]['responses'][] = $decodedAnswers[$question->id]; + } + } + } + + return view('responses.viewResponse', compact('form', 'responses', 'questions', 'statistics')); } + public function viewResponses(Form $form) { // Get all responses for the form, grouped by response_id @@ -43,9 +62,33 @@ public function viewResponses(Form $form) ->get() ->groupBy('response_id'); - return view('responses.viewResponses', compact('form', 'responses')); + // Get all questions for the form + $questions = Question::where('form_id', $form->id)->get()->keyBy('id'); + + // Aggregate data for statistics + $statistics = []; + foreach ($questions as $question) { + $statistics[$question->id] = [ + 'question_text' => $question->question_text, + 'type' => $question->type, + 'options' => json_decode($question->options, true), + 'responses' => [], + ]; + + foreach ($responses as $responseGroup) { + foreach ($responseGroup as $response) { + $decodedAnswers = json_decode($response->answers, true); + if (isset($decodedAnswers[$question->id])) { + $statistics[$question->id]['responses'][] = $decodedAnswers[$question->id]; + } + } + } + } + + return view('responses.viewResponses', compact('form', 'responses', 'statistics')); } + public function showForm(Form $form) { $questions = $form->questions; diff --git a/public/js/statistics.js b/public/js/statistics.js new file mode 100644 index 0000000..901b9b5 --- /dev/null +++ b/public/js/statistics.js @@ -0,0 +1,129 @@ +// statistics.js + +// Function to fetch responses from backend +function fetchResponses() { + return fetch('/api/responses') // Replace with your actual API endpoint + .then(response => response.json()) + .catch(error => console.error('Error fetching responses:', error)); +} + +// Function to process fetched responses data +function processDataForCharts(responses, questions) { + const pieData = {}; + const barData = {}; + + responses.forEach(response => { + const question = questions[response.question_id]; + const decodedAnswers = JSON.parse(response.answers); + + // Process data for pie chart + if (!pieData[question.question_text]) { + pieData[question.question_text] = {}; + } + if (question.type === 'multiple_choice' || question.type === 'checkbox') { + JSON.parse(question.options).forEach(option => { + pieData[question.question_text][option] = (pieData[question.question_text][option] || 0) + + (decodedAnswers.includes(option) ? 1 : 0); + }); + } + + // Process data for bar graph (assuming numerical responses) + if (question.type === 'short_answer' || question.type === 'long_answer') { + if (!barData[question.question_text]) { + barData[question.question_text] = { total: 0, count: 0 }; + } + barData[question.question_text].total += parseFloat(response.answers); + barData[question.question_text].count++; + } + }); + + // Calculate averages for bar graph + Object.keys(barData).forEach(key => { + barData[key].average = barData[key].total / barData[key].count; + }); + + return { pieData, barData }; +} + +// Function to render charts using Chart.js +function renderCharts(pieData, barData) { + // Render Pie Chart + const pieChartCanvas = document.getElementById('pieChart'); + new Chart(pieChartCanvas.getContext('2d'), { + type: 'pie', + data: { + labels: Object.keys(pieData), + datasets: Object.keys(pieData).map(question => ({ + label: question, + data: Object.values(pieData[question]), + backgroundColor: getRandomColors(Object.values(pieData[question]).length), + })), + }, + options: { + responsive: true, + plugins: { + legend: { + position: 'top', + }, + tooltip: { + callbacks: { + label: function(context) { + let label = context.label || ''; + if (context.parsed.y !== null) { + label += ': ' + context.parsed.y; + } + return label; + }, + }, + }, + }, + }, + }); + + // Render Bar Graph + const barGraphCanvas = document.getElementById('barGraph'); + new Chart(barGraphCanvas.getContext('2d'), { + type: 'bar', + data: { + labels: Object.keys(barData), + datasets: [{ + label: 'Average Response', + data: Object.values(barData).map(item => item.average.toFixed(2)), + backgroundColor: getRandomColors(Object.keys(barData).length), + }], + }, + options: { + responsive: true, + scales: { + y: { + beginAtZero: true, + }, + }, + }, + }); +} + +// Function to generate random colors +function getRandomColors(count) { + const colors = []; + for (let i = 0; i < count; i++) { + colors.push(`rgba(${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, 0.2)`); + } + return colors; +} + +// Main function to fetch data and render charts +async function main() { + try { + const responses = await fetchResponses(); + const questions = {!! json_encode($questions) !!}; // This assumes $questions is passed to the Blade view from Laravel + + const { pieData, barData } = processDataForCharts(responses, questions); + renderCharts(pieData, barData); + } catch (error) { + console.error('Error processing or rendering charts:', error); + } +} + +// Run main function on page load +window.addEventListener('DOMContentLoaded', main); diff --git a/resources/views/forms/edit.blade.php b/resources/views/forms/edit.blade.php index a3fb83e..59e3489 100644 --- a/resources/views/forms/edit.blade.php +++ b/resources/views/forms/edit.blade.php @@ -10,9 +10,9 @@ - - + -