Added sliding add button in edit page, Added statistics in responses page
This commit is contained in:
parent
d203dcaaba
commit
00f5ec6cf9
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Models\Form;
|
use App\Models\Form;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
@ -9,6 +10,7 @@ use App\Models\Response;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Facades\Session;
|
use Illuminate\Support\Facades\Session;
|
||||||
|
|
||||||
class FormController extends Controller
|
class FormController extends Controller
|
||||||
{
|
{
|
||||||
public function index()
|
public function index()
|
||||||
|
@ -24,16 +26,16 @@ class FormController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit(Form $form)
|
public function edit(Form $form)
|
||||||
{
|
{
|
||||||
// Questions are already fetched with their options cast to array due to the casts property
|
// Questions are already fetched with their options cast to array due to the casts property
|
||||||
$questions = $form->questions;
|
$questions = $form->questions;
|
||||||
foreach ($questions as $question) {
|
foreach ($questions as $question) {
|
||||||
$question->options = json_decode($question->options, true);
|
$question->options = json_decode($question->options, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass the questions to the view
|
// Pass the questions to the view
|
||||||
return view('forms.edit', compact('form', 'questions'));
|
return view('forms.edit', compact('form', 'questions'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,15 +74,14 @@ return view('forms.edit', compact('form', 'questions'));
|
||||||
public function show(Form $form)
|
public function show(Form $form)
|
||||||
{
|
{
|
||||||
$form->load('questions.responses');
|
$form->load('questions.responses');
|
||||||
|
|
||||||
return view('forms.show', compact('form'));
|
return view('forms.show', compact('form'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function preview($id)
|
public function preview($id)
|
||||||
{
|
{
|
||||||
$form = Form::findOrFail($id);
|
$form = Form::findOrFail($id);
|
||||||
return view('forms.previewForm', compact('form'));
|
return view('forms.previewForm', compact('form'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function update(Request $request, Form $form)
|
public function update(Request $request, Form $form)
|
||||||
|
|
|
@ -32,9 +32,28 @@ class ResponseController extends Controller
|
||||||
// Get all questions for the form
|
// Get all questions for the form
|
||||||
$questions = Question::where('form_id', $form->id)->get()->keyBy('id');
|
$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)
|
public function viewResponses(Form $form)
|
||||||
{
|
{
|
||||||
// Get all responses for the form, grouped by response_id
|
// Get all responses for the form, grouped by response_id
|
||||||
|
@ -43,9 +62,33 @@ public function viewResponses(Form $form)
|
||||||
->get()
|
->get()
|
||||||
->groupBy('response_id');
|
->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)
|
public function showForm(Form $form)
|
||||||
{
|
{
|
||||||
$questions = $form->questions;
|
$questions = $form->questions;
|
||||||
|
|
|
@ -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);
|
|
@ -10,9 +10,9 @@
|
||||||
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
|
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||||
|
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap"
|
||||||
|
rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
.shadow-custom {
|
.shadow-custom {
|
||||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||||
|
@ -23,8 +23,8 @@
|
||||||
<body class="bg-light">
|
<body class="bg-light">
|
||||||
<nav class="bg-white p-1 shadow-md">
|
<nav class="bg-white p-1 shadow-md">
|
||||||
<div class="container mx-auto flex justify-between items-center">
|
<div class="container mx-auto flex justify-between items-center">
|
||||||
<span style="color: rgb(103,58,183)" class="text-3xl font-bold font-sans"><a href="{{ url('/') }}" style="color: rgb(103,58,183)"
|
<span style="color: rgb(103,58,183)" class="text-3xl font-bold font-sans"><a href="{{ url('/') }}"
|
||||||
class="text-3xl font-bold font-sans">LaraForms</a> - Edit</span>
|
style="color: rgb(103,58,183)" class="text-3xl font-bold font-sans">LaraForms</a> - Edit</span>
|
||||||
<div class="relative dropdown">
|
<div class="relative dropdown">
|
||||||
<button id="profileMenuButton" class="flex items-center focus:outline-none">
|
<button id="profileMenuButton" class="flex items-center focus:outline-none">
|
||||||
<img src="{{ asset('images/user.png') }}" alt="Profile"
|
<img src="{{ asset('images/user.png') }}" alt="Profile"
|
||||||
|
@ -34,9 +34,8 @@
|
||||||
class="dropdown-menu hidden absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg py-2">
|
class="dropdown-menu hidden absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg py-2">
|
||||||
<form method="POST" action="{{ route('logout') }}">
|
<form method="POST" action="{{ route('logout') }}">
|
||||||
@csrf
|
@csrf
|
||||||
<button type="submit" class="block px-4 py-2 text-gray-700 hover:bg-gray-200 w-full text-left">
|
<button type="submit"
|
||||||
Logout
|
class="block px-4 py-2 text-gray-700 hover:bg-gray-200 w-full text-left">Logout</button>
|
||||||
</button>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -44,45 +43,68 @@
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div style="max-width: 700px" class="container">
|
<div style="max-width: 700px" class="container">
|
||||||
<form id="edit-form" method="POST" action="{{ route('forms.update', $form) }}" class="bg-white p-4 rounded shadow-sm">
|
<form id="edit-form" method="POST" action="{{ route('forms.update', $form) }}"
|
||||||
|
class="bg-white p-4 rounded shadow-sm">
|
||||||
@csrf
|
@csrf
|
||||||
@method('PUT')
|
@method('PUT')
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="text" id="form-title" name="title" class="form-control form-control-lg text-black" placeholder="Untitled Form" value="{{ $form->title }}" />
|
<input type="text" id="form-title" name="title" class="form-control form-control-lg text-black"
|
||||||
|
placeholder="Untitled Form" value="{{ $form->title }}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="text" name="description" id="form-description" class="form-control form-control-sm text-black" placeholder="Form Description" value="{{ $form->description }}" />
|
<input type="text" name="description" id="form-description"
|
||||||
|
class="form-control form-control-sm text-black" placeholder="Form Description"
|
||||||
|
value="{{ $form->description }}" />
|
||||||
</div>
|
</div>
|
||||||
<div id="questions-section">
|
<div id="questions-section">
|
||||||
@foreach ($questions as $index => $question)
|
@foreach ($questions as $index => $question)
|
||||||
<div class="question mb-4 p-3 border rounded bg-light" data-index="{{ $index }}">
|
<div class="question mb-4 p-3 border rounded bg-light" data-index="{{ $index }}">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
{{-- <label for="question-type-{{ $index }}">Question Type</label> --}}
|
<select class="form-control question-type" id="question-type-{{ $index }}"
|
||||||
<select class="form-control question-type" id="question-type-{{ $index }}" name="questions[{{ $index }}][type]">
|
name="questions[{{ $index }}][type]">
|
||||||
<option value="multiple_choice" {{ $question->type === 'multiple_choice' ? 'selected' : '' }}>Multiple Choice</option>
|
<option value="multiple_choice"
|
||||||
<option value="checkbox" {{ $question->type === 'checkbox' ? 'selected' : '' }}>Checkbox</option>
|
{{ $question->type === 'multiple_choice' ? 'selected' : '' }}>Multiple Choice
|
||||||
<option value="dropdown" {{ $question->type === 'dropdown' ? 'selected' : '' }}>Dropdown</option>
|
</option>
|
||||||
|
<option value="checkbox" {{ $question->type === 'checkbox' ? 'selected' : '' }}>
|
||||||
|
Checkbox</option>
|
||||||
|
<option value="dropdown" {{ $question->type === 'dropdown' ? 'selected' : '' }}>
|
||||||
|
Dropdown</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
{{-- <label for="question-text-{{ $index }}">Question Text</label> --}}
|
<input type="text" id="question-text-{{ $index }}"
|
||||||
<input type="text" id="question-text-{{ $index }}" name="questions[{{ $index }}][text]" class="form-control question-input" value="{{ $question->question_text }}" required>
|
name="questions[{{ $index }}][text]" class="form-control question-input"
|
||||||
|
value="{{ $question->question_text }}" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group options-container">
|
<div class="form-group options-container">
|
||||||
<label>Options</label>
|
<label>Options</label>
|
||||||
@if(is_array($question->options))
|
@if (is_array($question->options))
|
||||||
@foreach ($question->options as $optionIndex => $option)
|
@foreach ($question->options as $optionIndex => $option)
|
||||||
<div class="option d-flex align-items-center mb-2">
|
<div class="option d-flex align-items-center mb-2">
|
||||||
<input type="text" name="questions[{{ $index }}][options][{{ $optionIndex }}]" class="form-control option-input" value="{{ $option }}">
|
<input type="text"
|
||||||
<span class="delete-option ml-2 text-danger" onclick="deleteOption(this)" style="cursor: pointer;">✕</span>
|
name="questions[{{ $index }}][options][{{ $optionIndex }}]"
|
||||||
|
class="form-control option-input" value="{{ $option }}">
|
||||||
|
<span class="delete-option ml-2 text-danger" onclick="deleteOption(this)"
|
||||||
|
style="cursor: pointer;">✕</span>
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
@endif
|
@endif
|
||||||
<button type="button" class="btn btn-secondary" onclick="addOption(this)">Add Option</button>
|
<button type="button" class="btn btn-secondary" onclick="addOption(this)">Add
|
||||||
|
Option</button>
|
||||||
|
<button class="btn btn-md" id="moveUpButton" onclick="deleteQuestion(this);">
|
||||||
|
<img src="{{ asset('images/bin.png') }}" alt="" width="20px"
|
||||||
|
height="20px" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn btn-danger btn-sm" onclick="deleteQuestion(this)">Delete Question</button>
|
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
<div class="sidebar">
|
||||||
|
<div id="moveableDiv">
|
||||||
|
<button class="btn btn-light shadow-sm" type="button" onclick="addNewQuestion();">
|
||||||
|
<img src="{{ asset('images/add.png') }}" alt="ADD" width="20px" height="20px" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn btn-primary mb-4" onclick="addNewQuestion()">Add New Question</button>
|
<button type="button" class="btn btn-primary mb-4" onclick="addNewQuestion()">Add New Question</button>
|
||||||
<button type="submit" class="btn btn-success mb-4">Save</button>
|
<button type="submit" class="btn btn-success mb-4">Save</button>
|
||||||
|
@ -105,10 +127,12 @@
|
||||||
`;
|
`;
|
||||||
|
|
||||||
optionsContainer.append(optionHtml);
|
optionsContainer.append(optionHtml);
|
||||||
|
updateAddButtonPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteOption(button) {
|
function deleteOption(button) {
|
||||||
$(button).closest('.option').remove();
|
$(button).closest('.option').remove();
|
||||||
|
updateAddButtonPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
function addNewQuestion() {
|
function addNewQuestion() {
|
||||||
|
@ -118,7 +142,6 @@
|
||||||
const questionHtml = `
|
const questionHtml = `
|
||||||
<div class="question mb-4 p-3 border rounded bg-light" data-index="${questionIndex}">
|
<div class="question mb-4 p-3 border rounded bg-light" data-index="${questionIndex}">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="question-type-${questionIndex}">Question Type</label>
|
|
||||||
<select class="form-control question-type" id="question-type-${questionIndex}" name="questions[${questionIndex}][type]">
|
<select class="form-control question-type" id="question-type-${questionIndex}" name="questions[${questionIndex}][type]">
|
||||||
<option value="multiple_choice">Multiple Choice</option>
|
<option value="multiple_choice">Multiple Choice</option>
|
||||||
<option value="checkbox">Checkbox</option>
|
<option value="checkbox">Checkbox</option>
|
||||||
|
@ -126,46 +149,64 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="question-text-${questionIndex}">Question Text</label>
|
|
||||||
<input type="text" id="question-text-${questionIndex}" name="questions[${questionIndex}][text]" class="form-control question-input" placeholder="Type your question here" required>
|
<input type="text" id="question-text-${questionIndex}" name="questions[${questionIndex}][text]" class="form-control question-input" placeholder="Type your question here" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group options-container">
|
<div class="form-group options-container">
|
||||||
<label>Options</label>
|
<label>Options</label>
|
||||||
<button type="button" class="btn btn-secondary" onclick="addOption(this)">Add Option</button>
|
<button type="button" class="btn btn-secondary" onclick="addOption(this)">Add Option</button>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn btn-danger btn-sm" onclick="deleteQuestion(this)">Delete Question</button>
|
<button class="btn btn-md" id="moveUpButton" onclick="deleteQuestion(this);">
|
||||||
|
<img src="{{ asset('images/bin.png') }}" alt="" width="20px" height="20px" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
questionsSection.append(questionHtml);
|
questionsSection.append(questionHtml);
|
||||||
|
updateAddButtonPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteQuestion(button) {
|
function deleteQuestion(button) {
|
||||||
$(button).closest('.question').remove();
|
$(button).closest('.question').remove();
|
||||||
|
updateAddButtonPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateAddButtonPosition() {
|
||||||
|
const questions = document.querySelectorAll("#questions-section .question");
|
||||||
|
const sidebar = document.getElementById("moveableDiv");
|
||||||
|
|
||||||
|
if (questions.length > 0) {
|
||||||
|
const lastQuestion = questions[questions.length - 1];
|
||||||
|
const offsetTop = lastQuestion.offsetTop;
|
||||||
|
const sidebarHeight = sidebar.offsetHeight;
|
||||||
|
const containerHeight = document.getElementById("questions-section").offsetHeight;
|
||||||
|
|
||||||
|
const newPosition = offsetTop + lastQuestion.offsetHeight;
|
||||||
|
if (newPosition + sidebarHeight <= containerHeight) {
|
||||||
|
sidebar.style.transform = `translateY(${newPosition}px)`;
|
||||||
|
console.log(`Moving sidebar to: ${newPosition}px`);
|
||||||
|
} else {
|
||||||
|
sidebar.style.transform = `translateY(${containerHeight - sidebarHeight}px)`;
|
||||||
|
console.log(`Moving sidebar to bottom of container`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sidebar.style.transform = `translateY(0px)`;
|
||||||
|
console.log("No questions, moving sidebar to top");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('#edit-form').on('submit', function(e) {
|
$('#profileMenuButton').on('click', function() {
|
||||||
e.preventDefault();
|
$('#profileMenu').toggleClass('hidden');
|
||||||
const formId = '{{ $form->id }}';
|
});
|
||||||
$.ajax({
|
|
||||||
url: '/forms/' + formId,
|
$(document).on('click', function(e) {
|
||||||
type: 'PUT',
|
if (!$(e.target).closest('#profileMenuButton').length && !$(e.target).closest(
|
||||||
headers: {
|
'#profileMenu').length) {
|
||||||
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
|
$('#profileMenu').addClass('hidden');
|
||||||
},
|
|
||||||
data: $(this).serialize(),
|
|
||||||
success: function(response) {
|
|
||||||
console.log('Form updated successfully.');
|
|
||||||
window.location.href = '/forms/' + formId;
|
|
||||||
},
|
|
||||||
error: function(xhr) {
|
|
||||||
console.error('Error updating form:', xhr.responseText);
|
|
||||||
alert('Form Updated!');
|
|
||||||
window.location.href = '/forms';
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
updateAddButtonPosition();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<!-- CSRF Token -->
|
<!-- CSRF Token -->
|
||||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||||
|
|
||||||
<title>{{ config('app.name', 'Laravel') }}</title>
|
<title>{{ config('app.name', 'LaraForms') }}</title>
|
||||||
|
|
||||||
<!-- Fonts -->
|
<!-- Fonts -->
|
||||||
<link rel="dns-prefetch" href="//fonts.bunny.net">
|
<link rel="dns-prefetch" href="//fonts.bunny.net">
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
<nav class="navbar navbar-expand-md navbar-light shadow-md px-4 py-3 flex justify-between items-center" style="background-color: rgb(103,58,183)">
|
<nav class="navbar navbar-expand-md navbar-light shadow-md px-4 py-3 flex justify-between items-center" style="background-color: rgb(103,58,183)">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<a class="navbar-brand text-white" href="{{ url('/') }}">
|
<a class="navbar-brand text-white" href="{{ url('/') }}">
|
||||||
{{ config('app.name', 'Laravel') }}
|
{{ config('app.name', 'LaraForms') }}
|
||||||
</a>
|
</a>
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
@ -11,80 +10,8 @@
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
{{-- <script src="https://cdn.tailwindcss.com"></script> --}}
|
|
||||||
<style>
|
|
||||||
.box {
|
|
||||||
background-color: #fff;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-list {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
list-style: none;
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-list::before {
|
|
||||||
content: "";
|
|
||||||
display: block;
|
|
||||||
height: 2px;
|
|
||||||
width: 50%;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: #aaa;
|
|
||||||
transition: 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-item {
|
|
||||||
flex: 1;
|
|
||||||
text-align: center;
|
|
||||||
transition: 0.3s;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-toggle {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-content {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-toggle:nth-child(1):checked ~ .tab-list .tab-item:nth-child(1),
|
|
||||||
.tab-toggle:nth-child(2):checked ~ .tab-list .tab-item:nth-child(2){
|
|
||||||
opacity: 5;
|
|
||||||
color: #731273;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-toggle:nth-child(2):checked ~ .tab-list::before {
|
|
||||||
transform: translateX(100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-toggle:nth-child(1):checked ~ .tab-container .tab-content:nth-child(1),
|
|
||||||
.tab-toggle:nth-child(2):checked ~ .tab-container .tab-content:nth-child(2) {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.tab-trigger {
|
|
||||||
display: block;
|
|
||||||
padding: 0;
|
|
||||||
color: #731273;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-trigger:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-container {
|
|
||||||
padding: 15px 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</style>
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="font-open-sans">
|
<body class="font-open-sans">
|
||||||
<header class="bg-white shadow-md py-1">
|
<header class="bg-white shadow-md py-1">
|
||||||
<div class="container d-flex justify-content-start align-items-center">
|
<div class="container d-flex justify-content-start align-items-center">
|
||||||
|
@ -93,21 +20,6 @@
|
||||||
</a>
|
</a>
|
||||||
<h2 style="color: rgb(103,58,183)" class="ml-3">{{ $form->title }} - Response Detail</h2>
|
<h2 style="color: rgb(103,58,183)" class="ml-3">{{ $form->title }} - Response Detail</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="container">
|
|
||||||
<div class="box">
|
|
||||||
<input type="radio" class="tab-toggle" name="tab-toggle" id="tab1" checked />
|
|
||||||
<input type="radio" class="tab-toggle" name="tab-toggle" id="tab2" />
|
|
||||||
|
|
||||||
<ul class="tab-list">
|
|
||||||
<li class="tab-item">
|
|
||||||
<label class="tab-trigger" for="tab1"><b>Responses</b></label>
|
|
||||||
</li>
|
|
||||||
<li class="tab-item">
|
|
||||||
<label class="tab-trigger" for="tab2"><b>Statistics</b></label>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div mt-4">
|
<div mt-4">
|
||||||
|
@ -122,13 +34,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="questions_section">
|
<div class="section" id="questions_section">
|
||||||
|
|
||||||
@foreach ($responses as $response)
|
@foreach ($responses as $response)
|
||||||
@php
|
@php
|
||||||
$question = $questions[$response->question_id] ?? null;
|
$question = $questions[$response->question_id] ?? null;
|
||||||
$decodedAnswers = json_decode($response->answers, true);
|
$decodedAnswers = json_decode($response->answers, true);
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
@if ($question)
|
@if ($question)
|
||||||
<div class="question mb-4 p-3 border rounded bg-white">
|
<div class="question mb-4 p-3 border rounded bg-white">
|
||||||
<h3 class="text-lg font-medium mb-2">{{ $question->question_text }}</h3>
|
<h3 class="text-lg font-medium mb-2">{{ $question->question_text }}</h3>
|
||||||
|
@ -159,18 +69,6 @@
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Statistics Section -->
|
|
||||||
<div style="max-width: 800px" class="container statistics bg-light p-4 rounded shadow-sm" id="statistics_section" style="display: none;">
|
|
||||||
<h3>Statistics</h3>
|
|
||||||
<!-- Pie Chart -->
|
|
||||||
<div style="max-width: 300px" class="mb-6 container">
|
|
||||||
<canvas id="pieChart"></canvas>
|
|
||||||
</div>
|
|
||||||
<!-- Bar Graph -->
|
|
||||||
<div style="max-width: 300px" class="container">
|
|
||||||
<canvas id="barGraph"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="btnsub text-center mt-4">
|
<div class="btnsub text-center mt-4">
|
||||||
|
@ -178,80 +76,6 @@
|
||||||
<a href="{{ route('forms.index') }}" class="btn btn-secondary">Return to Forms</a>
|
<a href="{{ route('forms.index') }}" class="btn btn-secondary">Return to Forms</a>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
|
||||||
const tab1 = document.getElementById('tab1');
|
|
||||||
const tab2 = document.getElementById('tab2');
|
|
||||||
const responsesSection = document.getElementById('responses_section');
|
|
||||||
const statisticsSection = document.getElementById('statistics_section');
|
|
||||||
|
|
||||||
tab1.addEventListener('change', function() {
|
|
||||||
if (tab1.checked) {
|
|
||||||
responsesSection.style.display = 'block';
|
|
||||||
statisticsSection.style.display = 'none';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
tab2.addEventListener('change', function() {
|
|
||||||
if (tab2.checked) {
|
|
||||||
responsesSection.style.display = 'none';
|
|
||||||
statisticsSection.style.display = 'block';
|
|
||||||
renderCharts(); // Render charts when switching to statistics tab
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set the initial state
|
|
||||||
if (tab1.checked) {
|
|
||||||
responsesSection.style.display = 'block';
|
|
||||||
statisticsSection.style.display = 'none';
|
|
||||||
} else if (tab2.checked) {
|
|
||||||
responsesSection.style.display = 'none';
|
|
||||||
statisticsSection.style.display = 'block';
|
|
||||||
renderCharts(); // Render charts when switching to statistics tab
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function renderCharts() {
|
|
||||||
// Example data
|
|
||||||
const pieData = {
|
|
||||||
labels: ['Option 1', 'Option 2', 'Option 3'],
|
|
||||||
datasets: [{
|
|
||||||
label: 'Responses',
|
|
||||||
data: [10, 20, 30],
|
|
||||||
backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56'],
|
|
||||||
}]
|
|
||||||
};
|
|
||||||
|
|
||||||
const barData = {
|
|
||||||
labels: ['Question 1', 'Question 2', 'Question 3'],
|
|
||||||
datasets: [{
|
|
||||||
label: 'Number of Responses',
|
|
||||||
data: [15, 25, 10],
|
|
||||||
backgroundColor: '#36A2EB',
|
|
||||||
}]
|
|
||||||
};
|
|
||||||
|
|
||||||
// Pie Chart
|
|
||||||
const pieCtx = document.getElementById('pieChart').getContext('2d');
|
|
||||||
new Chart(pieCtx, {
|
|
||||||
type: 'pie',
|
|
||||||
data: pieData,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Bar Graph
|
|
||||||
const barCtx = document.getElementById('barGraph').getContext('2d');
|
|
||||||
new Chart(barCtx, {
|
|
||||||
type: 'bar',
|
|
||||||
data: barData,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script src="{{ asset('js/script.js') }}"></script>
|
<script src="{{ asset('js/script.js') }}"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
<title>Form Responses</title>
|
<title>Form Responses</title>
|
||||||
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="{{ asset('css/index.css') }}">
|
<link rel="stylesheet" href="{{ asset('css/index.css') }}">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body style="background-color: rgb(253, 251, 251)" class="font-roboto text-gray-800">
|
<body style="background-color: rgb(253, 251, 251)" class="font-roboto text-gray-800">
|
||||||
|
@ -25,10 +26,23 @@
|
||||||
<img src="{{ asset('images/user.png') }}" alt="User" class="h-8 w-8">
|
<img src="{{ asset('images/user.png') }}" alt="User" class="h-8 w-8">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="text-sm font-medium text-center text-purple-700 border-b border-black-700 dark:text-gray-400 dark:border-gray-700 hover: border-b-2">
|
||||||
|
<ul class="flex flex-wrap -mb-px">
|
||||||
|
<li class="mr-2">
|
||||||
|
<a href="javascript:void(0);" onclick="showTab('responses_tab')" class="tab-link text-black-600 font-bold inline-block p-4 border-b-2 border-transparent rounded-t-lg hover:text-purple-700 ">Responses</a>
|
||||||
|
</li>
|
||||||
|
<li class="mr-2">
|
||||||
|
<a href="javascript:void(0);" onclick="showTab('statistics_tab')" class="tab-link text-black-600 font-bold inline-block p-4 border-b-2 border-transparent rounded-t-lg hover:text-purple-700 ">Statistics</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Main Content -->
|
<!-- Main Content -->
|
||||||
<div class="mx-auto max-w-7xl px-6 py-8">
|
<div class="mx-auto max-w-7xl px-6 py-8">
|
||||||
|
|
||||||
|
<!-- Responses Tab -->
|
||||||
|
<div id="responses_tab" class="tab-content">
|
||||||
|
|
||||||
<!-- Share Link -->
|
<!-- Share Link -->
|
||||||
<div class="flex items-center mb-6">
|
<div class="flex items-center mb-6">
|
||||||
<h2 class="text-xl font-semibold mr-4">Responses</h2>
|
<h2 class="text-xl font-semibold mr-4">Responses</h2>
|
||||||
|
@ -43,7 +57,7 @@
|
||||||
</button>
|
</button>
|
||||||
<!-- Copy Link Notification -->
|
<!-- Copy Link Notification -->
|
||||||
<div id="copyNotification"
|
<div id="copyNotification"
|
||||||
class="hidden bg-green-100 border border-green-500 text-green-700 px-3 py-2 rounded ml-2">
|
class="hidden bg-green-100 border border-green-500 text-green-700 px-2 py-1 rounded ml-2">
|
||||||
Link copied!
|
Link copied!
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -84,6 +98,19 @@
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Statistics Tab -->
|
||||||
|
<div id="statistics_tab" class="tab-content hidden w-3/6">
|
||||||
|
<h2 class="text-xl font-semibold mb-6">Statistics</h2>
|
||||||
|
|
||||||
|
@foreach ($statistics as $questionId => $stat)
|
||||||
|
<div class="mb-8">
|
||||||
|
<h3 class="text-lg font-semibold mb-4">{{ $stat['question_text'] }}</h3>
|
||||||
|
<canvas id="chart-{{ $questionId }}"></canvas>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Script for Copy Link Functionality -->
|
<!-- Script for Copy Link Functionality -->
|
||||||
<script>
|
<script>
|
||||||
function copyLink() {
|
function copyLink() {
|
||||||
|
@ -99,6 +126,79 @@
|
||||||
copyNotification.classList.add("hidden");
|
copyNotification.classList.add("hidden");
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showTab(tabId) {
|
||||||
|
document.querySelectorAll('.tab-content').forEach(tab => {
|
||||||
|
tab.classList.add('hidden');
|
||||||
|
});
|
||||||
|
document.getElementById(tabId).classList.remove('hidden');
|
||||||
|
|
||||||
|
document.querySelectorAll('.tab-link').forEach(link => {
|
||||||
|
link.classList.remove('border-purple-600', 'text-purple-600');
|
||||||
|
});
|
||||||
|
document.querySelector(`[onclick="showTab('${tabId}')"]`).classList.add('border-purple-600', 'text-purple-600');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate Charts
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
const statistics = @json($statistics);
|
||||||
|
console.log(statistics); // Log statistics for debugging
|
||||||
|
|
||||||
|
Object.keys(statistics).forEach(questionId => {
|
||||||
|
const ctx = document.getElementById(`chart-${questionId}`).getContext('2d');
|
||||||
|
const stat = statistics[questionId];
|
||||||
|
|
||||||
|
let labels = [];
|
||||||
|
let data = [];
|
||||||
|
let backgroundColors = [];
|
||||||
|
|
||||||
|
if (stat.type === 'multiple_choice' || stat.type === 'checkbox' || stat.type === 'dropdown') {
|
||||||
|
const optionCounts = {};
|
||||||
|
stat.responses.forEach(response => {
|
||||||
|
if (Array.isArray(response)) {
|
||||||
|
response.forEach(option => {
|
||||||
|
if (option in optionCounts) {
|
||||||
|
optionCounts[option]++;
|
||||||
|
} else {
|
||||||
|
optionCounts[option] = 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (response in optionCounts) {
|
||||||
|
optionCounts[response]++;
|
||||||
|
} else {
|
||||||
|
optionCounts[response] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
labels = Object.keys(optionCounts);
|
||||||
|
data = Object.values(optionCounts);
|
||||||
|
backgroundColors = labels.map((_, index) => `rgba(${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)}, 0.5)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
new Chart(ctx, {
|
||||||
|
type: 'bar',
|
||||||
|
data: {
|
||||||
|
labels: labels,
|
||||||
|
datasets: [{
|
||||||
|
label: '# of Responses',
|
||||||
|
data: data,
|
||||||
|
backgroundColor: backgroundColors,
|
||||||
|
borderColor: backgroundColors.map(color => color.replace('0.5', '1')),
|
||||||
|
borderWidth: 1
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
scales: {
|
||||||
|
y: {
|
||||||
|
beginAtZero: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Custom Scripts -->
|
<!-- Custom Scripts -->
|
||||||
|
|
Loading…
Reference in New Issue