UI changes
This commit is contained in:
parent
2f7529ce2e
commit
e747614bd3
|
@ -20,7 +20,7 @@ class FormController extends Controller
|
||||||
$publishedForms = Form::where('is_published', true)->count();
|
$publishedForms = Form::where('is_published', true)->count();
|
||||||
$totalResponses = Response::count();
|
$totalResponses = Response::count();
|
||||||
|
|
||||||
$forms = Form::where('user_id', Auth::id())->get();
|
$forms = Form::where('user_id', Auth::id())->orderBy('created_at', 'desc')->get();
|
||||||
return view('forms.index', [
|
return view('forms.index', [
|
||||||
'forms' => $forms,
|
'forms' => $forms,
|
||||||
'totalForms' => $totalForms,
|
'totalForms' => $totalForms,
|
||||||
|
@ -54,6 +54,55 @@ class FormController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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'],
|
||||||
|
// Add more questions as needed
|
||||||
|
],
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'party':
|
||||||
|
$data = [
|
||||||
|
'title' => 'Party Invite',
|
||||||
|
'description' => 'Template for party invitations.',
|
||||||
|
'questions' => [
|
||||||
|
['type' => 'text', 'question_text' => 'Name'],
|
||||||
|
['type' => 'text', 'question_text' => 'RSVP Status'],
|
||||||
|
// Add more questions as needed
|
||||||
|
],
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('forms.create', ['data' => $data]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,6 +21,12 @@ class ResponseController extends Controller
|
||||||
return view('responses.index', compact('form', 'responses'));
|
return view('responses.index', compact('form', 'responses'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function showSuccess(Form $form)
|
||||||
|
{
|
||||||
|
return view('responses.success', compact('form'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Display a specific response
|
// Display a specific response
|
||||||
public function viewResponse(Form $form, $responseId)
|
public function viewResponse(Form $form, $responseId)
|
||||||
{
|
{
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 959 B |
Binary file not shown.
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 1.1 KiB |
|
@ -48,8 +48,8 @@
|
||||||
<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 p-2 mb-2" placeholder="Untitled Form" />
|
<input type="text" id="form-title" name="title" value="{{ $data['title'] ?? '' }}" class="form-control form-control-lg p-2 mb-2" placeholder="Untitled Form" />
|
||||||
<input type="text" name="description" id="form-description" class="form-control form-control-sm" placeholder="Form Description" />
|
<input type="text" name="description" id="form-description" value="{{ $data['description'] ?? '' }}" class="form-control form-control-sm" placeholder="Form Description" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap"
|
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap"
|
||||||
rel="stylesheet">
|
rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
|
@ -110,6 +112,49 @@
|
||||||
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
|
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
|
||||||
<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>
|
||||||
|
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
$('#edit-form').on('submit', function (e) {
|
||||||
|
e.preventDefault(); // Prevent the default form submission
|
||||||
|
|
||||||
|
// Get the form action and data
|
||||||
|
var form = $(this);
|
||||||
|
var url = form.attr('action');
|
||||||
|
var formData = form.serialize();
|
||||||
|
|
||||||
|
// Send an AJAX request to submit the form data
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: url,
|
||||||
|
data: formData,
|
||||||
|
success: function (response) {
|
||||||
|
// Show SweetAlert on success
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Success!',
|
||||||
|
text: 'Form edited successfully.',
|
||||||
|
icon: 'success',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
// Redirect to the show page
|
||||||
|
window.location.href = "{{ route('forms.show', $form) }}";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
error: function (xhr, status, error) {
|
||||||
|
// Handle any errors
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Error!',
|
||||||
|
text: 'An error occurred while editing the form. Please try again.',
|
||||||
|
icon: 'error',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function addOption(button) {
|
function addOption(button) {
|
||||||
const optionsContainer = $(button).closest('.options-container');
|
const optionsContainer = $(button).closest('.options-container');
|
||||||
const optionIndex = optionsContainer.find('.option').length;
|
const optionIndex = optionsContainer.find('.option').length;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<!DOCTYPE html>
|
{{-- <!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
<p class="font-normal text-gray-700 dark:text-gray-400">{{ $totalResponses }}</p>
|
<p class="font-normal text-gray-700 dark:text-gray-400">{{ $totalResponses }}</p>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<h2 class="text-3xl font-semibold text-gray-800 font-sans">Created Forms</h2>
|
<h2 class="text-3xl font-semibold text-gray-800 font-sans">Recent Forms</h2>
|
||||||
<br>
|
<br>
|
||||||
<div class="shadow-custom rounded-lg p-6 bg-gray-100">
|
<div class="shadow-custom rounded-lg p-6 bg-gray-100">
|
||||||
@if ($forms->isEmpty())
|
@if ($forms->isEmpty())
|
||||||
|
@ -163,3 +163,164 @@
|
||||||
<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>
|
</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>
|
||||||
|
.dropdown:hover .dropdown-menu {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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('/') }}" style="color: rgb(103,58,183)"
|
||||||
|
class="text-3xl font-bold font-sans">LaraForms</a>
|
||||||
|
<div class="relative dropdown">
|
||||||
|
<button id="profileMenuButton" class="flex items-center focus:outline-none">
|
||||||
|
<img src="{{ asset('images/user.png') }}" alt="Profile"
|
||||||
|
class="w-10 h-10 rounded-full border-2 border-white">
|
||||||
|
</button>
|
||||||
|
<div id="profileMenu"
|
||||||
|
class="dropdown-menu hidden absolute right-0 mt-2 w-48 bg-white rounded-md shadow-lg py-2">
|
||||||
|
<form method="POST" action="{{ route('logout') }}">
|
||||||
|
@csrf
|
||||||
|
<button type="submit" class="block px-4 py-2 text-gray-700 hover:bg-gray-200 w-full text-left">
|
||||||
|
Logout
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<br>
|
||||||
|
@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="container mx-auto mt-10">
|
||||||
|
<div class="flex justify-between mb-6 items-center grid grid-cols-4 gap-20">
|
||||||
|
<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 href="{{ route('forms.template', 'contact') }}" style="color: rgb(103,58,183)"
|
||||||
|
class="block max-w-md p-5 bg-white border border-gray-200 rounded-lg shadow hover:bg-gray-50 transition duration-200">
|
||||||
|
<h5 class="mb-2 text-gray-800 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Contact Information</h5>
|
||||||
|
<p class="font-normal text-gray-700 dark:text-gray-400">Use this template to create a contact information form.</p>
|
||||||
|
</a>
|
||||||
|
<a href="{{ route('forms.template', 'rsvp') }}" class="block max-w-md p-5 bg-white border border-gray-200 rounded-lg shadow hover:bg-gray-50 transition duration-200">
|
||||||
|
<h5 class="mb-2 text-gray-800 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">RSVP</h5>
|
||||||
|
<p class="font-normal text-gray-700 dark:text-gray-400">Use this template to create an RSVP form for events.</p>
|
||||||
|
</a>
|
||||||
|
<a href="{{ route('forms.template', 'party') }}" class="block max-w-md p-5 bg-white border border-gray-200 rounded-lg shadow hover:bg-gray-50 transition duration-200">
|
||||||
|
<h5 class="mb-2 text-gray-800 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Party Invite</h5>
|
||||||
|
<p class="font-normal text-gray-700 dark:text-gray-400">Use this template to create a party invite form.</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<hr style="height:30px">
|
||||||
|
<h2 class="text-3xl font-semibold text-gray-800 font-sans">Recent Forms</h2>
|
||||||
|
<br>
|
||||||
|
<div class="shadow-custom rounded-lg p-6 bg-gray-100">
|
||||||
|
@if ($forms->isEmpty())
|
||||||
|
<p class="text-gray-600 text-center">No forms available.</p>
|
||||||
|
@else
|
||||||
|
<table class="min-w-full bg-white rounded-md overflow-hidden">
|
||||||
|
<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 text-left text-sm font-semibold text-gray-600"></th>
|
||||||
|
<th class="py-4 px-6 border-b border-gray-200 text-left text-sm font-semibold text-gray-600"></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-10">
|
||||||
|
@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>
|
||||||
|
<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>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function handle() {
|
||||||
|
Swal.fire({
|
||||||
|
title: 'You cannot edit a published form',
|
||||||
|
icon: 'info',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setTimeout(function() {
|
||||||
|
var successMessage = document.getElementById('successMessage');
|
||||||
|
if (successMessage) {
|
||||||
|
successMessage.remove();
|
||||||
|
}
|
||||||
|
}, 3000);
|
||||||
|
</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>
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
<div><button type="submit" name="publish" value="publish" class="btnsave btn btn-secondary">Edit</button></div>
|
<div><button type="submit" name="publish" value="publish" class="btnsave btn btn-secondary"><a href="/forms/{{$form->id}}/edit">Edit</a></button></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,106 +1,4 @@
|
||||||
{{-- @extends('layouts.app')
|
{{-- @extends('layouts.app')
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
|
||||||
|
|
||||||
@section('content')
|
|
||||||
<div class="container mx-auto py-8 px-4 md:px-0">
|
|
||||||
<div class="bg-white shadow-md rounded-lg p-6">
|
|
||||||
<h1 class="text-3xl font-semibold text-gray-900">{{ $form->title }}</h1>
|
|
||||||
<p class="text-gray-600 mt-2">{{ $form->description }}</p>
|
|
||||||
|
|
||||||
<form action="{{ route('responses.submitForm', $form) }}" method="POST" class="mt-8">
|
|
||||||
@csrf
|
|
||||||
@foreach ($questions as $question)
|
|
||||||
<div class="mt-6">
|
|
||||||
<label class="block font-medium text-base text-gray-800 mb-2">{{ $question->question_text }}</label>
|
|
||||||
@if ($question->type == 'multiple_choice')
|
|
||||||
@foreach (json_decode($question->options) as $option)
|
|
||||||
<label class="flex items-center mt-2">
|
|
||||||
<input class="form-radio text-base text-purple-600 h-4 w-4" type="radio" name="answers[{{ $question->id }}]" value="{{ $option }}">
|
|
||||||
<span class="ml-2 text-gray-700">{{ $option }}</span>
|
|
||||||
</label>
|
|
||||||
@endforeach
|
|
||||||
@elseif($question->type == 'checkbox')
|
|
||||||
@foreach (json_decode($question->options) as $option)
|
|
||||||
<label class="flex items-center mt-2">
|
|
||||||
<input class="form-checkbox text-purple-600 h-4 w-4" type="checkbox" name="answers[{{ $question->id }}][]" value="{{ $option }}">
|
|
||||||
<span class="ml-2 text-gray-700">{{ $option }}</span>
|
|
||||||
</label>
|
|
||||||
@endforeach
|
|
||||||
@elseif($question->type == 'dropdown')
|
|
||||||
<select class="form-select mt-2 block w-full p-2 border border-gray-300 rounded-md bg-white shadow-sm focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm" name="answers[{{ $question->id }}]">
|
|
||||||
@foreach (json_decode($question->options) as $option)
|
|
||||||
<option value="{{ $option }}">{{ $option }}</option>
|
|
||||||
@endforeach
|
|
||||||
</select>
|
|
||||||
@elseif($question->type == 'text')
|
|
||||||
<textarea name="answers[{{ $question->id }}]" class="form-textarea mt-2 block w-full p-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm"></textarea>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
@endforeach
|
|
||||||
|
|
||||||
<button type="submit" class="mt-8 w-full md:w-auto inline-flex justify-center items-center px-6 py-3 bg-purple-700 border border-transparent rounded-md font-semibold text-white text-lg uppercase tracking-widest hover:bg-purple-800 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2">
|
|
||||||
Submit
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
document.getElementById('responseForm').addEventListener('submit', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
const form = event.target;
|
|
||||||
const formData = new FormData(form);
|
|
||||||
|
|
||||||
fetch(form.action, {
|
|
||||||
method: form.method,
|
|
||||||
headers: {
|
|
||||||
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
|
||||||
},
|
|
||||||
body: formData
|
|
||||||
})
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
if (data.success) {
|
|
||||||
Swal.fire({
|
|
||||||
title: 'Success!',
|
|
||||||
text: 'Form submitted successfully.',
|
|
||||||
icon: 'success',
|
|
||||||
confirmButtonText: 'OK'
|
|
||||||
}).then((result) => {
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
window.location.href = '/forms';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Swal.fire({
|
|
||||||
title: 'Error!',
|
|
||||||
text: 'Failed to submit form.',
|
|
||||||
icon: 'error',
|
|
||||||
confirmButtonText: 'OK'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Error:', error);
|
|
||||||
Swal.fire({
|
|
||||||
title: 'Error!',
|
|
||||||
text: 'An error occurred while submitting the form.',
|
|
||||||
icon: 'error',
|
|
||||||
confirmButtonText: 'OK'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
@endsection --}}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@extends('layouts.app')
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
|
<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>
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
|
|
||||||
|
@ -191,6 +89,119 @@
|
||||||
text: 'Form Submitted Successfully',
|
text: 'Form Submitted Successfully',
|
||||||
icon: 'success',
|
icon: 'success',
|
||||||
confirmButtonText: 'OK'
|
confirmButtonText: 'OK'
|
||||||
|
}).then()=>{
|
||||||
|
window.location.href
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endsection --}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@extends('layouts.app')
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container mx-auto py-8 px-4 md:px-0">
|
||||||
|
<div class="bg-white shadow-md rounded-lg p-6">
|
||||||
|
<h1 class="text-3xl font-semibold text-gray-900">{{ $form->title }}</h1>
|
||||||
|
<p class="text-gray-600 mt-2">{{ $form->description }}</p>
|
||||||
|
|
||||||
|
<form id="responseForm" action="{{ route('responses.submitForm', $form) }}" method="POST" class="mt-8">
|
||||||
|
@csrf
|
||||||
|
@foreach ($questions as $question)
|
||||||
|
<div class="mt-6">
|
||||||
|
<label class="block font-medium text-base text-gray-800 mb-2">{{ $question->question_text }}</label>
|
||||||
|
@if ($question->type == 'multiple_choice')
|
||||||
|
@foreach (json_decode($question->options) as $option)
|
||||||
|
<label class="flex items-center mt-2">
|
||||||
|
<input class="form-radio text-base text-purple-600 h-4 w-4" type="radio" name="answers[{{ $question->id }}]" value="{{ $option }}">
|
||||||
|
<span class="ml-2 text-gray-700">{{ $option }}</span>
|
||||||
|
</label>
|
||||||
|
@endforeach
|
||||||
|
@elseif($question->type == 'checkbox')
|
||||||
|
@foreach (json_decode($question->options) as $option)
|
||||||
|
<label class="flex items-center mt-2">
|
||||||
|
<input class="form-checkbox text-purple-600 h-4 w-4" type="checkbox" name="answers[{{ $question->id }}][]" value="{{ $option }}">
|
||||||
|
<span class="ml-2 text-gray-700">{{ $option }}</span>
|
||||||
|
</label>
|
||||||
|
@endforeach
|
||||||
|
@elseif($question->type == 'dropdown')
|
||||||
|
<select class="form-select mt-2 block w-full p-2 border border-gray-300 rounded-md bg-white shadow-sm focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm" name="answers[{{ $question->id }}]">
|
||||||
|
@foreach (json_decode($question->options) as $option)
|
||||||
|
<option value="{{ $option }}">{{ $option }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
@elseif($question->type == 'text')
|
||||||
|
<textarea name="answers[{{ $question->id }}]" class="form-textarea mt-2 block w-full p-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-purple-500 focus:border-purple-500 sm:text-sm"></textarea>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
<button type="submit" class="mt-8 w-full md:w-auto inline-flex justify-center items-center px-6 py-3 bg-purple-700 border border-transparent rounded-md font-semibold text-white text-lg uppercase tracking-widest hover:bg-purple-800 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2">
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.getElementById('responseForm').addEventListener('submit', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const form = event.target;
|
||||||
|
const formData = new FormData(form);
|
||||||
|
|
||||||
|
fetch(form.action, {
|
||||||
|
method: form.method,
|
||||||
|
headers: {
|
||||||
|
'X-CSRF-TOKEN': '{{ csrf_token() }}'
|
||||||
|
},
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Success!',
|
||||||
|
text: 'Form submitted successfully.',
|
||||||
|
icon: 'success',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
window.location.href = '{{ route('responses.success', $form) }}';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Success!',
|
||||||
|
text: 'Form submitted successfully.',
|
||||||
|
icon: 'success',
|
||||||
|
confirmButtonText: 'OK'
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
window.location.href = '{{ route('responses.success', $form) }}';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.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) }}';
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container mx-auto py-8 px-4 md:px-0">
|
||||||
|
<div class="bg-white shadow-md rounded-lg p-6 text-center">
|
||||||
|
<h1 class="text-3xl font-semibold text-gray-900">Response Submitted Successfully</h1>
|
||||||
|
<p class="text-gray-600 mt-2">Thank you for your response.</p>
|
||||||
|
<a href="{{ route('responses.showForm', $form) }}" class="mt-8 inline-flex justify-center items-center px-6 py-3 bg-purple-700 border border-transparent rounded-md font-semibold text-white text-lg uppercase tracking-widest hover:bg-purple-800 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2">
|
||||||
|
Fill Another Response
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
|
@ -141,110 +141,6 @@
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showTab(tabId) {
|
|
||||||
document.querySelectorAll('.tab-content').forEach(tab => {
|
|
||||||
tab.classList.add('hidden');
|
|
||||||
});
|
|
||||||
document.getElementById(tabId).classList.remove('hidden');
|
|
||||||
|
|
||||||
document.querySelectorAll('.tab-link').forEach(link => {
|
|
||||||
link.classList.remove('border-purple-600', 'text-purple-600');
|
|
||||||
});
|
|
||||||
document.querySelector(`[onclick="showTab('${tabId}')"]`).classList.add('border-purple-600', 'text-purple-600');
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
|
||||||
const statistics = @json($statistics);
|
|
||||||
console.log(statistics); // Log statistics for debugging
|
|
||||||
|
|
||||||
Object.keys(statistics).forEach(questionId => {
|
|
||||||
const ctx = document.getElementById(`chart-${questionId}`).getContext('2d');
|
|
||||||
const stat = statistics[questionId];
|
|
||||||
|
|
||||||
let labels = [];
|
|
||||||
let data = [];
|
|
||||||
let backgroundColors = [];
|
|
||||||
|
|
||||||
if (stat.type === 'multiple_choice' || stat.type === 'checkbox' || stat.type === 'dropdown') {
|
|
||||||
const optionCounts = {};
|
|
||||||
stat.responses.forEach(response => {
|
|
||||||
if (Array.isArray(response)) {
|
|
||||||
response.forEach(option => {
|
|
||||||
if (option in optionCounts) {
|
|
||||||
optionCounts[option]++;
|
|
||||||
} else {
|
|
||||||
optionCounts[option] = 1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (response in optionCounts) {
|
|
||||||
optionCounts[response]++;
|
|
||||||
} else {
|
|
||||||
optionCounts[response] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
labels = Object.keys(optionCounts);
|
|
||||||
data = Object.values(optionCounts);
|
|
||||||
backgroundColors = labels.map((_, index) => `rgba(${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)}, 0.5)`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stat.type === 'multiple_choice' || stat.type === 'dropdown') {
|
|
||||||
new Chart(ctx, {
|
|
||||||
type: 'pie',
|
|
||||||
data: {
|
|
||||||
labels: labels,
|
|
||||||
datasets: [{
|
|
||||||
label: 'Responses',
|
|
||||||
data: data,
|
|
||||||
backgroundColor: backgroundColors,
|
|
||||||
borderColor: backgroundColors.map(color => color.replace('0.5', '1')),
|
|
||||||
borderWidth: 1
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
beginAtZero: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
responsive: true,
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
position: 'top',
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
enabled: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (stat.type === 'checkbox') {
|
|
||||||
new Chart(ctx, {
|
|
||||||
type: 'bar',
|
|
||||||
data: {
|
|
||||||
labels: labels,
|
|
||||||
datasets: [{
|
|
||||||
label: 'Responses',
|
|
||||||
data: data,
|
|
||||||
backgroundColor: backgroundColors,
|
|
||||||
borderColor: backgroundColors.map(color => color.replace('0.5', '1')),
|
|
||||||
borderWidth: 1
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
beginAtZero: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Custom Scripts -->
|
<!-- Custom Scripts -->
|
||||||
|
|
|
@ -23,6 +23,8 @@ Route::middleware(['auth'])->group(function () {
|
||||||
Route::delete('/forms/{form}', [FormController::class, 'destroy'])->name('forms.destroy');
|
Route::delete('/forms/{form}', [FormController::class, 'destroy'])->name('forms.destroy');
|
||||||
Route::get('/forms/{form}/preview', [FormController::class, 'preview'])->name('forms.preview');
|
Route::get('/forms/{form}/preview', [FormController::class, 'preview'])->name('forms.preview');
|
||||||
Route::patch('/forms/{form}/publish', [FormController::class, 'togglePublish'])->name('forms.publish');
|
Route::patch('/forms/{form}/publish', [FormController::class, 'togglePublish'])->name('forms.publish');
|
||||||
|
Route::get('/forms/template/{template}', [FormController::class, 'createWithTemplate'])->name('forms.template');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Response routes
|
// Response routes
|
||||||
|
@ -30,5 +32,6 @@ Route::middleware(['auth'])->group(function () {
|
||||||
Route::get('/forms/respond/{form}', [ResponseController::class, 'showForm'])->name('responses.showForm');
|
Route::get('/forms/respond/{form}', [ResponseController::class, 'showForm'])->name('responses.showForm');
|
||||||
Route::post('/forms/respond/{form}', [ResponseController::class, 'submitForm'])->name('responses.submitForm');
|
Route::post('/forms/respond/{form}', [ResponseController::class, 'submitForm'])->name('responses.submitForm');
|
||||||
Route::get('/forms/{form}/responses', [ResponseController::class, 'viewResponses'])->name('responses.viewResponses');
|
Route::get('/forms/{form}/responses', [ResponseController::class, 'viewResponses'])->name('responses.viewResponses');
|
||||||
|
Route::get('/forms/{form}/success', [ResponseController::class, 'showSuccess'])->name('responses.success');
|
||||||
Route::get('/forms/{form}/responses/{responseId}', [ResponseController::class, 'viewResponse'])->name('responses.viewResponse');
|
Route::get('/forms/{form}/responses/{responseId}', [ResponseController::class, 'viewResponse'])->name('responses.viewResponse');
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue