Compare commits
No commits in common. "d391440e2a5c7efcfacfecbdc846cf014138a08c" and "d203dcaaba9287e0ce1a35307a2a8b0df49f8b2c" have entirely different histories.
d391440e2a
...
d203dcaaba
|
@ -1,7 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Models\Form;
|
use App\Models\Form;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
@ -10,23 +9,13 @@ 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()
|
||||||
{
|
{
|
||||||
$totalForms = Form::count();
|
// Get forms belonging to the authenticated user
|
||||||
$publishedForms = Form::where('is_published', true)->count();
|
$forms = Form::where('user_id', Auth::id())->get();
|
||||||
$totalResponses = Response::count();
|
return view('forms.index', compact('forms'));
|
||||||
|
|
||||||
$forms = Form::where('user_id', Auth::id())->orderBy('created_at', 'desc')->get();
|
|
||||||
return view('forms.index', [
|
|
||||||
'forms' => $forms,
|
|
||||||
'totalForms' => $totalForms,
|
|
||||||
'publishedForms' => $publishedForms,
|
|
||||||
'totalResponses' => $totalResponses,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create()
|
public function create()
|
||||||
|
@ -34,92 +23,35 @@ class FormController extends Controller
|
||||||
return view('forms.create');
|
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)
|
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'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function createWithTemplate($template)
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
|
|
||||||
switch ($template) {
|
|
||||||
case 'contact':
|
|
||||||
$data = [
|
|
||||||
'title' => 'Contact Information',
|
|
||||||
'description' => 'Template for collecting contact information.',
|
|
||||||
'questions' => [
|
|
||||||
['type' => 'text', 'question_text' => 'Name'],
|
|
||||||
['type' => 'text', 'question_text' => 'Email'],
|
|
||||||
// Add more questions as needed
|
|
||||||
],
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'rsvp':
|
|
||||||
$data = [
|
|
||||||
'title' => 'RSVP',
|
|
||||||
'description' => 'Event Address: 123 Your Street Your City, ST 12345
|
|
||||||
Contact us at (123) 456-7890 or no_reply@example.com
|
|
||||||
',
|
|
||||||
'questions' => [
|
|
||||||
['type' => 'text', 'question_text' => 'Can you attend?'],
|
|
||||||
['type' => 'text', 'question_text' => 'Number of Guests'],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'party':
|
|
||||||
$data = [
|
|
||||||
'title' => 'Party Invite',
|
|
||||||
'description' => 'Template for party invitations.',
|
|
||||||
'questions' => [
|
|
||||||
['type' => 'text', 'question_text' => 'Name'],
|
|
||||||
['type' => 'text', 'question_text' => 'RSVP Status'],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return view('forms.create', ['data' => $data]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
try {
|
|
||||||
$validatedData = $request->validate([
|
$validatedData = $request->validate([
|
||||||
'title' => 'required|string|max:255',
|
'title' => 'required|string|max:255',
|
||||||
'description' => 'nullable|string',
|
'description' => 'nullable|string',
|
||||||
'questions' => 'required|array',
|
'questions' => 'required|array',
|
||||||
'questions.*.type' => 'required|string|in:multiple_choice,checkbox,dropdown,text',
|
'questions.*.type' => 'required|string|in:multiple_choice,checkbox,dropdown,short_answer,long_answer',
|
||||||
'questions.*.text' => 'required|string',
|
'questions.*.text' => 'required|string', // This should match the key used in the JavaScript
|
||||||
'questions.*.options' => 'nullable|array',
|
'questions.*.options' => 'nullable|array',
|
||||||
'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'];
|
||||||
$form->is_published = $request->input('is_published', false);
|
$form->is_published = $request->input('is_published', false); // Default to false if not provided
|
||||||
$form->user_id = Auth::id();
|
$form->user_id = Auth::id();
|
||||||
$form->save();
|
$form->save();
|
||||||
|
|
||||||
|
@ -127,24 +59,20 @@ Contact us at (123) 456-7890 or no_reply@example.com
|
||||||
$question = new Question();
|
$question = new Question();
|
||||||
$question->form_id = $form->id;
|
$question->form_id = $form->id;
|
||||||
$question->type = $questionData['type'];
|
$question->type = $questionData['type'];
|
||||||
$question->question_text = $questionData['text'];
|
$question->question_text = $questionData['text']; // Ensure this matches the key in the validated data
|
||||||
$question->options = isset($questionData['options']) ? json_encode($questionData['options']) : null;
|
$question->options = isset($questionData['options']) ? json_encode($questionData['options']) : null;
|
||||||
$question->required = isset($questionData['required']) ? $questionData['required'] : false;
|
|
||||||
$question->save();
|
$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)
|
public function show(Form $form)
|
||||||
{
|
{
|
||||||
$form->load('questions.responses');
|
$form->load('questions.responses');
|
||||||
|
|
||||||
return view('forms.show', compact('form'));
|
return view('forms.show', compact('form'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +98,7 @@ Contact us at (123) 456-7890 or no_reply@example.com
|
||||||
'description' => 'nullable|string|max:255',
|
'description' => 'nullable|string|max:255',
|
||||||
'questions' => 'required|array',
|
'questions' => 'required|array',
|
||||||
'questions.*.id' => 'nullable|exists:questions,id',
|
'questions.*.id' => 'nullable|exists:questions,id',
|
||||||
'questions.*.type' => 'required|string|in:multiple_choice,checkbox,dropdown,text',
|
'questions.*.type' => 'required|string|in:multiple_choice,checkbox,dropdown,short_answer,long_answer',
|
||||||
'questions.*.text' => 'required|string|max:255',
|
'questions.*.text' => 'required|string|max:255',
|
||||||
'questions.*.options' => 'nullable|array',
|
'questions.*.options' => 'nullable|array',
|
||||||
'questions.*.options.*' => 'nullable|string|max:255',
|
'questions.*.options.*' => 'nullable|string|max:255',
|
||||||
|
@ -202,6 +130,7 @@ Contact us at (123) 456-7890 or no_reply@example.com
|
||||||
$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());
|
||||||
|
@ -219,8 +148,6 @@ Contact us at (123) 456-7890 or no_reply@example.com
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function destroy(Form $form)
|
public function destroy(Form $form)
|
||||||
{
|
{
|
||||||
// This will also delete all related questions and responses due to foreign key constraints
|
// This will also delete all related questions and responses due to foreign key constraints
|
||||||
|
|
|
@ -6,13 +6,21 @@ use Illuminate\Http\Request;
|
||||||
|
|
||||||
class HomeController extends Controller
|
class HomeController extends Controller
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Create a new controller instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->middleware('auth');
|
$this->middleware('auth');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the application dashboard.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\Support\Renderable
|
||||||
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
return view('forms.index');
|
return view('forms.index');
|
||||||
|
|
|
@ -17,14 +17,14 @@ class QuestionController extends Controller
|
||||||
|
|
||||||
public function store(Form $form, Request $request)
|
public function store(Form $form, Request $request)
|
||||||
{
|
{
|
||||||
|
// Validate question data
|
||||||
$validatedData = $request->validate([
|
$validatedData = $request->validate([
|
||||||
'type' => 'required|string|in:multiple_choice,checkbox,dropdown,short_answer,long_answer',
|
'type' => 'required|string|in:multiple_choice,checkbox,dropdown,short_answer,long_answer',
|
||||||
'question_text' => 'required|string',
|
'question_text' => 'required|string',
|
||||||
'options' => 'nullable|array',
|
'options' => 'nullable|array', // If needed based on question type
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Create new question for the form
|
||||||
$question = new Question();
|
$question = new Question();
|
||||||
$question->form_id = $form->id;
|
$question->form_id = $form->id;
|
||||||
$question->type = $validatedData['type'];
|
$question->type = $validatedData['type'];
|
||||||
|
@ -42,14 +42,14 @@ class QuestionController extends Controller
|
||||||
|
|
||||||
public function update(Form $form, Question $question, Request $request)
|
public function update(Form $form, Question $question, Request $request)
|
||||||
{
|
{
|
||||||
|
// Validate updated question data
|
||||||
$validatedData = $request->validate([
|
$validatedData = $request->validate([
|
||||||
'type' => 'required|string|in:multiple_choice,checkbox,dropdown,short_answer,long_answer',
|
'type' => 'required|string|in:multiple_choice,checkbox,dropdown,short_answer,long_answer',
|
||||||
'question_text' => 'required|string',
|
'question_text' => 'required|string',
|
||||||
'options' => 'nullable|array',
|
'options' => 'nullable|array', // If needed based on question type
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Update question details
|
||||||
$question->type = $validatedData['type'];
|
$question->type = $validatedData['type'];
|
||||||
$question->question_text = $validatedData['question_text'];
|
$question->question_text = $validatedData['question_text'];
|
||||||
$question->options = $validatedData['options'] ?? null;
|
$question->options = $validatedData['options'] ?? null;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Ramsey\Uuid\Uuid;
|
use Ramsey\Uuid\Uuid;
|
||||||
use App\Models\Form;
|
use App\Models\Form;
|
||||||
|
@ -22,79 +21,30 @@ class ResponseController extends Controller
|
||||||
return view('responses.index', compact('form', 'responses'));
|
return view('responses.index', compact('form', 'responses'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function showSuccess(Form $form)
|
// Display a specific response
|
||||||
{
|
|
||||||
return view('responses.success', compact('form'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function viewResponse(Form $form, $responseId)
|
public function viewResponse(Form $form, $responseId)
|
||||||
{
|
{
|
||||||
|
// Get all responses with the same response_id
|
||||||
$responses = Response::where('response_id', $responseId)
|
$responses = Response::where('response_id', $responseId)
|
||||||
->where('form_id', $form->id)
|
->where('form_id', $form->id)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
|
// Get all questions for the form
|
||||||
$questions = Question::where('form_id', $form->id)->get()->keyBy('id');
|
$questions = Question::where('form_id', $form->id)->get()->keyBy('id');
|
||||||
|
|
||||||
|
return view('responses.viewResponse', compact('form', 'responses', 'questions'));
|
||||||
$statistics = [];
|
|
||||||
foreach ($questions as $question) {
|
|
||||||
$statistics[$question->id] = [
|
|
||||||
'question_text' => $question->question_text,
|
|
||||||
'type' => $question->type,
|
|
||||||
'options' => json_decode($question->options),
|
|
||||||
'responses' => []
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($responses as $response) {
|
|
||||||
$decodedAnswers = json_decode($response->answers, true);
|
|
||||||
if (isset($decodedAnswers[$question->id])) {
|
|
||||||
$statistics[$question->id]['responses'][] = $decodedAnswers[$question->id];
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return view('responses.viewResponse', compact('form', 'responses', 'questions', 'statistics'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function viewResponses(Form $form)
|
public function viewResponses(Form $form)
|
||||||
{
|
{
|
||||||
|
// Get all responses for the form, grouped by response_id
|
||||||
$responses = Response::where('form_id', $form->id)
|
$responses = Response::where('form_id', $form->id)
|
||||||
->orderBy('submitted_at', 'desc')
|
->orderBy('submitted_at', 'desc')
|
||||||
->get()
|
->get()
|
||||||
->groupBy('response_id');
|
->groupBy('response_id');
|
||||||
|
|
||||||
|
return view('responses.viewResponses', compact('form', 'responses'));
|
||||||
$questions = Question::where('form_id', $form->id)->get()->keyBy('id');
|
|
||||||
|
|
||||||
|
|
||||||
$statistics = [];
|
|
||||||
foreach ($questions as $question) {
|
|
||||||
$statistics[$question->id] = [
|
|
||||||
'question_text' => $question->question_text,
|
|
||||||
'type' => $question->type,
|
|
||||||
'options' => json_decode($question->options, true),
|
|
||||||
'responses' => [],
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($responses as $responseGroup) {
|
|
||||||
foreach ($responseGroup as $response) {
|
|
||||||
$decodedAnswers = json_decode($response->answers, true);
|
|
||||||
if (isset($decodedAnswers[$question->id])) {
|
|
||||||
$statistics[$question->id]['responses'][] = $decodedAnswers[$question->id];
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return view('responses.viewResponses', compact('form', 'responses', 'statistics', 'questions'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function showForm(Form $form)
|
public function showForm(Form $form)
|
||||||
{
|
{
|
||||||
|
@ -108,38 +58,23 @@ class ResponseController extends Controller
|
||||||
|
|
||||||
public function submitForm(Request $request, Form $form)
|
public function submitForm(Request $request, Form $form)
|
||||||
{
|
{
|
||||||
Log::info($request->all());
|
Log::info($request->all()); // Log the entire request data for debugging
|
||||||
|
|
||||||
|
|
||||||
$questions = $form->questions;
|
|
||||||
|
|
||||||
|
|
||||||
$requiredQuestionIds = $questions->where('required', true)->pluck('id')->toArray();
|
|
||||||
|
|
||||||
|
|
||||||
|
// Validate and process form submission
|
||||||
$validatedData = $request->validate([
|
$validatedData = $request->validate([
|
||||||
'answers' => 'required|array',
|
'answers' => 'required|array',
|
||||||
'answers.*' => 'required',
|
'answers.*' => 'required',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
Log::info($validatedData); // Log the validated data for debugging
|
||||||
|
|
||||||
foreach ($requiredQuestionIds as $requiredQuestionId) {
|
// Generate a UUID for response_id
|
||||||
if (!isset($validatedData['answers'][$requiredQuestionId]) || empty($validatedData['answers'][$requiredQuestionId])) {
|
|
||||||
return redirect()->back()
|
|
||||||
->withErrors(['errors' => 'Please answer all required questions.'])
|
|
||||||
->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Log::info($validatedData);
|
|
||||||
|
|
||||||
|
|
||||||
$responseId = Uuid::uuid4()->toString();
|
$responseId = Uuid::uuid4()->toString();
|
||||||
|
|
||||||
|
// Save each question's response
|
||||||
foreach ($validatedData['answers'] as $questionId => $answer) {
|
foreach ($validatedData['answers'] as $questionId => $answer) {
|
||||||
$response = new Response();
|
$response = new Response();
|
||||||
$response->response_id = $responseId;
|
$response->response_id = $responseId; // Assign the generated UUID
|
||||||
$response->question_id = $questionId;
|
$response->question_id = $questionId;
|
||||||
$response->form_id = $form->id;
|
$response->form_id = $form->id;
|
||||||
$response->user_id = auth()->id();
|
$response->user_id = auth()->id();
|
||||||
|
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
0
database/migrations/2014_10_12_100000_create_password_reset_tokens_table.php
Executable file → Normal file
0
database/migrations/2014_10_12_100000_create_password_resets_table.php
Executable file → Normal file
0
database/migrations/2019_12_14_000001_create_personal_access_tokens_table.php
Executable file → Normal file
|
@ -14,9 +14,8 @@ return new class extends Migration
|
||||||
Schema::create('questions', function (Blueprint $table) {
|
Schema::create('questions', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->foreignId('form_id')->constrained()->onDelete('cascade');
|
$table->foreignId('form_id')->constrained()->onDelete('cascade');
|
||||||
$table->enum('type', ['multiple_choice', 'checkbox', 'dropdown', 'text']);
|
$table->enum('type', ['multiple_choice', 'checkbox', 'dropdown', 'short_answer', 'long_answer']);
|
||||||
$table->text('question_text');
|
$table->text('question_text');
|
||||||
$table->boolean('required')->default(false);
|
|
||||||
$table->json('options')->nullable(); // Store options as JSON if applicable
|
$table->json('options')->nullable(); // Store options as JSON if applicable
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,8 +5,7 @@
|
||||||
"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",
|
||||||
|
@ -890,11 +889,6 @@
|
||||||
"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",
|
||||||
|
@ -1113,14 +1107,6 @@
|
||||||
"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",
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
"vite": "^5.0.0"
|
"vite": "^5.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"sweetalert": "^2.1.2",
|
"sweetalert": "^2.1.2"
|
||||||
"toastr": "^2.1.4"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,6 @@
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
input:focus, textarea:focus, select:focus{
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#moveableDiv {
|
#moveableDiv {
|
||||||
transition: transform 1s ease;
|
transition: transform 1s ease;
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 959 B After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 623 B After Width: | Height: | Size: 623 B |
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
@ -1,3 +1,216 @@
|
||||||
|
// 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 () {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
const questionsSection = document.getElementById("questions_section");
|
const questionsSection = document.getElementById("questions_section");
|
||||||
|
|
||||||
|
@ -20,62 +233,40 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||||
updateAddButtonPosition();
|
updateAddButtonPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeQuestionType(selectElement) {
|
function changeQuestionType(select) {
|
||||||
const questionContainer = selectElement.closest(".question");
|
const questionInput = select.nextElementSibling;
|
||||||
const optionsContainer =
|
questionInput.style.display = "block";
|
||||||
questionContainer.querySelector(".options-container");
|
const optionsContainer = select.nextElementSibling.nextElementSibling;
|
||||||
const addOptionButton =
|
optionsContainer.innerHTML =
|
||||||
questionContainer.querySelector(".btn-secondary");
|
'<input type="text" class="form-control option-input" placeholder="Option 1">';
|
||||||
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;
|
let questionCount = document.querySelectorAll(".question").length;
|
||||||
|
|
||||||
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 shadow-sm">
|
<div class="question mb-4 p-3 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)">
|
||||||
<option style="border:1px solid rgb(103,58,183);" value="">Select Question Type</option>
|
<option value="">Select Question Type</option>
|
||||||
<option value="multiple_choice">Multiple Choice</option>
|
<option value="multiple_choice">Multiple Choice</option>
|
||||||
<option value="checkbox">Checkbox</option>
|
<option value="checkbox">Checkbox</option>
|
||||||
<option value="dropdown">Dropdown</option>
|
<option value="dropdown">Dropdown</option>
|
||||||
<option value="text">Text</option>
|
|
||||||
</select>
|
</select>
|
||||||
<input style="border:none; border-bottom: 2px solid rgb(103,58,183); border-radius:0" 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">
|
||||||
|
<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>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-secondary add-option-btn" onclick="addOption(this)">
|
</div>
|
||||||
|
<button class="btn btn-secondary" onclick="addOption(this)">
|
||||||
Add Option
|
Add Option
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-md" id="moveUpButton" onclick="deleteQuestion(this);">
|
<button class="btn btn-md" id="moveUpButton" onclick="deleteQuestion(this);">
|
||||||
<img src="/images/bin.png" alt="" width="20px" height="20px" />
|
<img src="/images/bin.png" alt="" width="20px" height="20px" />
|
||||||
</button>
|
</button>
|
||||||
<label class="ml-3">
|
|
||||||
<input type="checkbox" class="required-checkbox"> Required
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
questionsSection.appendChild(newQuestionDiv);
|
questionsSection.appendChild(newQuestionDiv);
|
||||||
|
@ -110,9 +301,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||||
sidebar.style.transform = `translateY(${newPosition}px)`;
|
sidebar.style.transform = `translateY(${newPosition}px)`;
|
||||||
console.log(`Moving sidebar to: ${newPosition}px`);
|
console.log(`Moving sidebar to: ${newPosition}px`);
|
||||||
} else {
|
} else {
|
||||||
sidebar.style.transform = `translateY(${
|
sidebar.style.transform = `translateY(${containerHeight - sidebarHeight}px)`;
|
||||||
containerHeight - sidebarHeight
|
|
||||||
}px)`;
|
|
||||||
console.log(`Moving sidebar to bottom of container`);
|
console.log(`Moving sidebar to bottom of container`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -123,43 +312,18 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
|
||||||
function saveForm() {
|
function saveForm() {
|
||||||
const formTitle = document.getElementById("form-title").value;
|
const formTitle = document.getElementById("form-title").value;
|
||||||
const formDescription =
|
const formDescription = document.getElementById("form-description").value;
|
||||||
document.getElementById("form-description").value;
|
|
||||||
const questions = document.querySelectorAll(".question");
|
const questions = document.querySelectorAll(".question");
|
||||||
let formData = [];
|
let formData = [];
|
||||||
|
|
||||||
console.log(questions);
|
questions.forEach((question, index) => {
|
||||||
|
|
||||||
questions.forEach((question) => {
|
|
||||||
const questionType = question.querySelector("select").value;
|
const questionType = question.querySelector("select").value;
|
||||||
const questionText =
|
const questionText = question.querySelector(".question-input").value;
|
||||||
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({
|
formData.push({
|
||||||
type: questionType,
|
type: questionType,
|
||||||
text: questionText,
|
text: questionText,
|
||||||
options: options,
|
options: options,
|
||||||
required: isRequired,
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log({
|
|
||||||
type: questionType,
|
|
||||||
text: questionText,
|
|
||||||
options: options,
|
|
||||||
required: isRequired,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -178,7 +342,8 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||||
questions: formData,
|
questions: formData,
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(data);
|
console.log("Form Data:", data);
|
||||||
|
console.log("CSRF Token:", csrfToken);
|
||||||
|
|
||||||
fetch("/forms", {
|
fetch("/forms", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
@ -188,26 +353,19 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||||
},
|
},
|
||||||
body: JSON.stringify(data),
|
body: JSON.stringify(data),
|
||||||
})
|
})
|
||||||
.then((response) => response.json())
|
.then((response) => {
|
||||||
.then((result) => {
|
if (!response.ok) {
|
||||||
if (result.success) {
|
throw new Error("Network response was not ok");
|
||||||
Swal.fire({
|
|
||||||
title: "Success!",
|
|
||||||
text: "Form saved successfully.",
|
|
||||||
icon: "success",
|
|
||||||
confirmButtonText: "OK",
|
|
||||||
}).then((result) => {
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
window.location.href = "/forms";
|
|
||||||
}
|
}
|
||||||
});
|
return response.json();
|
||||||
|
})
|
||||||
|
.then((result) => {
|
||||||
|
console.log("Server Response:", result);
|
||||||
|
if (result.success) {
|
||||||
|
alert("Form saved successfully!");
|
||||||
|
window.location.href = "/forms";
|
||||||
} else {
|
} else {
|
||||||
Swal.fire({
|
alert("Failed to save form.");
|
||||||
title: "Error!",
|
|
||||||
text: "Failed to save form.",
|
|
||||||
icon: "error",
|
|
||||||
confirmButtonText: "OK",
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
@ -223,12 +381,36 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||||
window.changeQuestionType = changeQuestionType;
|
window.changeQuestionType = changeQuestionType;
|
||||||
window.saveForm = saveForm;
|
window.saveForm = saveForm;
|
||||||
|
|
||||||
// document.getElementById("add-question-button").addEventListener("click", addNewQuestion);
|
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 = [];
|
||||||
|
|
||||||
document
|
questions.forEach((question) => {
|
||||||
.getElementById("questions_section")
|
const questionType = question.querySelector("select").value;
|
||||||
.addEventListener("DOMNodeInserted", updateAddButtonPosition);
|
const questionText = question.querySelector(".question-input").value;
|
||||||
document
|
const options = Array.from(question.querySelectorAll(".option-input")).map((input) => input.value);
|
||||||
.getElementById("questions_section")
|
formData.push({
|
||||||
.addEventListener("DOMNodeRemoved", updateAddButtonPosition);
|
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("DOMNodeRemoved", updateAddButtonPosition);
|
||||||
|
});
|
||||||
|
|
||||||
|
|