Fixed: Duplicating question while creating form, UI changes

This commit is contained in:
yash 2024-07-19 16:38:05 +05:30
parent eedc2668da
commit 2f7529ce2e
10 changed files with 178 additions and 198 deletions

View File

@ -10,14 +10,23 @@ 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;
use Illuminate\Validation\Rules\Unique;
class FormController extends Controller class FormController extends Controller
{ {
public function index() public function index()
{ {
// Get forms belonging to the authenticated user $totalForms = Form::count();
$publishedForms = Form::where('is_published', true)->count();
$totalResponses = Response::count();
$forms = Form::where('user_id', Auth::id())->get(); $forms = Form::where('user_id', Auth::id())->get();
return view('forms.index', compact('forms')); return view('forms.index', [
'forms' => $forms,
'totalForms' => $totalForms,
'publishedForms' => $publishedForms,
'totalResponses' => $totalResponses,
]);
} }
public function create() public function create()
@ -36,13 +45,11 @@ 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 = $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
return view('forms.edit', compact('form', 'questions')); return view('forms.edit', compact('form', 'questions'));
} }
@ -61,6 +68,7 @@ class FormController extends Controller
'questions.*.required' => 'nullable|boolean', 'questions.*.required' => 'nullable|boolean',
]); ]);
$form = new Form(); $form = new Form();
$form->title = $validatedData['title']; $form->title = $validatedData['title'];
$form->description = $validatedData['description']; $form->description = $validatedData['description'];
@ -78,6 +86,8 @@ class FormController extends Controller
$question->save(); $question->save();
} }
return response()->json(['success' => true, 'form_id' => $form->id]); return response()->json(['success' => true, 'form_id' => $form->id]);
} catch (\Exception $e) { } catch (\Exception $e) {
Log::error('Error saving form: ' . $e->getMessage(), ['exception' => $e]); Log::error('Error saving form: ' . $e->getMessage(), ['exception' => $e]);
@ -145,7 +155,6 @@ class FormController extends Controller
$existingQuestionIds[] = $question->id; $existingQuestionIds[] = $question->id;
} }
// Delete questions that were removed
$form->questions()->whereNotIn('id', $existingQuestionIds)->delete(); $form->questions()->whereNotIn('id', $existingQuestionIds)->delete();
Log::info('Remaining questions: ', $form->questions()->get()->toArray()); Log::info('Remaining questions: ', $form->questions()->get()->toArray());

View File

@ -85,7 +85,7 @@ public function viewResponses(Form $form)
} }
} }
return view('responses.viewResponses', compact('form', 'responses', 'statistics')); return view('responses.viewResponses', compact('form', 'responses', 'statistics', 'questions'));
} }

16
package-lock.json generated
View File

@ -5,7 +5,8 @@
"packages": { "packages": {
"": { "": {
"dependencies": { "dependencies": {
"sweetalert": "^2.1.2" "sweetalert": "^2.1.2",
"toastr": "^2.1.4"
}, },
"devDependencies": { "devDependencies": {
"@popperjs/core": "^2.11.6", "@popperjs/core": "^2.11.6",
@ -889,6 +890,11 @@
"node": ">=0.12.0" "node": ">=0.12.0"
} }
}, },
"node_modules/jquery": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg=="
},
"node_modules/laravel-vite-plugin": { "node_modules/laravel-vite-plugin": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.0.5.tgz", "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.0.5.tgz",
@ -1107,6 +1113,14 @@
"node": ">=8.0" "node": ">=8.0"
} }
}, },
"node_modules/toastr": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/toastr/-/toastr-2.1.4.tgz",
"integrity": "sha512-LIy77F5n+sz4tefMmFOntcJ6HL0Fv3k1TDnNmFZ0bU/GcvIIfy6eG2v7zQmMiYgaalAiUv75ttFrPn5s0gyqlA==",
"dependencies": {
"jquery": ">=1.12.0"
}
},
"node_modules/vite": { "node_modules/vite": {
"version": "5.3.3", "version": "5.3.3",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.3.3.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.3.tgz",

View File

@ -14,6 +14,7 @@
"vite": "^5.0.0" "vite": "^5.0.0"
}, },
"dependencies": { "dependencies": {
"sweetalert": "^2.1.2" "sweetalert": "^2.1.2",
"toastr": "^2.1.4"
} }
} }

