diff --git a/app/Http/Controllers/FormController.php b/app/Http/Controllers/FormController.php index 5ead730..13743e3 100644 --- a/app/Http/Controllers/FormController.php +++ b/app/Http/Controllers/FormController.php @@ -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 diff --git a/app/Http/Controllers/ResponseController.php b/app/Http/Controllers/ResponseController.php index ab2fe34..c70c197 100644 --- a/app/Http/Controllers/ResponseController.php +++ b/app/Http/Controllers/ResponseController.php @@ -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.'); } + + + + + } diff --git a/database/migrations/2024_07_10_073443_create_questions_table.php b/database/migrations/2024_07_10_073443_create_questions_table.php index af395ae..16ea7b4 100644 --- a/database/migrations/2024_07_10_073443_create_questions_table.php +++ b/database/migrations/2024_07_10_073443_create_questions_table.php @@ -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(); }); diff --git a/public/js/script.js b/public/js/script.js index 9fea1f5..4c6026a 100644 --- a/public/js/script.js +++ b/public/js/script.js @@ -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 = ` -// -// ✕ -// `; -// 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 = -// ''; -// } - -// let questionCount = document.querySelectorAll(".question").length; - -// function addNewQuestion() { -// const newQuestionDiv = document.createElement("div"); -// newQuestionDiv.className = "question"; -// newQuestionDiv.innerHTML = ` -// -// -//
-// -// -// `; -// 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 = - ''; + 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 = ` + + ✕ + `; + 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 = ` -