Added Required button, Text box question type, Added sweetalerts
This commit is contained in:
parent
7ad8d86e7f
commit
22bf15864e
|
@ -25,6 +25,15 @@ class FormController extends Controller
|
|||
return view('forms.create');
|
||||
}
|
||||
|
||||
public function togglePublish(Form $form)
|
||||
{
|
||||
$form->is_published = !$form->is_published;
|
||||
$form->save();
|
||||
|
||||
return redirect()->route('forms.show', $form->id)->with('success', 'Form publish status updated.');
|
||||
}
|
||||
|
||||
|
||||
public function edit(Form $form)
|
||||
{
|
||||
// Questions are already fetched with their options cast to array due to the casts property
|
||||
|
@ -40,20 +49,22 @@ class FormController extends Controller
|
|||
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
{
|
||||
try {
|
||||
$validatedData = $request->validate([
|
||||
'title' => 'required|string|max:255',
|
||||
'description' => 'nullable|string',
|
||||
'questions' => 'required|array',
|
||||
'questions.*.type' => 'required|string|in:multiple_choice,checkbox,dropdown,short_answer,long_answer',
|
||||
'questions.*.text' => 'required|string', // This should match the key used in the JavaScript
|
||||
'questions.*.type' => 'required|string|in:multiple_choice,checkbox,dropdown,text',
|
||||
'questions.*.text' => 'required|string',
|
||||
'questions.*.options' => 'nullable|array',
|
||||
'questions.*.required' => 'nullable|boolean',
|
||||
]);
|
||||
|
||||
$form = new Form();
|
||||
$form->title = $validatedData['title'];
|
||||
$form->description = $validatedData['description'];
|
||||
$form->is_published = $request->input('is_published', false); // Default to false if not provided
|
||||
$form->is_published = $request->input('is_published', false);
|
||||
$form->user_id = Auth::id();
|
||||
$form->save();
|
||||
|
||||
|
@ -61,15 +72,18 @@ class FormController extends Controller
|
|||
$question = new Question();
|
||||
$question->form_id = $form->id;
|
||||
$question->type = $questionData['type'];
|
||||
$question->question_text = $questionData['text']; // Ensure this matches the key in the validated data
|
||||
$question->question_text = $questionData['text'];
|
||||
$question->options = isset($questionData['options']) ? json_encode($questionData['options']) : null;
|
||||
|
||||
$question->required = isset($questionData['required']) ? $questionData['required'] : false;
|
||||
$question->save();
|
||||
}
|
||||
Session::flash('success', 'Form created successfully!');
|
||||
return response()->json(['success' => true, 'form_id' => $form->id]);
|
||||
}
|
||||
|
||||
return response()->json(['success' => true, 'form_id' => $form->id]);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Error saving form: ' . $e->getMessage(), ['exception' => $e]);
|
||||
return response()->json(['success' => false, 'message' => 'Error saving form'], 500);
|
||||
}
|
||||
}
|
||||
|
||||
public function show(Form $form)
|
||||
{
|
||||
|
@ -99,7 +113,7 @@ class FormController extends Controller
|
|||
'description' => 'nullable|string|max:255',
|
||||
'questions' => 'required|array',
|
||||
'questions.*.id' => 'nullable|exists:questions,id',
|
||||
'questions.*.type' => 'required|string|in:multiple_choice,checkbox,dropdown,short_answer,long_answer',
|
||||
'questions.*.type' => 'required|string|in:multiple_choice,checkbox,dropdown,text',
|
||||
'questions.*.text' => 'required|string|max:255',
|
||||
'questions.*.options' => 'nullable|array',
|
||||
'questions.*.options.*' => 'nullable|string|max:255',
|
||||
|
@ -149,6 +163,8 @@ class FormController extends Controller
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
public function destroy(Form $form)
|
||||
{
|
||||
// This will also delete all related questions and responses due to foreign key constraints
|
||||
|
|
|
@ -103,12 +103,27 @@ public function viewResponses(Form $form)
|
|||
{
|
||||
Log::info($request->all()); // Log the entire request data for debugging
|
||||
|
||||
// Fetch all questions for the form
|
||||
$questions = $form->questions;
|
||||
|
||||
// Extract IDs of required questions
|
||||
$requiredQuestionIds = $questions->where('required', true)->pluck('id')->toArray();
|
||||
|
||||
// Validate and process form submission
|
||||
$validatedData = $request->validate([
|
||||
'answers' => 'required|array',
|
||||
'answers.*' => 'required',
|
||||
'answers.*' => 'required', // Ensure all answers are provided
|
||||
]);
|
||||
|
||||
// Ensure all required questions are answered
|
||||
foreach ($requiredQuestionIds as $requiredQuestionId) {
|
||||
if (!array_key_exists($requiredQuestionId, $validatedData['answers'])) {
|
||||
return redirect()->back()
|
||||
->withErrors(['errors' => 'Please answer all required questions.'])
|
||||
->withInput();
|
||||
}
|
||||
}
|
||||
|
||||
Log::info($validatedData); // Log the validated data for debugging
|
||||
|
||||
// Generate a UUID for response_id
|
||||
|
@ -129,4 +144,9 @@ public function viewResponses(Form $form)
|
|||
return redirect()->route('responses.showForm', $form)
|
||||
->with('success', 'Response submitted successfully.');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -14,8 +14,9 @@ return new class extends Migration
|
|||
Schema::create('questions', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('form_id')->constrained()->onDelete('cascade');
|
||||
$table->enum('type', ['multiple_choice', 'checkbox', 'dropdown', 'short_answer', 'long_answer']);
|
||||
$table->enum('type', ['multiple_choice', 'checkbox', 'dropdown', 'text']);
|
||||
$table->text('question_text');
|
||||
$table->boolean('required')->default(false);
|
||||
$table->json('options')->nullable(); // Store options as JSON if applicable
|
||||
$table->timestamps();
|
||||
});
|
||||
|
|
|
@ -1,216 +1,3 @@
|
|||
// document.addEventListener("DOMContentLoaded", function () {
|
||||
// const questionsSection = document.getElementById("questions_section");
|
||||
|
||||
// function addOption(button) {
|
||||
// const optionContainer = button.previousElementSibling;
|
||||
// const optionDiv = document.createElement("div");
|
||||
// optionDiv.className = "option";
|
||||
// optionDiv.innerHTML = `
|
||||
// <input type="text" class="form-control option-input" placeholder="New Option" />
|
||||
// <span class="delete-option" onclick="deleteOption(this)">✕</span>
|
||||
// `;
|
||||
// optionContainer.appendChild(optionDiv);
|
||||
// updateAddButtonPosition();
|
||||
// }
|
||||
|
||||
// function deleteOption(span) {
|
||||
// const optionDiv = span.parentElement;
|
||||
// optionDiv.remove();
|
||||
// updateAddButtonPosition();
|
||||
// }
|
||||
|
||||
// function changeQuestionType(select) {
|
||||
// const questionInput = select.nextElementSibling;
|
||||
// questionInput.style.display = "block";
|
||||
// const optionsContainer = select.nextElementSibling.nextElementSibling;
|
||||
// optionsContainer.innerHTML =
|
||||
// '<input type="text" class="form-control option-input" placeholder="Option 1">';
|
||||
// }
|
||||
|
||||
// let questionCount = document.querySelectorAll(".question").length;
|
||||
|
||||
// function addNewQuestion() {
|
||||
// const newQuestionDiv = document.createElement("div");
|
||||
// newQuestionDiv.className = "question";
|
||||
// newQuestionDiv.innerHTML = `
|
||||
// <select class="form-control question_type" 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" class="form-control question-input" placeholder="Type your question here" />
|
||||
// <div class="options-container">
|
||||
// <div class="option">
|
||||
// <input type="text" class="form-control option-input" placeholder="Option 1" />
|
||||
// <span class="delete-option" onclick="deleteOption(this)">✕</span>
|
||||
// </div>
|
||||
// </div>
|
||||
// <button class="btn btn-secondary" onclick="addOption(this)">Add Option</button>
|
||||
// <button class="btnn" onclick="deleteQuestion(this)">
|
||||
// <img src="public/images/bin.png" alt="" width="20px" height="20px" />
|
||||
// </button>
|
||||
// `;
|
||||
// questionsSection.appendChild(newQuestionDiv);
|
||||
// questionCount++;
|
||||
// updateAddButtonPosition();
|
||||
// }
|
||||
|
||||
// function saveForm() {
|
||||
// const formTitle = document.getElementById("form-title").value;
|
||||
// const formDescription =
|
||||
// document.getElementById("form-description").value;
|
||||
// const questions = document.querySelectorAll(".question");
|
||||
// let formData = [];
|
||||
|
||||
// questions.forEach((question, index) => {
|
||||
// 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, // Ensure this matches the key in the PHP validation
|
||||
// options: options,
|
||||
// });
|
||||
// });
|
||||
|
||||
// // Get CSRF token
|
||||
// const csrfTokenMeta = document.querySelector('meta[name="csrf-token"]');
|
||||
// let csrfToken = "";
|
||||
// if (csrfTokenMeta) {
|
||||
// csrfToken = csrfTokenMeta.getAttribute("content");
|
||||
// } else {
|
||||
// console.error("CSRF token meta tag not found.");
|
||||
// // Handle the error condition gracefully or abort further execution
|
||||
// return;
|
||||
// }
|
||||
|
||||
// const data = {
|
||||
// title: formTitle,
|
||||
// description: formDescription,
|
||||
// questions: formData,
|
||||
// };
|
||||
|
||||
// console.log("Form Data:", data); // Log form data
|
||||
// console.log("CSRF Token:", csrfToken); // Log CSRF token
|
||||
|
||||
// // Send AJAX request to save the form data
|
||||
// fetch("/forms", {
|
||||
// method: "POST",
|
||||
// headers: {
|
||||
// "Content-Type": "application/json",
|
||||
// "X-CSRF-TOKEN": csrfToken,
|
||||
// },
|
||||
// body: JSON.stringify(data),
|
||||
// })
|
||||
// .then((response) => {
|
||||
// if (!response.ok) {
|
||||
// throw new Error("Network response was not ok");
|
||||
// }
|
||||
// return response.json();
|
||||
// })
|
||||
// .then((result) => {
|
||||
// console.log("Server Response:", result); // Log server response
|
||||
// if (result.success) {
|
||||
// alert("Form saved successfully!");
|
||||
// window.location.href = "/forms"; // Redirect to forms index page
|
||||
// } else {
|
||||
// alert("Failed to save form.");
|
||||
// }
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// console.error("Error saving form:", error);
|
||||
// alert("An error occurred while saving the form.");
|
||||
// });
|
||||
// }
|
||||
|
||||
// window.addNewQuestion = addNewQuestion;
|
||||
// window.deleteQuestion = deleteQuestion;
|
||||
// window.addOption = addOption;
|
||||
// window.changeQuestionType = changeQuestionType;
|
||||
// window.saveForm = saveForm;
|
||||
|
||||
// window.previewForm = function (formId) {
|
||||
// const formTitle = document.getElementById("form-title").value;
|
||||
// const formDescription =
|
||||
// document.getElementById("form-description").value;
|
||||
// const questions = document.querySelectorAll(".question");
|
||||
// let formData = [];
|
||||
|
||||
// questions.forEach((question, index) => {
|
||||
// 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';
|
||||
// };
|
||||
|
||||
// window.addNewQuestion = addNewQuestion;
|
||||
// window.deleteQuestion = deleteQuestion;
|
||||
// window.addOption = addOption;
|
||||
// window.changeQuestionType = changeQuestionType;
|
||||
// });
|
||||
|
||||
// function deleteQuestion(element) {
|
||||
// let questionContainer = element.closest(".question");
|
||||
// if (questionContainer) {
|
||||
// questionContainer.remove();
|
||||
// updateAddButtonPosition();
|
||||
// }
|
||||
// }
|
||||
|
||||
// function deleteOption(span) {
|
||||
// const optionDiv = span.parentElement;
|
||||
// optionDiv.remove();
|
||||
// updateAddButtonPosition();
|
||||
// }
|
||||
|
||||
// function updateAddButtonPosition() {
|
||||
// const questionsSection = document.getElementById("questions_section");
|
||||
// const lastQuestion = questionsSection.lastElementChild;
|
||||
|
||||
// // Check if lastQuestion exists before accessing its properties
|
||||
// if (lastQuestion) {
|
||||
// const selectQuestionType = lastQuestion.querySelector(".question_type");
|
||||
|
||||
// // Ensure selectQuestionType is not null before accessing offsetTop
|
||||
// if (selectQuestionType) {
|
||||
// const sidebar = document.getElementById("moveableDiv");
|
||||
// const offset = selectQuestionType.offsetTop - sidebar.offsetHeight;
|
||||
// sidebar.style.transform = `translateY(${offset}px)`;
|
||||
// console.log(`Moving sidebar to: ${offset}px`);
|
||||
// } else {
|
||||
// console.warn("No .question_type found in last question.");
|
||||
// }
|
||||
// } else {
|
||||
// const sidebar = document.getElementById("moveableDiv");
|
||||
// sidebar.style.transform = `translateY(0px)`;
|
||||
// console.log(`Moving sidebar to: 0px`);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const questionsSection = document.getElementById("questions_section");
|
||||
|
||||
|
@ -233,12 +20,27 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
updateAddButtonPosition();
|
||||
}
|
||||
|
||||
function changeQuestionType(select) {
|
||||
const questionInput = select.nextElementSibling;
|
||||
questionInput.style.display = "block";
|
||||
const optionsContainer = select.nextElementSibling.nextElementSibling;
|
||||
optionsContainer.innerHTML =
|
||||
'<input type="text" class="form-control option-input" placeholder="Option 1">';
|
||||
function changeQuestionType(selectElement) {
|
||||
const questionContainer = selectElement.closest('.question');
|
||||
const optionsContainer = questionContainer.querySelector('.options-container');
|
||||
const addOptionButton = questionContainer.querySelector('.btn-secondary');
|
||||
const questionType = selectElement.value;
|
||||
|
||||
// Clear the options container
|
||||
optionsContainer.innerHTML = '';
|
||||
|
||||
if (questionType === 'multiple_choice' || questionType === 'checkbox' || questionType === 'dropdown') {
|
||||
const optionDiv = document.createElement('div');
|
||||
optionDiv.className = 'option d-flex align-items-center mb-2';
|
||||
optionDiv.innerHTML = `
|
||||
<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;">✕</span>
|
||||
`;
|
||||
optionsContainer.appendChild(optionDiv);
|
||||
addOptionButton.style.display = 'inline-block'; // Show the "Add Option" button
|
||||
} else if (questionType === 'text') {
|
||||
addOptionButton.style.display = 'none'; // Hide the "Add Option" button
|
||||
}
|
||||
}
|
||||
|
||||
let questionCount = document.querySelectorAll(".question").length;
|
||||
|
@ -247,26 +49,27 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
const newQuestionDiv = document.createElement("div");
|
||||
newQuestionDiv.className = "question";
|
||||
newQuestionDiv.innerHTML = `
|
||||
<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-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>
|
||||
<option value="text">Text</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;">✕</span>
|
||||
<!-- Options or text input will be dynamically added here -->
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-secondary" onclick="addOption(this)">
|
||||
<button class="btn btn-secondary add-option-btn" onclick="addOption(this)">
|
||||
Add Option
|
||||
</button>
|
||||
<button class="btn btn-md" id="moveUpButton" onclick="deleteQuestion(this);">
|
||||
<img src="/images/bin.png" alt="" width="20px" height="20px" />
|
||||
</button>
|
||||
<label class="ml-3">
|
||||
<input type="checkbox" class="required-checkbox"> Required
|
||||
</label>
|
||||
</div>
|
||||
`;
|
||||
questionsSection.appendChild(newQuestionDiv);
|
||||
|
@ -316,14 +119,21 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
const questions = document.querySelectorAll(".question");
|
||||
let formData = [];
|
||||
|
||||
questions.forEach((question, index) => {
|
||||
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);
|
||||
const isRequired = question.querySelector(".required-checkbox").checked;
|
||||
let options = [];
|
||||
|
||||
if (questionType === 'multiple_choice' || questionType === 'checkbox' || questionType === 'dropdown') {
|
||||
options = Array.from(question.querySelectorAll(".option-input")).map((input) => input.value);
|
||||
}
|
||||
|
||||
formData.push({
|
||||
type: questionType,
|
||||
text: questionText,
|
||||
options: options,
|
||||
required: isRequired
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -339,33 +149,38 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
const data = {
|
||||
title: formTitle,
|
||||
description: formDescription,
|
||||
questions: formData,
|
||||
questions: formData
|
||||
};
|
||||
|
||||
console.log("Form Data:", data);
|
||||
console.log("CSRF Token:", csrfToken);
|
||||
|
||||
fetch("/forms", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-CSRF-TOKEN": csrfToken,
|
||||
"X-CSRF-TOKEN": csrfToken
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error("Network response was not ok");
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((result) => {
|
||||
console.log("Server Response:", result);
|
||||
if (result.success) {
|
||||
alert("Form saved successfully!");
|
||||
Swal.fire({
|
||||
title: 'Success!',
|
||||
text: 'Form saved successfully.',
|
||||
icon: 'success',
|
||||
confirmButtonText: 'OK'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
window.location.href = "/forms";
|
||||
}
|
||||
});
|
||||
} else {
|
||||
alert("Failed to save form.");
|
||||
Swal.fire({
|
||||
title: 'Error!',
|
||||
text: 'Failed to save form.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
|
@ -374,6 +189,12 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
window.addNewQuestion = addNewQuestion;
|
||||
window.deleteQuestion = deleteQuestion;
|
||||
window.addOption = addOption;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
{{-- <!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
|
@ -98,4 +98,121 @@
|
|||
<script src={{ asset('js/script.js') }}></script>
|
||||
</body>
|
||||
|
||||
</html> --}}
|
||||
|
||||
|
||||
|
||||
<!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') }} />
|
||||
<script src="https://cdn.jsdelivr.net/npm/alpinejs@2.8.2/dist/alpine.min.js" defer></script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
|
||||
<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 style="background-color: #f4f4f9;" >
|
||||
<nav class="bg-white p-4 shadow-sm">
|
||||
<div class="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>
|
||||
<br><br>
|
||||
<div style="background-color: #f4f4f9; 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-4 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>
|
||||
<option value="text">Text</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">
|
||||
<!-- Options or text input will be dynamically added here -->
|
||||
</div>
|
||||
<button class="btn btn-secondary add-option-btn" 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>
|
||||
<label class="ml-3">
|
||||
<input type="checkbox" class="required-checkbox"> Required
|
||||
</label>
|
||||
</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: #f4f4f9;" class="btnsub">
|
||||
<span>
|
||||
<button type="submit" name="save" value="save" onclick="saveForm()"
|
||||
class="btnsave btn btn-secondary">
|
||||
Save
|
||||
</button>
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<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>
|
||||
<script src="https://cdn.jsdelivr.net/npm/alpinejs@2.8.2/dist/alpine.min.js" defer></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
@ -60,15 +60,11 @@
|
|||
@foreach ($questions as $index => $question)
|
||||
<div class="question mb-4 p-3 border rounded bg-light" data-index="{{ $index }}">
|
||||
<div class="form-group">
|
||||
<select class="form-control question-type" id="question-type-{{ $index }}"
|
||||
name="questions[{{ $index }}][type]">
|
||||
<option value="multiple_choice"
|
||||
{{ $question->type === 'multiple_choice' ? 'selected' : '' }}>Multiple Choice
|
||||
</option>
|
||||
<option value="checkbox" {{ $question->type === 'checkbox' ? 'selected' : '' }}>
|
||||
Checkbox</option>
|
||||
<option value="dropdown" {{ $question->type === 'dropdown' ? 'selected' : '' }}>
|
||||
Dropdown</option>
|
||||
<select class="form-control question-type" id="question-type-{{ $index }}" name="questions[{{ $index }}][type]">
|
||||
<option value="multiple_choice" {{ $question->type === 'multiple_choice' ? 'selected' : '' }}>Multiple Choice</option>
|
||||
<option value="checkbox" {{ $question->type === 'checkbox' ? 'selected' : '' }}>Checkbox</option>
|
||||
<option value="dropdown" {{ $question->type === 'dropdown' ? 'selected' : '' }}>Dropdown</option>
|
||||
<option value="text" {{ $question->type === 'text' ? 'selected' : '' }}>Text</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -76,24 +72,25 @@
|
|||
name="questions[{{ $index }}][text]" class="form-control question-input"
|
||||
value="{{ $question->question_text }}" required>
|
||||
</div>
|
||||
<div class="form-group options-container">
|
||||
<div class="form-group form-check">
|
||||
<input type="checkbox" id="question-required-{{ $index }}"
|
||||
name="questions[{{ $index }}][required]" class="form-check-input"
|
||||
{{ $question->required ? 'checked' : '' }}>
|
||||
<label for="question-required-{{ $index }}" class="form-check-label">Required</label>
|
||||
</div>
|
||||
<div class="form-group options-container" style="{{ $question->type === 'text' ? 'display:none;' : '' }}">
|
||||
<label>Options</label>
|
||||
@if (is_array($question->options))
|
||||
@foreach ($question->options as $optionIndex => $option)
|
||||
<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 }}">
|
||||
<span class="delete-option ml-2 text-danger" onclick="deleteOption(this)"
|
||||
style="cursor: pointer;">✕</span>
|
||||
<input type="text" 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>
|
||||
@endforeach
|
||||
@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" />
|
||||
<img src="{{ asset('images/bin.png') }}" alt="" width="20px" height="20px" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -106,7 +103,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -142,23 +138,30 @@
|
|||
const questionHtml = `
|
||||
<div class="question mb-4 p-3 border rounded bg-light" data-index="${questionIndex}">
|
||||
<div class="form-group">
|
||||
<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]" onchange="handleQuestionTypeChange(this)">
|
||||
<option value="multiple_choice">Multiple Choice</option>
|
||||
<option value="checkbox">Checkbox</option>
|
||||
<option value="dropdown">Dropdown</option>
|
||||
<option value="text">Text</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="text" id="question-text-${questionIndex}" name="questions[${questionIndex}][text]" class="form-control question-input" placeholder="Type your question here" required>
|
||||
</div>
|
||||
<div class="form-group form-check">
|
||||
<input type="checkbox" id="question-required-{{ $index }}"
|
||||
name="questions[{{ $index }}][required]" class="form-check-input"
|
||||
{{ $question->required ? 'checked' : '' }}>
|
||||
<label for="question-required-{{ $index }}" class="form-check-label">Required</label>
|
||||
</div>
|
||||
<div class="form-group options-container">
|
||||
<label>Options</label>
|
||||
<button type="button" class="btn btn-secondary" onclick="addOption(this)">Add Option</button>
|
||||
</div>
|
||||
<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);
|
||||
|
@ -167,9 +170,35 @@
|
|||
|
||||
function deleteQuestion(button) {
|
||||
$(button).closest('.question').remove();
|
||||
updateQuestionIndices();
|
||||
updateAddButtonPosition();
|
||||
}
|
||||
|
||||
function updateQuestionIndices() {
|
||||
$('#questions-section .question').each((index, element) => {
|
||||
$(element).attr('data-index', index);
|
||||
$(element).find('.question-type').attr('name', `questions[${index}][type]`);
|
||||
$(element).find('.question-input').attr('name', `questions[${index}][text]`);
|
||||
$(element).find('.question-input').attr('id', `question-text-${index}`);
|
||||
$(element).find('.form-check-input').attr('name', `questions[${index}][required]`);
|
||||
$(element).find('.form-check-input').attr('id', `question-required-${index}`);
|
||||
$(element).find('.options-container').find('.option-input').each((optionIndex, optionElement) => {
|
||||
$(optionElement).attr('name', `questions[${index}][options][${optionIndex}]`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function handleQuestionTypeChange(selectElement) {
|
||||
const selectedType = $(selectElement).val();
|
||||
const optionsContainer = $(selectElement).closest('.question').find('.options-container');
|
||||
|
||||
if (selectedType === 'text') {
|
||||
optionsContainer.hide();
|
||||
} else {
|
||||
optionsContainer.show();
|
||||
}
|
||||
}
|
||||
|
||||
function updateAddButtonPosition() {
|
||||
const questions = document.querySelectorAll("#questions-section .question");
|
||||
const sidebar = document.getElementById("moveableDiv");
|
||||
|
@ -194,21 +223,32 @@
|
|||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$('#profileMenuButton').on('click', function() {
|
||||
$(document).ready(function () {
|
||||
$('#profileMenuButton').click(function () {
|
||||
$('#profileMenu').toggleClass('hidden');
|
||||
});
|
||||
|
||||
$(document).on('click', function(e) {
|
||||
if (!$(e.target).closest('#profileMenuButton').length && !$(e.target).closest(
|
||||
'#profileMenu').length) {
|
||||
$(document).click(function (event) {
|
||||
if (!$(event.target).closest('#profileMenuButton, #profileMenu').length) {
|
||||
$('#profileMenu').addClass('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
$('.question-type').each((index, element) => {
|
||||
handleQuestionTypeChange(element);
|
||||
});
|
||||
|
||||
updateAddButtonPosition();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -74,9 +74,11 @@
|
|||
<th
|
||||
class="py-4 px-6 border-b border-gray-200 text-left text-sm font-semibold text-gray-600">
|
||||
Responses</th>
|
||||
<th
|
||||
class="py-4 px-6 border-b border-gray-200 text-left text-sm font-semibold text-gray-600">
|
||||
Actions</th>
|
||||
<th class="py-4 px-6 border-b border-gray-200 text-left text-sm font-semibold text-gray-600">
|
||||
Status</th>
|
||||
<th></th>
|
||||
<th>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -93,11 +95,20 @@
|
|||
<a href="{{ route('responses.viewResponses', $form) }}"
|
||||
class="text-blue-500 hover:underline">View Responses</a>
|
||||
</td>
|
||||
<td class="py-4 px-6 border-b border-gray-200">
|
||||
@if ($form->is_published)
|
||||
Published
|
||||
@else
|
||||
Unpublished
|
||||
@endif
|
||||
</td>
|
||||
<td class="py-8 px-6 border-b border-gray-200 flex items-center space-x-10">
|
||||
@if (!$form->is_published)
|
||||
<a href="{{ route('forms.edit', $form) }}"
|
||||
class="text-green-500 hover:underline">Edit</a>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<form action="{{ route('forms.destroy', $form) }}" method="POST"
|
||||
class="inline-block">
|
||||
@csrf
|
||||
|
|
|
@ -1,134 +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>Show Form - {{ $form->title }}</title>
|
||||
<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>
|
||||
<div class="form_header">
|
||||
<div class="form_header_left">
|
||||
<a href="/forms"><img src="{{ asset('images/google-form.png') }}" class="form_header_icon" height="45px" width="40px" /></a>
|
||||
<input type="text" name="title" id="form-title-nav" placeholder="Untitled Form" class="form_name" value="{{ $form->title }}" readonly />
|
||||
<img src="{{ asset('images/folder.png') }}" alt="" class="form_header_icon" height="20px" width="20px" />
|
||||
<img src="{{ asset('images/star.svg') }}" alt="" class="form_header_icon" />
|
||||
</div>
|
||||
<div class="form_header_right">
|
||||
<span><img src="{{ asset('images/palette-svgrepo-com.svg') }}" alt="pallette" height="20px" width="20px" /></span>
|
||||
<span><img src="{{ asset('images/view.png') }}" alt="eye" height="20px" width="20px" onclick="previewForm()" /></span>
|
||||
<span><img src="{{ asset('images/undo.png') }}" alt="" height="20px" width="20px" /></span>
|
||||
<span><img src="{{ asset('images/forward.png') }}" alt="" height="20px" width="20px" /></span>
|
||||
<button class="btn">Send</button>
|
||||
<span><img src="{{ asset('images/menu.png') }}" alt="menu" height="30px" width="30px" /></span>
|
||||
<span><img src="{{ asset('images/user.png') }}" alt="" height="30px" width="30px" /></span>
|
||||
</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" />
|
||||
<input type="radio" class="tab-toggle" name="tab-toggle" id="tab3" />
|
||||
|
||||
<ul class="tab-list">
|
||||
<li class="tab-item">
|
||||
<label class="tab-trigger" for="tab1"><b>Questions</b></label>
|
||||
</li>
|
||||
<li class="tab-item">
|
||||
<label class="tab-trigger" for="tab2"><b>Responses</b></label>
|
||||
</li>
|
||||
<li class="tab-item">
|
||||
<label class="tab-trigger" for="tab3"><b>Settings</b></label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<form id="publish-form" method="POST" action="{{ route('forms.update', $form) }}">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
<div class="question_form">
|
||||
<br />
|
||||
<div class="section">
|
||||
<div class="question_title_section">
|
||||
<div class="question_form_top">
|
||||
<input type="text" id="form-title" name="title" class="question_form_top_name form-control" style="color: black" placeholder="Untitled Form" value="{{ $form->title }}" readonly />
|
||||
<input type="text" name="description" id="form-description" class="question_form_top_desc" style="color: black" placeholder="Form Description" value="{{ $form->description }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="questions_section">
|
||||
@foreach ($form->questions as $index => $question)
|
||||
<div class="question">
|
||||
<select class="form-control question_type" name="questions[{{ $index }}][type]" onchange="changeQuestionType(this)" disabled>
|
||||
<option value="multiple_choice" {{ $question->type === 'multiple_choice' ? 'selected' : '' }}>Multiple Choice</option>
|
||||
<option value="checkbox" {{ $question->type === 'checkbox' ? 'selected' : '' }}>Checkbox</option>
|
||||
<option value="dropdown" {{ $question->type === 'dropdown' ? 'selected' : '' }}>Dropdown</option>
|
||||
</select>
|
||||
<input type="text" name="questions[{{ $index }}][text]" class="form-control question-input" placeholder="Type your question here" value="{{ $question->question_text }}" readonly />
|
||||
@if ($question->options)
|
||||
<div class="options-container">
|
||||
@foreach (json_decode($question->options) as $optionIndex => $option)
|
||||
<div class="option">
|
||||
<input type="text" name="questions[{{ $index }}][options][{{ $optionIndex }}]" class="form-control option-input" placeholder="Option" value="{{ $option }}" readonly />
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
<div class="btnsub">
|
||||
<span>
|
||||
<a href="{{ route('forms.edit', $form) }}" class="btnsave btn btn-secondary">Edit</a>
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<span>
|
||||
<button type="submit" name="publish" value="publish" class="btnsave btn btn-secondary">
|
||||
{{ $form->is_published ? 'Unpublish' : 'Publish' }}
|
||||
</button>
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
<span>
|
||||
<a href="/forms" class="btnsave btn btn-secondary">Return</a>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
document.querySelector('button[name="publish"]').addEventListener('click', function(event) {
|
||||
event.preventDefault();
|
||||
document.getElementById('publish-form').action = "{{ route('forms.update', $form) }}";
|
||||
document.getElementById('publish-form').submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script src="{{ asset('js/script.js') }}"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--}}
|
||||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
@ -194,6 +64,7 @@
|
|||
<option value="multiple_choice" {{ $question->type === 'multiple_choice' ? 'selected' : '' }}>Multiple Choice</option>
|
||||
<option value="checkbox" {{ $question->type === 'checkbox' ? 'selected' : '' }}>Checkbox</option>
|
||||
<option value="dropdown" {{ $question->type === 'dropdown' ? 'selected' : '' }}>Dropdown</option>
|
||||
<option value="text" {{ $question->type === 'text' ? 'selected' : '' }}>Text</option>
|
||||
</select>
|
||||
<input type="text" name="questions[{{ $index }}][text]" class="form-control question-input mb-3" placeholder="Type your question here" value="{{ $question->question_text }}" readonly />
|
||||
@if ($question->options)
|
||||
|
@ -210,9 +81,16 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="btnsub text-center mt-4">
|
||||
<span>
|
||||
<a href="{{ route('forms.index') }}" class="btnsave btn btn-secondary">Return to Forms</a>
|
||||
</span>
|
||||
<form action="{{ route('forms.publish', $form->id) }}" method="POST">
|
||||
@csrf
|
||||
@method('PATCH')
|
||||
<span><button type="submit" name="publish" value="publish" class="btnsave btn btn-secondary">
|
||||
{{ $form->is_published ? 'Unpublish' : 'Publish' }}
|
||||
</button></span>
|
||||
</form>
|
||||
|
||||
|
||||
<span><a href="{{ route('forms.index') }}" class="btnsave btn btn-secondary">Return to Forms</a></span>
|
||||
</div>
|
||||
<script src="{{ asset('js/script.js') }}"></script>
|
||||
</body>
|
||||
|
|
|
@ -1,54 +1,7 @@
|
|||
{{-- @extends('layouts.app')
|
||||
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
|
||||
@section('content')
|
||||
<div class="container mx-auto py-8">
|
||||
<h1 class="text-3xl font-semibold">{{ $form->title }}</h1>
|
||||
<p class="text-gray-700 mt-2">{{ $form->description }}</p>
|
||||
|
||||
<form action="{{ route('responses.submitForm', $form) }}" method="POST" class="mt-8">
|
||||
@csrf
|
||||
@foreach ($questions as $question)
|
||||
<div class="mt-6">
|
||||
<label class="block font-medium text-gray-800">{{ $question->question_text }}</label>
|
||||
@if ($question->type == 'multiple_choice')
|
||||
@foreach (json_decode($question->options) as $option)
|
||||
<label class="inline-flex items-center mt-2">
|
||||
<input class="form-radio text-purple-600" type="radio" name="answers[{{ $question->id }}]" value="{{ $option }}">
|
||||
<span class="ml-2 text-gray-700">{{ $option }}</span>
|
||||
</label>
|
||||
@endforeach
|
||||
@elseif($question->type == 'checkbox')
|
||||
@foreach (json_decode($question->options) as $option)
|
||||
<label class="inline-flex items-center mt-2">
|
||||
<input class="form-checkbox text-purple-600" type="checkbox" name="answers[{{ $question->id }}][]" value="{{ $option }}">
|
||||
<span class="ml-2 text-gray-700">{{ $option }}</span>
|
||||
</label>
|
||||
@endforeach
|
||||
@elseif($question->type == 'dropdown')
|
||||
<select class="form-select mt-2 block w-full p-2 border border-gray-300 rounded-md bg-white shadow-sm focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm" name="answers[{{ $question->id }}]">
|
||||
@foreach (json_decode($question->options) as $option)
|
||||
<option value="{{ $option }}">{{ $option }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@elseif($question->type == 'short_answer')
|
||||
<input type="text" name="answers[{{ $question->id }}]" class="form-input mt-2 block w-full p-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm">
|
||||
@elseif($question->type == 'long_answer')
|
||||
<textarea name="answers[{{ $question->id }}]" class="form-textarea mt-2 block w-full p-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm"></textarea>
|
||||
@endif
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
<button type="submit" class="mt-6 inline-flex items-center px-4 py-2 bg-purple-700 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-purple-800 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 focus:ring-offset-purple-200">
|
||||
Submit
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@endsection
|
||||
--}}
|
||||
|
||||
|
||||
@extends('layouts.app')
|
||||
@section('content')
|
||||
<div class="container mx-auto py-8 px-4 md:px-0">
|
||||
<div class="bg-white shadow-md rounded-lg p-6">
|
||||
|
@ -80,9 +33,7 @@
|
|||
<option value="{{ $option }}">{{ $option }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@elseif($question->type == 'short_answer')
|
||||
<input type="text" name="answers[{{ $question->id }}]" class="form-input mt-2 block w-full p-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm">
|
||||
@elseif($question->type == 'long_answer')
|
||||
@elseif($question->type == 'text')
|
||||
<textarea name="answers[{{ $question->id }}]" class="form-textarea mt-2 block w-full p-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm"></textarea>
|
||||
@endif
|
||||
</div>
|
||||
|
@ -94,4 +45,154 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.getElementById('responseForm').addEventListener('submit', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const form = event.target;
|
||||
const formData = new FormData(form);
|
||||
|
||||
fetch(form.action, {
|
||||
method: form.method,
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||
},
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire({
|
||||
title: 'Success!',
|
||||
text: 'Form submitted successfully.',
|
||||
icon: 'success',
|
||||
confirmButtonText: 'OK'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
window.location.href = '/forms';
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: 'Error!',
|
||||
text: 'Failed to submit form.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
Swal.fire({
|
||||
title: 'Error!',
|
||||
text: 'An error occurred while submitting the form.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endsection --}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@extends('layouts.app')
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
|
||||
@section('content')
|
||||
<div class="container mx-auto py-8 px-4 md:px-0">
|
||||
<div class="bg-white shadow-md rounded-lg p-6">
|
||||
<h1 class="text-3xl font-semibold text-gray-900">{{ $form->title }}</h1>
|
||||
<p class="text-gray-600 mt-2">{{ $form->description }}</p>
|
||||
|
||||
<form id="responseForm" action="{{ route('responses.submitForm', $form) }}" method="POST" class="mt-8">
|
||||
@csrf
|
||||
@foreach ($questions as $question)
|
||||
<div class="mt-6">
|
||||
<label class="block font-medium text-base text-gray-800 mb-2">{{ $question->question_text }}</label>
|
||||
@if ($question->type == 'multiple_choice')
|
||||
@foreach (json_decode($question->options) as $option)
|
||||
<label class="flex items-center mt-2">
|
||||
<input class="form-radio text-base text-purple-600 h-4 w-4" type="radio" name="answers[{{ $question->id }}]" value="{{ $option }}">
|
||||
<span class="ml-2 text-gray-700">{{ $option }}</span>
|
||||
</label>
|
||||
@endforeach
|
||||
@elseif($question->type == 'checkbox')
|
||||
@foreach (json_decode($question->options) as $option)
|
||||
<label class="flex items-center mt-2">
|
||||
<input class="form-checkbox text-purple-600 h-4 w-4" type="checkbox" name="answers[{{ $question->id }}][]" value="{{ $option }}">
|
||||
<span class="ml-2 text-gray-700">{{ $option }}</span>
|
||||
</label>
|
||||
@endforeach
|
||||
@elseif($question->type == 'dropdown')
|
||||
<select class="form-select mt-2 block w-full p-2 border border-gray-300 rounded-md bg-white shadow-sm focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm" name="answers[{{ $question->id }}]">
|
||||
@foreach (json_decode($question->options) as $option)
|
||||
<option value="{{ $option }}">{{ $option }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@elseif($question->type == 'text')
|
||||
<textarea name="answers[{{ $question->id }}]" class="form-textarea mt-2 block w-full p-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm"></textarea>
|
||||
@endif
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
<button type="submit" class="mt-8 w-full md:w-auto inline-flex justify-center items-center px-6 py-3 bg-purple-700 border border-transparent rounded-md font-semibold text-white text-lg uppercase tracking-widest hover:bg-purple-800 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2">
|
||||
Submit
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.getElementById('responseForm').addEventListener('submit', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const form = event.target;
|
||||
const formData = new FormData(form);
|
||||
|
||||
fetch(form.action, {
|
||||
method: form.method,
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||
},
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
Swal.fire({
|
||||
title: 'Success!',
|
||||
text: 'Form submitted successfully.',
|
||||
icon: 'success',
|
||||
confirmButtonText: 'OK'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
window.location.href = '/forms';
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: 'Error!',
|
||||
text: 'Failed to submit form.',
|
||||
icon: 'error',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
Swal.fire({
|
||||
title: 'Success!',
|
||||
text: 'Form Submitted Successfully',
|
||||
icon: 'success',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
|
|
|
@ -22,7 +22,7 @@ Route::middleware(['auth'])->group(function () {
|
|||
Route::put('/forms/{form}', [FormController::class, 'update'])->name('forms.update');
|
||||
Route::delete('/forms/{form}', [FormController::class, 'destroy'])->name('forms.destroy');
|
||||
Route::get('/forms/{form}/preview', [FormController::class, 'preview'])->name('forms.preview');
|
||||
|
||||
Route::patch('/forms/{form}/publish', [FormController::class, 'togglePublish'])->name('forms.publish');
|
||||
});
|
||||
|
||||
// Response routes
|
||||
|
|
Loading…
Reference in New Issue