View File

@ -47,7 +47,7 @@ document.addEventListener("DOMContentLoaded", function () {
function addNewQuestion() { function addNewQuestion() {
const newQuestionDiv = document.createElement("div"); const newQuestionDiv = document.createElement("div");
newQuestionDiv.className = "question"; // newQuestionDiv.className = "question";
newQuestionDiv.innerHTML = ` newQuestionDiv.innerHTML = `
<div class="question mb-4 p-4 border rounded bg-white"> <div class="question mb-4 p-4 border rounded bg-white">
<select class="form-control question_type mb-1" onchange="changeQuestionType(this)"> <select class="form-control question_type mb-1" onchange="changeQuestionType(this)">
@ -59,7 +59,7 @@ document.addEventListener("DOMContentLoaded", function () {
</select> </select>
<input type="text" name="question" class="form-control question-input mb-3" placeholder="Type your question here" /> <input type="text" name="question" class="form-control question-input mb-3" placeholder="Type your question here" />
<div class="options-container mb-3"> <div class="options-container mb-3">
<!-- Options or text input will be dynamically added here -->
</div> </div>
<button class="btn btn-secondary add-option-btn" onclick="addOption(this)"> <button class="btn btn-secondary add-option-btn" onclick="addOption(this)">
Add Option Add Option
@ -119,6 +119,8 @@ document.addEventListener("DOMContentLoaded", function () {
const questions = document.querySelectorAll(".question"); const questions = document.querySelectorAll(".question");
let formData = []; let formData = [];
console.log(questions);
questions.forEach((question) => { questions.forEach((question) => {
const questionType = question.querySelector("select").value; const questionType = question.querySelector("select").value;
const questionText = question.querySelector(".question-input").value; const questionText = question.querySelector(".question-input").value;
@ -135,6 +137,13 @@ document.addEventListener("DOMContentLoaded", function () {
options: options, options: options,
required: isRequired required: isRequired
}); });
console.log({
type: questionType,
text: questionText,
options: options,
required: isRequired
});
}); });
const csrfTokenMeta = document.querySelector('meta[name="csrf-token"]'); const csrfTokenMeta = document.querySelector('meta[name="csrf-token"]');
@ -152,6 +161,8 @@ document.addEventListener("DOMContentLoaded", function () {
questions: formData questions: formData
}; };
console.log(data);
fetch("/forms", { fetch("/forms", {
method: "POST", method: "POST",
@ -195,6 +206,8 @@ document.addEventListener("DOMContentLoaded", function () {
window.addNewQuestion = addNewQuestion; window.addNewQuestion = addNewQuestion;
window.deleteQuestion = deleteQuestion; window.deleteQuestion = deleteQuestion;
window.addOption = addOption; window.addOption = addOption;
@ -202,34 +215,7 @@ document.addEventListener("DOMContentLoaded", function () {
window.changeQuestionType = changeQuestionType; window.changeQuestionType = changeQuestionType;
window.saveForm = saveForm; window.saveForm = saveForm;
window.previewForm = function (formId) { // document.getElementById("add-question-button").addEventListener("click", addNewQuestion);
const formTitle = document.getElementById("form-title").value;
const formDescription = document.getElementById("form-description").value;
const questions = document.querySelectorAll(".question");
let formData = [];
questions.forEach((question) => {
const questionType = question.querySelector("select").value;
const questionText = question.querySelector(".question-input").value;
const options = Array.from(question.querySelectorAll(".option-input")).map((input) => input.value);
formData.push({
type: questionType,
text: questionText,
options: options,
});
});
const formParams = new URLSearchParams({
title: formTitle,
description: formDescription,
data: JSON.stringify(formData),
});
window.location.href = '/forms/' + formId + '/preview';
};
// Assuming there's a button with id "add-question-button"
document.getElementById("add-question-button").addEventListener("click", addNewQuestion);
document.getElementById("questions_section").addEventListener("DOMNodeInserted", updateAddButtonPosition); document.getElementById("questions_section").addEventListener("DOMNodeInserted", updateAddButtonPosition);
document.getElementById("questions_section").addEventListener("DOMNodeRemoved", updateAddButtonPosition); document.getElementById("questions_section").addEventListener("DOMNodeRemoved", updateAddButtonPosition);

View File

@ -1,104 +1,4 @@
{{-- <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Google-Form-Clone</title>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" />
<link rel="stylesheet" href={{ asset('css/app.css') }} />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<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" />
</head>
<body>
<nav class="bg-white p-4 shadow-lg">
<div class="container mx-auto flex justify-between items-center">
<a href="{{ url('/') }}" style="color: rgb(103,58,183)"
class="text-3xl font-bold font-sans">LaraForms</a>
<div class="relative dropdown">
<button id="profileMenuButton" class="flex items-center focus:outline-none">
<img src="{{ asset('images/user.png') }}" alt="Profile"
class="w-10 h-10 rounded-full border-2 border-white">
</button>
<div id="profileMenu"
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') }}">
@csrf
<button type="submit" class="block px-4 py-2 text-gray-700 hover:bg-gray-200 w-full text-left">
Logout
</button>
</form>
</div>
</div>
</div>
</nav>
<div style="background-color: #f0ebf8; max-width: 100%" class="question_form p-4 rounded">
<div class="section">
<div class="question_title_section mb-1">
<div class="question_form_top">
<input type="text" id="form-title" name="title" class="form-control form-control-lg p-2 mb-2" placeholder="Untitled Form" />
<input type="text" name="description" id="form-description" class="form-control form-control-sm" placeholder="Form Description" />
</div>
</div>
</div>
<div class="section" id="questions_section">
<div class="question mb-4 p-3 border rounded bg-white">
<select class="form-control question_type mb-1" onchange="changeQuestionType(this)">
<option value="">Select Question Type</option>
<option value="multiple_choice">Multiple Choice</option>
<option value="checkbox">Checkbox</option>
<option value="dropdown">Dropdown</option>
</select>
<input type="text" name="question" class="form-control question-input mb-3" placeholder="Type your question here" />
<div class="options-container mb-3">
<div class="option d-flex align-items-center">
<input type="text" name="option" class="form-control option-input" placeholder="Option 1" />
<span class="delete-option ml-2 text-danger" onclick="deleteOption(this)" style="cursor: pointer;">&#10005;</span>
</div>
</div>
<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 class="sidebar">
<div id="moveableDiv">
<button class="btn btn-light shadow-sm" onclick="addNewQuestion();">
<img src="{{ asset('images/add.png') }}" alt="" width="20px" height="20px" />
</button>
</div>
</div>
</div>
</div>
<div style="background-color: #f0ebf8"class="btnsub">
<span>
<button type="submit" name="save" value="save" onclick="saveForm()"
class="btnsave btn btn-secondary">
Save
</button>
</span>
&nbsp;
&nbsp;
&nbsp;
<span>
<button type="submit" name="publish" value="publish" onclick="saveForm()"
class="btnsave btn btn-secondary">
Publish
</button>
</span>
</div>
<script src={{ asset('js/script.js') }}></script>
</body>
</html> --}}
@ -122,7 +22,7 @@
</head> </head>
<body style="background-color: #f4f4f9;" > <body style="background-color: #f4f4f9;" >
<nav class="bg-white p-4 shadow-sm"> <nav class="bg-white p-4 shadow-md">
<div class="mx-auto flex justify-between items-center"> <div class="mx-auto flex justify-between items-center">
<a href="{{ url('/') }}" style="color: rgb(103,58,183)" <a href="{{ url('/') }}" style="color: rgb(103,58,183)"
class="text-3xl font-bold font-sans">LaraForms</a> class="text-3xl font-bold font-sans">LaraForms</a>
@ -146,7 +46,7 @@
<br><br> <br><br>
<div style="background-color: #f4f4f9; max-width: 100%" class="question_form p-4 rounded"> <div style="background-color: #f4f4f9; max-width: 100%" class="question_form p-4 rounded">
<div class="section"> <div class="section">
<div class="question_title_section mb-1"> <div class="question_title_section mb-4">
<div class="question_form_top"> <div class="question_form_top">
<input type="text" id="form-title" name="title" class="form-control form-control-lg p-2 mb-2" placeholder="Untitled Form" /> <input type="text" id="form-title" name="title" class="form-control form-control-lg p-2 mb-2" placeholder="Untitled Form" />
<input type="text" name="description" id="form-description" class="form-control form-control-sm" placeholder="Form Description" /> <input type="text" name="description" id="form-description" class="form-control form-control-sm" placeholder="Form Description" />
@ -164,7 +64,7 @@
</select> </select>
<input type="text" name="question" class="form-control question-input mb-3" placeholder="Type your question here" /> <input type="text" name="question" class="form-control question-input mb-3" placeholder="Type your question here" />
<div class="options-container mb-3"> <div class="options-container mb-3">
<!-- Options or text input will be dynamically added here -->
</div> </div>
<button class="btn btn-secondary add-option-btn" onclick="addOption(this)"> <button class="btn btn-secondary add-option-btn" onclick="addOption(this)">
Add Option Add Option
@ -188,7 +88,7 @@
<div style="background-color: #f4f4f9;" class="btnsub"> <div style="background-color: #f4f4f9;" class="btnsub">
<span> <span>
<button type="submit" name="save" value="save" onclick="saveForm()" <button type="submit" name="save" data-action:"save" value="save" onclick="saveForm()"
class="btnsave btn btn-secondary"> class="btnsave btn btn-secondary">
Save Save
</button> </button>
@ -197,7 +97,7 @@
&nbsp; &nbsp;
&nbsp; &nbsp;
<span> <span>
<button type="submit" name="publish" value="publish" onclick="saveForm()" <button type="submit" name="publish" data-action:"publish" value="publish" onclick="saveForm()"
class="btnsave btn btn-secondary"> class="btnsave btn btn-secondary">
Publish Publish
</button> </button>

View File

@ -20,7 +20,7 @@
</style> </style>
</head> </head>
<body class="bg-light"> <body class="bg-purple-100">
<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('/') }}" <span style="color: rgb(103,58,183)" class="text-3xl font-bold font-sans"><a href="{{ url('/') }}"

View File

@ -6,6 +6,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Forms</title> <title>Forms</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 href="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/css/toastr.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
<style> <style>
.dropdown:hover .dropdown-menu { .dropdown:hover .dropdown-menu {
display: block; display: block;
@ -17,7 +19,7 @@
</style> </style>
</head> </head>
<body style="bg-gray-100"> <body class="bg-gray-100">
<nav class="bg-white p-4 shadow-lg"> <nav class="bg-white p-4 shadow-lg">
<div class="container mx-auto flex justify-between items-center"> <div class="container mx-auto flex justify-between items-center">
<a href="{{ url('/') }}" style="color: rgb(103,58,183)" <a href="{{ url('/') }}" style="color: rgb(103,58,183)"
@ -49,16 +51,31 @@
<span class="block sm:inline">{{ session('delete') }}</span> <span class="block sm:inline">{{ session('delete') }}</span>
</div> </div>
@endif @endif
<div class="container mx-auto mt-10"> <div class="container mx-auto mt-10 ">
<div class="flex justify-between mb-6 items-center"> <div class="flex justify-between mb-6 items-center grid grid-cols-4 gap-20">
<a href="{{ route('forms.create') }}" <a href="{{ route('forms.create') }}"
class="inline-block px-6 py-3 text-white font-semibold rounded-md shadow bg-purple-700 hover:bg-purple-900 transition duration-200">Start class="inline-block px-6 py-3 text-white font-semibold rounded-md shadow bg-purple-700 hover:bg-purple-900 transition duration-200">Start
a new form</a> a new form</a>
<a style="color: rgb(103,58,183)" class="block max-w-md p-5 bg-white border border-gray-200 rounded-lg shadow">
<h5 class="mb-2 text-gray-800 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Total Forms Created</h5>
<p class="font-normal text-gray-700 dark:text-gray-400">{{ $totalForms }}</p>
</a>
<a class="block max-w-md p-5 bg-white border border-gray-200 rounded-lg shadow">
<h5 class="mb-2 text-gray-800 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Total Forms Published</h5>
<p class="font-normal text-gray-700 dark:text-gray-400">{{ $publishedForms }}</p>
</a>
<a class="block max-w-md p-5 bg-white border border-gray-200 rounded-lg shadow">
<h5 class="mb-2 text-gray-800 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Total Responses Received</h5>
<p class="font-normal text-gray-700 dark:text-gray-400">{{ $totalResponses }}</p>
</a>
</div> </div>
<h2 class="text-3xl font-semibold text-gray-800 font-sans">Recent Forms</h2> <h2 class="text-3xl font-semibold text-gray-800 font-sans">Created Forms</h2>
<br> <br>
<div class="bg-white shadow-custom rounded-lg p-6"> <div class="shadow-custom rounded-lg p-6 bg-gray-100">
@if ($forms->isEmpty()) @if ($forms->isEmpty())
<p class="text-gray-600 text-center">No forms available.</p> <p class="text-gray-600 text-center">No forms available.</p>
@else @else
@ -76,8 +93,8 @@
Responses</th> Responses</th>
<th class="py-4 px-6 border-b border-gray-200 text-left text-sm font-semibold text-gray-600"> <th class="py-4 px-6 border-b border-gray-200 text-left text-sm font-semibold text-gray-600">
Status</th> Status</th>
<th></th> <th class="py-4 px-6 border-b border-gray-200 text-left text-sm font-semibold text-gray-600"></th>
<th> <th class="py-4 px-6 border-b border-gray-200 text-left text-sm font-semibold text-gray-600">
</th> </th>
</tr> </tr>
</thead> </thead>
@ -104,9 +121,11 @@
</td> </td>
<td class="py-8 px-6 border-b border-gray-200 flex items-center space-x-10"> <td class="py-8 px-6 border-b border-gray-200 flex items-center space-x-10">
@if (!$form->is_published) @if (!$form->is_published)
<a href="{{ route('forms.edit', $form) }}" <a href="{{ route('forms.edit', $form) }}" class="text-green-500 hover:underline">Edit</a>
class="text-green-500 hover:underline">Edit</a> @else
<a href="#" class="text-gray-500" id="formd" onclick="handle()">Edit</a>
@endif @endif
</td> </td>
<td> <td>
<form action="{{ route('forms.destroy', $form) }}" method="POST" <form action="{{ route('forms.destroy', $form) }}" method="POST"
@ -125,9 +144,13 @@
</div> </div>
<script> <script>
document.getElementById('profileMenuButton').addEventListener('click', function() { function handle() {
document.getElementById('profileMenu').classList.toggle('hidden'); Swal.fire({
title: 'You cannot edit a published form',
icon: 'info',
confirmButtonText: 'OK'
}); });
}
setTimeout(function() { setTimeout(function() {
var successMessage = document.getElementById('successMessage'); var successMessage = document.getElementById('successMessage');
if (successMessage) { if (successMessage) {
@ -135,6 +158,8 @@
} }
}, 3000); }, 3000);
</script> </script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js" ></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/js/toastr.min.js"></script>
</body> </body>
</html> </html>

View File

@ -13,29 +13,29 @@
<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">
</head> </head>
<body> <body class="bg-gray-100">
<nav class="bg-white p-4 shadow-sm"> <nav class="bg-white p-2 shadow-gray-lg">
<div class="mx-auto flex justify-between items-center"> <div class="mx-auto flex justify-between items-center">
<a href="{{ url('/') }}" style="color: rgb(103,58,183)" <a href="{{ url('/') }}" style="color: rgb(103,58,183)"
class="text-3xl font-bold font-sans">LaraForms</a> class="text-3xl font-bold font-sans">LaraForms</a>
<div class="relative dropdown"> <div class="relative dropdown">
<button id="profileMenuButton" class="flex items-center focus:outline-none"> <div class="btnsub text-center mt-4">
<img src="{{ asset('images/user.png') }}" alt="Profile" <form action="{{ route('forms.publish', $form->id) }}" method="POST">
class="w-10 h-10 rounded-full border-2 border-white">
</button>
<div id="profileMenu"
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') }}">
@csrf @csrf
<button type="submit" class="block px-4 py-2 text-gray-700 hover:bg-gray-200 w-full text-left"> @method('PATCH')
Logout <span><button type="submit" name="publish" value="publish" class="btnsave btn btn-secondary">
</button> {{ $form->is_published ? 'Unpublish' : 'Publish' }}
</button></span>
</form> </form>
&nbsp;
&nbsp;
<div><button type="submit" name="publish" value="publish" class="btnsave btn btn-secondary">Edit</button></div>
</div> </div>
</div> </div>
</div> </div>
</nav> </nav>
<div class="question_form bg-light p-4 rounded shadow-sm"> <div class="question_form bg-gray-100 p-4 rounded shadow-sm">
<div class="section"> <div class="section">
<div class="question_title_section mb-4"> <div class="question_title_section mb-4">
<div class="question_form_top"> <div class="question_form_top">
@ -46,7 +46,7 @@
</div> </div>
<div class="section" id="questions_section"> <div class="section" id="questions_section">
@foreach ($form->questions as $index => $question) @foreach ($form->questions as $index => $question)
<div class="question mb-4 p-3 border rounded bg-white"> <div class="question mb-4 p-4 border rounded bg-white">
<select class="form-control question_type mb-3" name="questions[{{ $index }}][type]" onchange="changeQuestionType(this)" disabled> <select class="form-control question_type mb-3" name="questions[{{ $index }}][type]" onchange="changeQuestionType(this)" disabled>
<option value="multiple_choice" {{ $question->type === 'multiple_choice' ? 'selected' : '' }}>Multiple Choice</option> <option value="multiple_choice" {{ $question->type === 'multiple_choice' ? 'selected' : '' }}>Multiple Choice</option>
<option value="checkbox" {{ $question->type === 'checkbox' ? 'selected' : '' }}>Checkbox</option> <option value="checkbox" {{ $question->type === 'checkbox' ? 'selected' : '' }}>Checkbox</option>

View File

@ -11,19 +11,30 @@
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <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 class="font-roboto text-gray-800 bg-white">
<!-- Header --> <!-- Header -->
<div class="bg-white shadow-md px-6 py-4 flex justify-between items-center"> <div class="bg-white shadow-md px-6 py-4 flex justify-between items-center">
<div class="flex items-center"> <div class="flex items-center">
<h1 class="text-2xl font-semibold text-purple-900">{{ $form->title }} - Responses</h1> <h1 class="text-2xl font-semibold text-purple-900">{{ $form->title }} - Responses</h1>
</div> </div>
<div class="flex items-center"> <div class="relative dropdown">
<img src="{{ asset('images/menu.png') }}" alt="Menu" class="h-8 w-8 mr-4"> <button id="profileMenuButton" class="flex items-center focus:outline-none">
<img src="{{ asset('images/user.png') }}" alt="User" class="h-8 w-8"> <img src="{{ asset('images/user.png') }}" alt="Profile"
class="w-10 h-10 rounded-full border-2 border-white">
</button>
<div id="profileMenu"
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') }}">
@csrf
<button type="submit" class="block px-4 py-2 text-gray-700 hover:bg-gray-200 w-full text-left">
Logout
</button>
</form>
</div>
</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"> {{-- <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"> <ul class="flex flex-wrap -mb-px">
<li class="mr-2"> <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> <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>
@ -32,7 +43,7 @@
<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> <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> </li>
</ul> </ul>
</div> </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">
@ -42,7 +53,7 @@
<!-- 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>
<div class="flex items-center"> <div class="flex items-center">
<input type="text" value="{{ route('responses.showForm', $form) }}" id="shareLink" <input type="text" value="{{ route('responses.showForm', $form) }}" id="shareLink"
class="bg-white border border-gray-300 px-3 py-1 rounded-l sm:w-auto focus:outline-none" class="bg-white border border-gray-300 px-3 py-1 rounded-l sm:w-auto focus:outline-none"
@ -59,7 +70,9 @@
</div> </div>
</div> </div>
</div> </div>
<br>
<h2 class="text-xl font-semibold mr-4">Responses</h2>
<br>
<!-- Responses Table --> <!-- Responses Table -->
@if ($responses->isEmpty()) @if ($responses->isEmpty())
<p class="text-gray-600">No responses available.</p> <p class="text-gray-600">No responses available.</p>
@ -100,7 +113,7 @@
</div> </div>
<!-- Statistics Tab --> <!-- Statistics Tab -->
<div id="statistics_tab" class="tab-content hidden w-3/6"> {{-- <div id="statistics_tab" class="tab-content hidden w-3/6">
<h2 class="text-xl font-semibold mb-6">Statistics</h2> <h2 class="text-xl font-semibold mb-6">Statistics</h2>
@foreach ($statistics as $questionId => $stat) @foreach ($statistics as $questionId => $stat)
@ -109,7 +122,7 @@
<canvas id="chart-{{ $questionId }}"></canvas> <canvas id="chart-{{ $questionId }}"></canvas>
</div> </div>
@endforeach @endforeach
</div> </div> --}}
</div> </div>
<!-- Script for Copy Link Functionality --> <!-- Script for Copy Link Functionality -->
@ -140,7 +153,6 @@
document.querySelector(`[onclick="showTab('${tabId}')"]`).classList.add('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 () { document.addEventListener('DOMContentLoaded', function () {
const statistics = @json($statistics); const statistics = @json($statistics);
console.log(statistics); // Log statistics for debugging console.log(statistics); // Log statistics for debugging
@ -178,28 +190,61 @@
backgroundColors = labels.map((_, index) => `rgba(${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)}, 0.5)`); 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, { if (stat.type === 'multiple_choice' || stat.type === 'dropdown') {
type: 'bar', new Chart(ctx, {
data: { type: 'pie',
labels: labels, data: {
datasets: [{ labels: labels,
label: 'Responses', datasets: [{
data: data, label: 'Responses',
backgroundColor: backgroundColors, data: data,
borderColor: backgroundColors.map(color => color.replace('0.5', '1')), backgroundColor: backgroundColors,
borderWidth: 1 borderColor: backgroundColors.map(color => color.replace('0.5', '1')),
}] borderWidth: 1
}, }]
options: { },
scales: { options: {
y: { scales: {
y: {
beginAtZero: true beginAtZero: true
}
}
responsive: true,
plugins: {
legend: {
position: 'top',
},
tooltip: {
enabled: true
}
} }
} }
} });
}); } else if (stat.type === 'checkbox') {
new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: '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 -->