Compare commits
7 Commits
d391440e2a
...
2ce4691231
Author | SHA1 | Date |
---|---|---|
yash | 2ce4691231 | |
yash | c4c52ac0af | |
Yash | b6b8642496 | |
Yash | f83295fdfd | |
Yash | d4ad6e9a47 | |
Yash | 87e0486962 | |
yash | 93916d6cde |
|
@ -1,7 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Models\Form;
|
use App\Models\Form;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
@ -104,41 +104,42 @@ Contact us at (123) 456-7890 or no_reply@example.com
|
||||||
|
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
|
$validatedData = $request->validate([
|
||||||
|
'title' => 'required|string|max:255',
|
||||||
|
'description' => 'nullable|string',
|
||||||
|
'questions' => 'required|array',
|
||||||
|
'questions.*.type' => 'required|string|in:multiple_choice,checkbox,dropdown,text',
|
||||||
|
'questions.*.text' => 'required|string',
|
||||||
|
'questions.*.options' => 'nullable|array',
|
||||||
|
'questions.*.required' => 'boolean',
|
||||||
|
]);
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$validatedData = $request->validate([
|
$form = Form::create([
|
||||||
'title' => 'required|string|max:255',
|
'title' => $validatedData['title'],
|
||||||
'description' => 'nullable|string',
|
'description' => $validatedData['description'],
|
||||||
'questions' => 'required|array',
|
'user_id' => Auth::id(),
|
||||||
'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);
|
|
||||||
$form->user_id = Auth::id();
|
|
||||||
$form->save();
|
|
||||||
|
|
||||||
foreach ($validatedData['questions'] as $questionData) {
|
foreach ($validatedData['questions'] as $questionData) {
|
||||||
$question = new Question();
|
$question = new Question([
|
||||||
$question->form_id = $form->id;
|
'form_id' => $form->id,
|
||||||
$question->type = $questionData['type'];
|
'type' => $questionData['type'],
|
||||||
$question->question_text = $questionData['text'];
|
'question_text' => $questionData['text'],
|
||||||
$question->options = isset($questionData['options']) ? json_encode($questionData['options']) : null;
|
'options' => json_encode($questionData['options'] ?? []),
|
||||||
$question->required = isset($questionData['required']) ? $questionData['required'] : false;
|
'required' => $questionData['required'],
|
||||||
|
]);
|
||||||
$question->save();
|
$question->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
return response()->json(['success' => true, 'message' => 'Form saved successfully.']);
|
||||||
return response()->json(['success' => true, 'form_id' => $form->id]);
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
Log::error('Error saving form: ' . $e->getMessage(), ['exception' => $e]);
|
DB::rollBack();
|
||||||
return response()->json(['success' => false, 'message' => 'Error saving form'], 500);
|
Log::error('Error saving form: ' . $e->getMessage());
|
||||||
|
return response()->json(['success' => false, 'message' => 'Failed to save form.']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,15 +157,22 @@ Contact us at (123) 456-7890 or no_reply@example.com
|
||||||
|
|
||||||
|
|
||||||
public function update(Request $request, Form $form)
|
public function update(Request $request, Form $form)
|
||||||
{
|
{
|
||||||
if ($request->has('publish')) {
|
try {
|
||||||
$form->is_published = !$form->is_published;
|
// Normalize the 'required' field to boolean
|
||||||
$form->save();
|
if ($request->has('questions')) {
|
||||||
|
$questions = $request->input('questions');
|
||||||
return redirect()->route('forms.show', $form);
|
foreach ($questions as $index => $question) {
|
||||||
|
if (isset($question['required']) && $question['required'] === 'on') {
|
||||||
|
$questions[$index]['required'] = true;
|
||||||
|
} else {
|
||||||
|
$questions[$index]['required'] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$request->merge(['questions' => $questions]);
|
||||||
}
|
}
|
||||||
Log::info('Incoming request data: ', $request->all());
|
|
||||||
|
|
||||||
|
// Validate the request
|
||||||
$validatedData = $request->validate([
|
$validatedData = $request->validate([
|
||||||
'title' => 'required|string|max:255',
|
'title' => 'required|string|max:255',
|
||||||
'description' => 'nullable|string|max:255',
|
'description' => 'nullable|string|max:255',
|
||||||
|
@ -174,50 +182,38 @@ Contact us at (123) 456-7890 or no_reply@example.com
|
||||||
'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',
|
||||||
|
'questions.*.required' => 'boolean',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Log::info('Validated data: ', $validatedData);
|
// Update form
|
||||||
|
|
||||||
$form->update([
|
$form->update([
|
||||||
'title' => $validatedData['title'],
|
'title' => $validatedData['title'],
|
||||||
'description' => $validatedData['description'],
|
'description' => $validatedData['description'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$existingQuestionIds = [];
|
// Clear existing questions
|
||||||
|
$form->questions()->delete();
|
||||||
|
|
||||||
|
// Create or update questions
|
||||||
foreach ($validatedData['questions'] as $questionData) {
|
foreach ($validatedData['questions'] as $questionData) {
|
||||||
if (isset($questionData['id'])) {
|
$question = new Question([
|
||||||
$question = Question::find($questionData['id']);
|
'form_id' => $form->id,
|
||||||
} else {
|
'type' => $questionData['type'],
|
||||||
$question = new Question();
|
'question_text' => $questionData['text'],
|
||||||
$question->form_id = $form->id;
|
'options' => json_encode($questionData['options'] ?? []),
|
||||||
}
|
'required' => $questionData['required'],
|
||||||
|
]);
|
||||||
$question->type = $questionData['type'];
|
|
||||||
$question->question_text = $questionData['text'];
|
|
||||||
$question->options = isset($questionData['options']) ? json_encode($questionData['options']) : json_encode([]);
|
|
||||||
$question->save();
|
$question->save();
|
||||||
|
|
||||||
Log::info('Saved question: ', $question->toArray());
|
|
||||||
|
|
||||||
$existingQuestionIds[] = $question->id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$form->questions()->whereNotIn('id', $existingQuestionIds)->delete();
|
DB::commit();
|
||||||
|
|
||||||
Log::info('Remaining questions: ', $form->questions()->get()->toArray());
|
|
||||||
|
|
||||||
return redirect()->route('forms.show', $form)->with('success', 'Form updated successfully.');
|
return redirect()->route('forms.show', $form)->with('success', 'Form updated successfully.');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
Log::error('Error updating form: ' . $e->getMessage());
|
||||||
|
return back()->withErrors(['error' => 'An error occurred while updating the form. Please try again.'])->withInput();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,33 +31,27 @@ class ResponseController extends Controller
|
||||||
|
|
||||||
public function viewResponse(Form $form, $responseId)
|
public function viewResponse(Form $form, $responseId)
|
||||||
{
|
{
|
||||||
|
|
||||||
$responses = Response::where('response_id', $responseId)
|
$responses = Response::where('response_id', $responseId)
|
||||||
->where('form_id', $form->id)
|
->where('form_id', $form->id)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
|
if ($responses->isEmpty()) {
|
||||||
$questions = Question::where('form_id', $form->id)->get()->keyBy('id');
|
abort(404, 'Response not found');
|
||||||
|
|
||||||
|
|
||||||
$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'));
|
$formSnapshot = json_decode($responses->first()->form_snapshot, true);
|
||||||
|
|
||||||
|
if (is_null($formSnapshot) || !isset($formSnapshot['questions'])) {
|
||||||
|
Log::error('Form snapshot is null or does not contain questions', [
|
||||||
|
'response_id' => $responseId,
|
||||||
|
'form_snapshot' => $responses->first()->form_snapshot
|
||||||
|
]);
|
||||||
|
abort(500, 'Form snapshot is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
$questions = collect($formSnapshot['questions'])->keyBy('id');
|
||||||
|
|
||||||
|
return view('responses.viewResponse', compact('form', 'responses', 'questions'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,34 +102,39 @@ class ResponseController extends Controller
|
||||||
|
|
||||||
public function submitForm(Request $request, Form $form)
|
public function submitForm(Request $request, Form $form)
|
||||||
{
|
{
|
||||||
Log::info($request->all());
|
Log::info('Form submission started', $request->all());
|
||||||
|
|
||||||
|
|
||||||
$questions = $form->questions;
|
$questions = $form->questions;
|
||||||
|
|
||||||
|
|
||||||
$requiredQuestionIds = $questions->where('required', true)->pluck('id')->toArray();
|
$requiredQuestionIds = $questions->where('required', true)->pluck('id')->toArray();
|
||||||
|
|
||||||
|
|
||||||
$validatedData = $request->validate([
|
$validatedData = $request->validate([
|
||||||
'answers' => 'required|array',
|
'answers' => 'array',
|
||||||
'answers.*' => 'required',
|
'answers.*' => '',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
foreach ($requiredQuestionIds as $requiredQuestionId) {
|
foreach ($requiredQuestionIds as $requiredQuestionId) {
|
||||||
if (!array_key_exists($requiredQuestionId, $validatedData['answers'])) {
|
if (!isset($validatedData['answers'][$requiredQuestionId]) || empty($validatedData['answers'][$requiredQuestionId])) {
|
||||||
return redirect()->back()
|
return response()->json(['success' => false, 'message' => 'Please answer all required questions.']);
|
||||||
->withErrors(['errors' => 'Please answer all required questions.'])
|
|
||||||
->withInput();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::info($validatedData);
|
Log::info('Validation passed', $validatedData);
|
||||||
|
|
||||||
|
|
||||||
$responseId = Uuid::uuid4()->toString();
|
$responseId = Uuid::uuid4()->toString();
|
||||||
|
|
||||||
|
$formSnapshot = [
|
||||||
|
'title' => $form->title,
|
||||||
|
'description' => $form->description,
|
||||||
|
'questions' => $questions->map(function ($question) {
|
||||||
|
return [
|
||||||
|
'id' => $question->id,
|
||||||
|
'question_text' => $question->question_text,
|
||||||
|
'type' => $question->type,
|
||||||
|
'options' => $question->options,
|
||||||
|
];
|
||||||
|
})->toArray(),
|
||||||
|
];
|
||||||
|
|
||||||
foreach ($validatedData['answers'] as $questionId => $answer) {
|
foreach ($validatedData['answers'] as $questionId => $answer) {
|
||||||
$response = new Response();
|
$response = new Response();
|
||||||
|
@ -145,10 +144,12 @@ class ResponseController extends Controller
|
||||||
$response->user_id = auth()->id();
|
$response->user_id = auth()->id();
|
||||||
$response->answers = json_encode($answer);
|
$response->answers = json_encode($answer);
|
||||||
$response->submitted_at = now();
|
$response->submitted_at = now();
|
||||||
|
$response->form_snapshot = json_encode($formSnapshot);
|
||||||
$response->save();
|
$response->save();
|
||||||
|
|
||||||
|
Log::info('Response saved', $response->toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect()->route('responses.showForm', $form)
|
return response()->json(['success' => true, 'message' => 'Response submitted successfully.']);
|
||||||
->with('success', 'Response submitted successfully.');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,21 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
class Question extends Model
|
class Question extends Model
|
||||||
{
|
{
|
||||||
|
use SoftDeletes;
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
protected $fillable = ['form_id', 'user_id', 'submitted_at', 'answers'];
|
protected $fillable = ['form_id', 'type', 'question_text', 'options', 'required'];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'answers' => 'array',
|
|
||||||
'options' => 'array',
|
'options' => 'array',
|
||||||
|
'required' => 'boolean',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function getOptionsAttribute($value)
|
|
||||||
{
|
|
||||||
return json_decode($value, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function form()
|
public function form()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Form::class);
|
return $this->belongsTo(Form::class);
|
||||||
|
|
|
@ -8,7 +8,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||||
class Response extends Model
|
class Response extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
protected $fillable = ['form_id', 'user_id', 'answers'];
|
protected $fillable = ['form_id', 'user_id', 'response_id', 'question_id', 'answers', 'submitted_at', 'form_snapshot'];
|
||||||
|
|
||||||
// Define relationships
|
// Define relationships
|
||||||
public function form()
|
public function form()
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('questions', function (Blueprint $table) {
|
||||||
|
$table->softDeletes();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('questions', function (Blueprint $table) {
|
||||||
|
$table->dropSoftDeletes();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('responses', function (Blueprint $table) {
|
||||||
|
$table->json('form_snapshot')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('responses', function (Blueprint $table) {
|
||||||
|
if (Schema::hasColumn('responses', 'form_snapshot')) {
|
||||||
|
$table->dropColumn('form_snapshot');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
|
@ -255,3 +255,7 @@ input:focus, textarea:focus, select:focus{
|
||||||
color: black;
|
color: black;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.active-question {
|
||||||
|
border-left: 4px solid blue;
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||||
const optionDiv = document.createElement("div");
|
const optionDiv = document.createElement("div");
|
||||||
optionDiv.className = "option";
|
optionDiv.className = "option";
|
||||||
optionDiv.innerHTML = `
|
optionDiv.innerHTML = `
|
||||||
<input type="text" class="form-control option-input" placeholder="New Option" />
|
<input type="text" class="form-control option-input mb-1" placeholder="New Option" />
|
||||||
<span class="delete-option" onclick="deleteOption(this)">✕</span>
|
<span class="delete-option" onclick="deleteOption(this)">✕</span>
|
||||||
`;
|
`;
|
||||||
optionContainer.appendChild(optionDiv);
|
optionContainer.appendChild(optionDiv);
|
||||||
|
|
|
@ -62,7 +62,7 @@
|
||||||
<option value="dropdown">Dropdown</option>
|
<option value="dropdown">Dropdown</option>
|
||||||
<option value="text">Text</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 style="border:none; border-bottom: 2px solid rgb(103,58,183); border-radius:0; color:black" 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>
|
</div>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="bg-purple-100">
|
<body class="bg-purple-100">
|
||||||
<nav class="bg-white p-1 shadow-md">
|
<nav class="bg-white p-0.5 shadow-md">
|
||||||
<div class="container mx-auto flex justify-between items-center">
|
<div class="container mx-auto flex justify-between items-center">
|
||||||
<span style="color: rgb(103,58,183)" class="text-3xl font-bold font-sans"><a href="{{ url('/') }}"
|
<span style="color: rgb(103,58,183)" class="text-3xl font-bold font-sans"><a href="{{ url('/') }}"
|
||||||
style="color: rgb(103,58,183)" class="text-3xl font-bold font-sans">LaraForms</a> - Edit</span>
|
style="color: rgb(103,58,183)" class="text-3xl font-bold font-sans">LaraForms</a> - Edit</span>
|
||||||
|
@ -59,6 +59,7 @@
|
||||||
<div id="questions-section">
|
<div id="questions-section">
|
||||||
@foreach ($questions as $index => $question)
|
@foreach ($questions as $index => $question)
|
||||||
<div class="question mb-4 p-3 border rounded bg-light" data-index="{{ $index }}">
|
<div class="question mb-4 p-3 border rounded bg-light" data-index="{{ $index }}">
|
||||||
|
<input type="hidden" name="questions[{{ $index }}][id]" value="{{ $question->id }}">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<select class="form-control question-type" id="question-type-{{ $index }}" name="questions[{{ $index }}][type]">
|
<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="multiple_choice" {{ $question->type === 'multiple_choice' ? 'selected' : '' }}>Multiple Choice</option>
|
||||||
|
@ -88,7 +89,9 @@
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
@endif
|
@endif
|
||||||
<button type="button" class="btn btn-secondary" onclick="addOption(this)">Add Option</button>
|
</div>
|
||||||
|
<div class="d-flex align-items-center mt-2">
|
||||||
|
<button type="button" class="btn btn-secondary mr-2" onclick="addOption(this)">Add Option</button>
|
||||||
<button class="btn btn-md" id="moveUpButton" onclick="deleteQuestion(this);">
|
<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>
|
</button>
|
||||||
|
@ -111,7 +114,7 @@
|
||||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
function addOption(button) {
|
function addOption(button) {
|
||||||
const optionsContainer = $(button).closest('.options-container');
|
const optionsContainer = $(button).closest('.question').find('.options-container');
|
||||||
const optionIndex = optionsContainer.find('.option').length;
|
const optionIndex = optionsContainer.find('.option').length;
|
||||||
const questionIndex = optionsContainer.closest('.question').data('index');
|
const questionIndex = optionsContainer.closest('.question').data('index');
|
||||||
|
|
||||||
|
@ -137,6 +140,7 @@
|
||||||
|
|
||||||
const questionHtml = `
|
const questionHtml = `
|
||||||
<div class="question mb-4 p-3 border rounded bg-light" data-index="${questionIndex}">
|
<div class="question mb-4 p-3 border rounded bg-light" data-index="${questionIndex}">
|
||||||
|
<input type="hidden" name="questions[${questionIndex}][id]" value="">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<select class="form-control question-type" id="question-type-${questionIndex}" name="questions[${questionIndex}][type]" onchange="handleQuestionTypeChange(this)">
|
<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="multiple_choice">Multiple Choice</option>
|
||||||
|
@ -149,14 +153,15 @@
|
||||||
<input type="text" id="question-text-${questionIndex}" name="questions[${questionIndex}][text]" class="form-control question-input" placeholder="Type your question here" required>
|
<input type="text" id="question-text-${questionIndex}" name="questions[${questionIndex}][text]" class="form-control question-input" placeholder="Type your question here" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group form-check">
|
<div class="form-group form-check">
|
||||||
<input type="checkbox" id="question-required-{{ $index }}"
|
<input type="checkbox" id="question-required-${questionIndex}"
|
||||||
name="questions[{{ $index }}][required]" class="form-check-input"
|
name="questions[${questionIndex}][required]" class="form-check-input">
|
||||||
{{ $question->required ? 'checked' : '' }}>
|
<label for="question-required-${questionIndex}" class="form-check-label">Required</label>
|
||||||
<label for="question-required-{{ $index }}" class="form-check-label">Required</label>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group options-container">
|
<div class="form-group options-container">
|
||||||
<label>Options</label>
|
<label>Options</label>
|
||||||
<button type="button" class="btn btn-secondary" onclick="addOption(this)">Add Option</button>
|
</div>
|
||||||
|
<div class="d-flex align-items-center mt-2">
|
||||||
|
<button type="button" class="btn btn-secondary mr-2" onclick="addOption(this)">Add Option</button>
|
||||||
<button class="btn btn-md" id="moveUpButton" onclick="deleteQuestion(this);">
|
<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>
|
</button>
|
||||||
|
@ -239,16 +244,14 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
updateAddButtonPosition();
|
updateAddButtonPosition();
|
||||||
|
|
||||||
|
$('#edit-form').on('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
updateQuestionIndices();
|
||||||
|
this.submit();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<!DOCTYPE html>
|
{{-- <!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
|
@ -9,10 +9,6 @@
|
||||||
<link href="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/css/toastr.min.css" rel="stylesheet" />
|
<link href="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/css/toastr.min.css" rel="stylesheet" />
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
|
||||||
<style>
|
<style>
|
||||||
.dropdown:hover .dropdown-menu {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shadow-custom {
|
.shadow-custom {
|
||||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||||
}
|
}
|
||||||
|
@ -136,6 +132,11 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
document.getElementById('profileMenuButton').addEventListener('click', function() {
|
||||||
|
var menu = document.getElementById('profileMenu');
|
||||||
|
menu.classList.toggle('hidden');
|
||||||
|
});
|
||||||
|
|
||||||
function handle() {
|
function handle() {
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
title: 'You cannot edit a published form',
|
title: 'You cannot edit a published form',
|
||||||
|
@ -154,4 +155,156 @@
|
||||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/js/toastr.min.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/js/toastr.min.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
</html> --}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Forms</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||||
|
<link href="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/css/toastr.min.css" rel="stylesheet" />
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
|
||||||
|
<style>
|
||||||
|
.shadow-custom {
|
||||||
|
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="bg-gray-100">
|
||||||
|
<nav class="bg-white p-4 shadow-lg">
|
||||||
|
<div class="container mx-auto flex justify-between items-center">
|
||||||
|
<a href="{{ url('/') }}" class="text-3xl font-bold font-sans" style="color: rgb(103,58,183)">LaraForms</a>
|
||||||
|
<div class="relative dropdown">
|
||||||
|
<button id="profileMenuButton" class="flex items-center focus:outline-none">
|
||||||
|
<img src="{{ asset('images/user.png') }}" alt="Profile" class="w-10 h-10 rounded-full border-2 border-white">
|
||||||
|
</button>
|
||||||
|
<div id="profileMenu" class="dropdown-menu hidden absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg py-2">
|
||||||
|
<form method="POST" action="{{ route('logout') }}">
|
||||||
|
@csrf
|
||||||
|
<button type="submit" class="block px-4 py-2 text-gray-700 hover:bg-gray-200 w-full text-left">
|
||||||
|
Logout
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="container mx-auto mt-10 px-4">
|
||||||
|
@if (session('success'))
|
||||||
|
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-2 rounded relative mt-4" role="alert">
|
||||||
|
<span class="block sm:inline">{{ session('success') }}</span>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@if (session('delete'))
|
||||||
|
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-2 rounded relative mt-4" role="alert">
|
||||||
|
<span class="block sm:inline">{{ session('delete') }}</span>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="flex flex-wrap justify-between mb-6 items-center space-y-4 lg:space-y-0 lg:space-x-4">
|
||||||
|
<a href="{{ route('forms.create') }}"
|
||||||
|
class="inline-block px-6 py-3 text-white font-semibold rounded-md shadow bg-purple-700 hover:bg-purple-900 transition duration-200">
|
||||||
|
Start a new form
|
||||||
|
</a>
|
||||||
|
<a class="block max-w-md w-full lg:w-1/4 p-5 bg-white border border-gray-200 rounded-lg shadow">
|
||||||
|
<h5 class="mb-2 text-gray-800 text-xl font-bold">Total Forms Created</h5>
|
||||||
|
<p class="font-normal text-gray-700">{{ $totalForms }}</p>
|
||||||
|
</a>
|
||||||
|
<a class="block max-w-md w-full lg:w-1/4 p-5 bg-white border border-gray-200 rounded-lg shadow">
|
||||||
|
<h5 class="mb-2 text-gray-800 text-xl font-bold">Total Forms Published</h5>
|
||||||
|
<p class="font-normal text-gray-700">{{ $publishedForms }}</p>
|
||||||
|
</a>
|
||||||
|
<a class="block max-w-md w-full lg:w-1/4 p-5 bg-white border border-gray-200 rounded-lg shadow">
|
||||||
|
<h5 class="mb-2 text-gray-800 text-xl font-bold">Total Responses Received</h5>
|
||||||
|
<p class="font-normal text-gray-700">{{ $totalResponses }}</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<div class="mt-6">
|
||||||
|
<h2 class="text-3xl font-semibold text-gray-800 font-sans">Recent Forms</h2>
|
||||||
|
<div class="shadow-custom rounded-lg p-6 bg-gray-100 mt-4">
|
||||||
|
@if ($forms->isEmpty())
|
||||||
|
<p class="text-gray-600 text-center">No forms available.</p>
|
||||||
|
@else
|
||||||
|
<div class="overflow-x-auto">
|
||||||
|
<table class="min-w-full bg-white rounded-md">
|
||||||
|
<thead class="bg-gray-100">
|
||||||
|
<tr>
|
||||||
|
<th class="py-4 px-6 border-b border-gray-200 text-left text-sm font-semibold text-gray-600">Form Title</th>
|
||||||
|
<th class="py-4 px-6 border-b border-gray-200 text-left text-sm font-semibold text-gray-600">Created At</th>
|
||||||
|
<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">Status</th>
|
||||||
|
<th class="py-4 px-6 border-b border-gray-200"></th>
|
||||||
|
<th class="py-4 px-6 border-b border-gray-200"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach ($forms as $form)
|
||||||
|
<tr class="hover:bg-gray-50 transition duration-150">
|
||||||
|
<td class="py-4 px-6 border-b border-gray-200">
|
||||||
|
<a href="{{ route('forms.show', $form) }}" class="text-blue-600 font-semibold hover:underline">{{ $form->title }}</a>
|
||||||
|
<p class="text-gray-600">{{ $form->description }}</p>
|
||||||
|
</td>
|
||||||
|
<td class="py-4 px-6 border-b border-gray-200">{{ $form->created_at->format('M d, Y') }}</td>
|
||||||
|
<td class="py-4 px-6 border-b border-gray-200">
|
||||||
|
<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-4">
|
||||||
|
@if (!$form->is_published)
|
||||||
|
<a href="{{ route('forms.edit', $form) }}" class="text-green-500 hover:underline">Edit</a>
|
||||||
|
@else
|
||||||
|
<a href="#" class="text-gray-500" id="formd" onclick="handle()">Edit</a>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td class="border-b border-gray-200">
|
||||||
|
<form action="{{ route('forms.destroy', $form) }}" method="POST" class="inline-block">
|
||||||
|
@csrf
|
||||||
|
@method('DELETE')
|
||||||
|
<button type="submit" class="text-red-500 hover:underline">Delete</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.getElementById('profileMenuButton').addEventListener('click', function () {
|
||||||
|
var menu = document.getElementById('profileMenu');
|
||||||
|
menu.classList.toggle('hidden');
|
||||||
|
});
|
||||||
|
|
||||||
|
function handle() {
|
||||||
|
Swal.fire({
|
||||||
|
title: 'You cannot edit a published form',
|
||||||
|
icon: 'info',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/js/toastr.min.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -35,6 +35,16 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
@if (session('success'))
|
||||||
|
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-2 rounded relative mt-4" role="alert">
|
||||||
|
<span class="block sm:inline">{{ session('success') }}</span>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@if (session('delete'))
|
||||||
|
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-2 rounded relative mt-4" role="alert">
|
||||||
|
<span class="block sm:inline">{{ session('delete') }}</span>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
<div class="question_form bg-gray-100 p-4 rounded shadow-sm">
|
<div class="question_form bg-gray-100 p-4 rounded shadow-sm">
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="question_title_section mb-4">
|
<div class="question_title_section mb-4">
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||||
|
|
||||||
<title>{{ config('app.name', 'LaraForms') }}</title>
|
<title>{{ config('app.name', 'LaraForms') }}</title>
|
||||||
|
<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>
|
||||||
<!-- Fonts -->
|
<!-- Fonts -->
|
||||||
<link rel="dns-prefetch" href="//fonts.bunny.net">
|
<link rel="dns-prefetch" href="//fonts.bunny.net">
|
||||||
<link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet">
|
<link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet">
|
||||||
|
|
|
@ -12,7 +12,12 @@
|
||||||
@csrf
|
@csrf
|
||||||
@foreach ($questions as $question)
|
@foreach ($questions as $question)
|
||||||
<div class="mt-6">
|
<div class="mt-6">
|
||||||
<label class="block font-medium text-base text-gray-800 mb-2">{{ $question->question_text }}</label>
|
<label class="block font-medium text-base text-gray-800 mb-2">
|
||||||
|
{{ $question->question_text }}
|
||||||
|
@if ($question->required)
|
||||||
|
<span class="text-red-600">*</span>
|
||||||
|
@endif
|
||||||
|
</label>
|
||||||
@if ($question->type == 'multiple_choice')
|
@if ($question->type == 'multiple_choice')
|
||||||
@foreach (json_decode($question->options) as $option)
|
@foreach (json_decode($question->options) as $option)
|
||||||
<label class="flex items-center mt-2">
|
<label class="flex items-center mt-2">
|
||||||
|
@ -47,57 +52,72 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.getElementById('responseForm').addEventListener('submit', function(event) {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
event.preventDefault();
|
const responseForm = document.getElementById('responseForm');
|
||||||
|
responseForm.addEventListener('submit', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
const form = event.target;
|
const form = event.target;
|
||||||
const formData = new FormData(form);
|
const formData = new FormData(form);
|
||||||
|
let valid = true;
|
||||||
|
|
||||||
fetch(form.action, {
|
// @foreach ($questions as $question)
|
||||||
method: form.method,
|
// @if ($question->required)
|
||||||
headers: {
|
// const answer = formData.get('answers[{{ $question->id }}]');
|
||||||
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
// console.log('Question ID:', {{ $question->id }}, 'Answer:', answer);
|
||||||
},
|
// if (!answer || !answer.trim()) {
|
||||||
body: formData
|
// valid = false;
|
||||||
})
|
// Swal.fire({
|
||||||
.then(response => response.json())
|
// title: 'Error!',
|
||||||
.then(data => {
|
// text: 'Please answer all required questions.',
|
||||||
if (data.success) {
|
// icon: 'error',
|
||||||
Swal.fire({
|
// confirmButtonText: 'OK'
|
||||||
title: 'Success!',
|
// });
|
||||||
text: 'Form submitted successfully.',
|
// return; // Exit the function to prevent further execution
|
||||||
icon: 'success',
|
// }
|
||||||
confirmButtonText: 'OK'
|
// @endif
|
||||||
}).then((result) => {
|
// @endforeach
|
||||||
if (result.isConfirmed) {
|
|
||||||
window.location.href = '{{ route('responses.success', $form) }}';
|
if (valid) {
|
||||||
}
|
fetch(form.action, {
|
||||||
});
|
method: form.method,
|
||||||
} else {
|
headers: {
|
||||||
Swal.fire({
|
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||||
title: 'Success!',
|
},
|
||||||
text: 'Form submitted successfully.',
|
body: formData
|
||||||
icon: 'success',
|
})
|
||||||
confirmButtonText: 'OK'
|
.then(response => response.json())
|
||||||
}).then((result) => {
|
.then(data => {
|
||||||
if (result.isConfirmed) {
|
if (data.success) {
|
||||||
window.location.href = '{{ route('responses.success', $form) }}';
|
Swal.fire({
|
||||||
|
title: 'Success!',
|
||||||
|
text: 'Form submitted successfully.',
|
||||||
|
icon: 'success',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
window.location.href = '{{ route('responses.success', $form) }}';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Error!',
|
||||||
|
text: 'Error submitting. Answer all required questions',
|
||||||
|
icon: 'error',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Error!',
|
||||||
|
text: 'There was an error submitting the form.',
|
||||||
|
icon: 'error',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Error:', error);
|
|
||||||
Swal.fire({
|
|
||||||
title: 'Success!',
|
|
||||||
text: 'Form submitted successfully.',
|
|
||||||
icon: 'success',
|
|
||||||
confirmButtonText: 'OK'
|
|
||||||
}).then((result) => {
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
window.location.href = '{{ route('responses.success', $form) }}';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -22,50 +22,49 @@
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div mt-4">
|
|
||||||
|
<div style="max-width: 100%;" class="container mt-4">
|
||||||
<!-- Responses Section -->
|
<!-- Responses Section -->
|
||||||
<div class="question_form bg-light p-4 rounded shadow-md" id="responses_section">
|
<div style="max-width: 100%;" class="question_form bg-light p-1 rounded shadow-md" id="responses_section">
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="question_title_section mb-4">
|
<div class="question_title_section mb-4">
|
||||||
<div class="question_form_top">
|
<div class="question_form_top">
|
||||||
<input type="text" id="form-title" name="title" class="form-control form-control-lg mb-2" style="color: black" placeholder="Untitled Form" value="{{ $form->title }}" readonly />
|
<input type="text" id="form-title" name="title" class="form-control form-control-lg mb-2" style="color: black" placeholder="Untitled Form" value="{{ $form->title }}" readonly />
|
||||||
<input type="text" name="description" id="form-description" class="form-control form-control-sm" style="color: black" value="{{$form->description}}" readonly/>
|
<input type="text" name="description" id="form-description" class="form-control form-control-sm" style="color: black" value="{{ $form->description }}" readonly/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="section shadow-md" id="questions_section">
|
<div class="section shadow-md" id="questions_section">
|
||||||
@foreach ($responses as $response)
|
@foreach ($responses as $response)
|
||||||
@php
|
@php
|
||||||
$question = $questions[$response->question_id] ?? null;
|
$question = $questions[$response->question_id];
|
||||||
$decodedAnswers = json_decode($response->answers, true);
|
$decodedAnswers = json_decode($response->answers, true);
|
||||||
@endphp
|
@endphp
|
||||||
@if ($question)
|
<div class="question mb-4 p-3 border rounded bg-white shadow-md">
|
||||||
<div class="question mb-4 p-3 border rounded bg-white shadow-md">
|
<h3 class="text-lg font-medium mb-2">
|
||||||
<h3 class="text-lg font-medium mb-2">{{ $question->question_text }}</h3>
|
{{ $question['question_text'] }}
|
||||||
@if ($question->type == 'dropdown')
|
</h3>
|
||||||
<select disabled class="form-control">
|
@if ($question['type'] == 'dropdown')
|
||||||
@foreach (json_decode($question->options) as $option)
|
<select disabled class="form-control">
|
||||||
<option {{ ($option == $decodedAnswers) ? 'selected' : '' }}>
|
@foreach (json_decode($question['options'] ?? '[]') as $option)
|
||||||
{{ $option }}
|
<option {{ ($option == $decodedAnswers) ? 'selected' : '' }}>
|
||||||
</option>
|
{{ $option }}
|
||||||
@endforeach
|
</option>
|
||||||
</select>
|
@endforeach
|
||||||
@elseif (in_array($question->type, ['multiple_choice', 'checkbox']))
|
</select>
|
||||||
<div class="options-container mb-3">
|
@elseif (in_array($question['type'], ['multiple_choice', 'checkbox']))
|
||||||
@foreach (json_decode($question->options) as $option)
|
<div class="options-container mb-3">
|
||||||
<div class="option d-flex align-items-center mb-2">
|
@foreach (json_decode($question['options'] ?? '[]') as $option)
|
||||||
<input type="{{ $question->type == 'checkbox' ? 'checkbox' : 'radio' }}" disabled {{ in_array($option, (array)$decodedAnswers) ? 'checked' : '' }} class="mr-2">
|
<div class="option d-flex align-items-center mb-2">
|
||||||
{{ $option }}
|
<input type="{{ $question['type'] == 'checkbox' ? 'checkbox' : 'radio' }}" disabled {{ in_array($option, (array)$decodedAnswers) ? 'checked' : '' }} class="mr-2">
|
||||||
</div>
|
{{ $option }}
|
||||||
@endforeach
|
</div>
|
||||||
</div>
|
@endforeach
|
||||||
@else
|
</div>
|
||||||
<p class="mt-2 p-3 bg-light rounded">{{ is_array($decodedAnswers) ? implode(', ', $decodedAnswers) : $decodedAnswers }}</p>
|
@else
|
||||||
@endif
|
<p class="mt-2 p-3 bg-light rounded">{{ is_array($decodedAnswers) ? implode(', ', $decodedAnswers) : $decodedAnswers }}</p>
|
||||||
</div>
|
@endif
|
||||||
@else
|
</div>
|
||||||
<p class="text-danger">Question not found for ID: {{ $response->question_id }}</p>
|
|
||||||
@endif
|
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
<body class="font-roboto text-gray-800 bg-white">
|
<body class="font-roboto text-gray-800 bg-white">
|
||||||
|
|
||||||
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="bg-white shadow-md px-6 py-4 flex justify-between items-center">
|
<div class="bg-white shadow-md px-6 py-4 flex justify-between items-center">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
|
|
|
@ -11,11 +11,4 @@ export default defineConfig({
|
||||||
refresh: true,
|
refresh: true,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
server: {
|
|
||||||
host: '0.0.0.0',
|
|
||||||
port: 3000,
|
|
||||||
hmr: {
|
|
||||||
host: '192.168.2.179',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue