SurveyVista/Web/Views/QuestionnaireResponse/DisplayQuestionnaire.cshtml
2024-04-21 19:59:57 +02:00

684 lines
28 KiB
Text

@model ResponseQuestionnaireViewModel
@{
ViewData["Title"] = "DisplayQuestionnaire";
Layout = "~/Views/Shared/_QuestionnaireResponse.cshtml";
}
<style>
body {
height: 100% !important;
background-color:#141c27 !important;
}
#QuestionCard{
height:auto;
padding:15px;
}
#rowSectionError {
display: flex;
flex-wrap: nowrap;
justify-content: space-around;
align-items: center;
align-content: center;
width: 100%;
flex-direction: row;
}
output{
color:white !important;
font-weight:bold;
}
#boxBanner {
display: block;
width: auto;
margin: 5px;
}
.QuestionContainer{
padding-top:100px;
padding-bottom:100px;
}
.stepper {
display: flex;
flex-direction: column;
align-items: center;
}
.step-indicator {
width: 150px;
height: 30px;
border-radius: 3px;
background-color:transparent;
margin-bottom:10px;
display: flex;
justify-content: center;
align-items: center;
color: white; /* Text color */
font-weight: bold;
border: 0.05px solid #294255;
box-shadow: 0px 0px 6px 2px rgba(0,0,0,0.18);
-webkit-box-shadow: 0px 0px 6px 2px rgba(0,0,0,0.18);
-moz-box-shadow: 0px 0px 6px 2px rgba(0,0,0,0.18);
}
.step-indicator.active {
background-color: #33b3ae; /* Primary color for active step */
box-shadow: 0px 0px 21px -4px rgba(0,0,0,0.45);
-webkit-box-shadow: 0px 0px 21px -4px rgba(0,0,0,0.45);
-moz-box-shadow: 0px 0px 21px -4px rgba(0,0,0,0.45);
}
h4, h5,h6, p, label {
color:aliceblue;
}
.card{
box-shadow: 0px 0px 36px -12px rgba(20,101,230,1);
-webkit-box-shadow: 0px 0px 36px -12px rgba(20,101,230,1);
-moz-box-shadow: 0px 0px 36px -12px rgba(20,101,230,1);
border-radius:10px;
background-color:transparent;
padding:50px;
}
.form-control {
width: 80%;
margin: 15px 0px 0px 0px;
}
.hidden-textarea {
display: none;
}
.rating .rating-item {
display: inline-block; /* Align items horizontally */
text-align: center; /* Center-align the label and star */
margin: 5px; /* Spacing between rating items */
}
.rating .rating-label {
display: block; /* Ensure the label is on a new line */
margin-bottom: 2px; /* Space between label and star */
font-size: 14px; /* Smaller font size for the label */
color: white;
}
/* Style the stars */
.rating .rating-star {
font-size: 24px; /* Adjust size as needed */
color: #ccc; /* Default color of stars */
cursor: pointer; /* Change cursor to pointer on hover */
transition: color 0.3s ease; /* Smooth transition for color change */
}
/* Style the stars when they are hovered over */
.rating .rating-star:hover,
.rating .rating-star:hover ~ .rating-star {
color: #ffe350; /* Color when hovered */
}
/* Style the stars when they are selected */
.rating .rating-star.selected {
color: #df9d01; /* Color of selected stars */
}
.rank-list {
list-style-type: none;
padding: 0;
}
.rank-list li {
padding: 5px;
margin-bottom: 2px;
color:white
}
</style>
<div class="QuestionContainer">
<section class="hero container card">
<form id="questionnaireForm" method="post" asp-action="DisplayQuestionnaire">
<input type="hidden" name="Id" value="@Model.Id">
<input type="hidden" name="Title" value="@Model.Title">
<input type="hidden" name="Description" value="@Model.Description">
<h4>@Model.Title</h4>
<p>@Html.Raw(Model.Description)</p>
<div class="container">
<div class="row align-items-center">
<!-- Stepper -->
<div class="col-md-3">
<div class="stepper">
@for (int i = 0; i < Model.Questions.Count; i++)
{
var question = Model.Questions[i];
string stepClass = i == 0 ? "active" : ""; // Adjusted the index to start from the first question
<div class="step-indicator @(stepClass)" data-step-index="@i">
<span class="step-number">@((i + 1)). </span>
<span class="step-label">@question.Type</span>
</div>
}
</div>
</div>
<!-- Form Content -->
<div class="col-md-9">
@for (int i = 0; i < Model.Questions.Count; i++)
{
var question = Model.Questions[i];
<input type="hidden" name="Id" value="@question.Id">
<input type="hidden" name="Questions[@i].Text" value="@question.Text">
<input type="hidden" name="Questions[@i].Id" value="@question.Id">
<input type="hidden" name="Questions[@i].Type" value="@((int)question.Type)">
@for (int j = 0; j < question.Answers.Count; j++)
{
var answer = question.Answers[j];
<input type="hidden" name="Questions[@i].Answers[@j].Id" value="@answer.Id">
<input type="hidden" name="Questions[@i].Answers[@j].Text" value="@answer.Text">
<!-- Add more hidden fields as needed for other properties of the answer -->
}
<div class="step @(i == 0 ? "active" : "")">
<p class="font-weight-normal">@(i + 1). @question.Text</p>
<div id="QuestionCard">
@switch (question.Type)
{
case QuestionType.Text:
@foreach (var answer in question.Answers)
{
<input type="Text" class="form-control" id="question@(i + 1)" name="Questions[@i].SelectedText" rows="3" placeholder="Enter answer"></input>
<input class="form-control hidden-textarea" id="question@(i + 1)" name="Questions[@i].SelectedAnswerIds" value="@answer.Id" rows="3" placeholder="Enter answer"></input>
}
break;
case QuestionType.CheckBox:
case QuestionType.Multiple_choice:
case QuestionType.Likert:
case QuestionType.Matrix:
case QuestionType.Demographic:
<div class="form-group">
@foreach (var answer in question.Answers)
{
<div class="form-check">
<input class="form-check-input" id="question@(i)_answer@(answer.Id)" type="checkbox" name="Questions[@i].SelectedAnswerIds" value="@answer.Id">
<label class="form-check-label" for="question@(i)_answer@(answer.Id)">
@answer.Text
</label>
</div>
}
</div>
break;
case QuestionType.TrueFalse:
<div class="form-check">
@foreach (var answer in question.Answers)
{
<div class="form-check">
<input class="form-check-input answer-input" type="radio" id="question@(i)_answer@(answer.Id)" name="Questions[@i].SelectedAnswerIds" value="@answer.Id">
<label class="form-check-label" for="question@(i)_answer@(answer.Id)">
@answer.Text
</label>
</div>
}
</div>
break;
case QuestionType.Open_ended:
@foreach (var answer in question.Answers)
{
<textarea type="Text" class="form-control" id="question@(i + 1)" name="Questions[@i].SelectedText" value="@answer.Text" rows="3" placeholder="Enter answer"></textarea>
<input type="hidden" class="form-control" id="question@(i + 1)" name="Questions[@i].SelectedAnswerIds" value="@answer.Id" rows="3" placeholder="Enter answer"></input>
}
break;
case QuestionType.Image:
<input type="file" class="form-control-file" id="question@(i + 1)" name="Questions[@i].SelectedAnswerIds">
break;
case QuestionType.Slider:
@foreach(var answer in question.Answers)
{
<input type="range" class="form-range " id="question@(i + 1)" name="Questions[@i].SelectedText" min="0" max="100" step="1">
<input type="hidden" class="form-range " id="question@(i + 1)" name="Questions[@i].SelectedAnswerIds" value="@answer.Id" min="0" max="100" step="1">
<output id="question@(i + 1)_output">50</output>
<script>
document.getElementById('question@(i + 1)').addEventListener('input', function () {
document.getElementById('question@(i + 1)_output').value = this.value;
});
</script>
}
break;
case QuestionType.Rating:
<div class="rating" data-question="@i" >
@foreach (var answer in question.Answers)
{
<div class="rating-item">
<div class="rating-label">@answer.Text</div>
<input type="radio" id="question@(i)_rating@(answer.Id)"
name="Questions[@i].SelectedAnswerIds"
value="@answer.Id" class="rating-input" hidden>
<label for="question@(i)_rating@(answer.Id)" class="bi bi-star-fill rating-star"></label>
</div>
}
</div>
break;
case QuestionType.Ranking:
<div class="ranking" data-question="@i">
<ul class="rank-list">
@foreach (var answer in question.Answers)
{
<li data-answer-id="@answer.Id">
@answer.Text
<button type="button" class="up-button btn btn-primary btn-sm" onclick="moveUp(this)"><i class="bi bi-arrow-up"></i> Up</button>
<button type="button" class="down-button btn btn-info btn-sm" onclick="moveDown(this)"><i class="bi bi-arrow-down"></i> Down</button>
<input type="hidden" name="Questions[@i].SelectedAnswerIds" value="@answer.Id">
</li>
}
</ul>
</div>
<script>
</script>
break;
default:
<div class="alert alert-danger" role="alert">
Unsupported question type.
</div>
break;
}
</div>
<div class="mt-3">
@if (i > 0)
{
<button type="button" class="btn btn-secondary btn-sm mr-3 prev" id="BannerButon"><i class="bi bi-arrow-left"></i> Previous </button>
}
@if (i < Model.Questions.Count - 1)
{
<button type="button" class="btn btn-primary btn-sm next" id="BannerButon">Next <i class="bi bi-arrow-right"></i></button>
}
</div>
</div>
}
<button type="submit" class="btn btn-primary submit btn-sm mt-4" id="BannerButon">Submit</button>
</div>
</div>
</div>
</form>
</section>
</div>
@section Scripts {
@{
<partial name="_ValidationScriptsPartial" />
}
<script>
document.addEventListener("DOMContentLoaded", function () {
const form = document.getElementById('questionnaireForm');
if (!form) {
console.error('Form not found!');
return;
}
$(document).ready(function () {
$('.rating-item').on('click', function () {
// Remove 'selected' class from all stars within the same rating
$(this).siblings().find('.rating-star').removeClass('selected');
// Add 'selected' class to the clicked star and all stars before it within the same rating
$(this).find('.rating-star').addClass('selected');
$(this).prevAll().find('.rating-star').addClass('selected');
// Toggle 'fill' class on the clicked star
$(this).find('.rating-star').toggleClass('bi-star-fill bi-star');
// Check the corresponding radio input
$(this).find('.rating-input').prop('checked', true);
});
});
// Ensure we only add listeners once by checking if they've been added already
if (!window.hasEventListenersAdded) {
const upButtons = document.querySelectorAll('.up-button');
const downButtons = document.querySelectorAll('.down-button');
upButtons.forEach(button => {
button.addEventListener('click', function () {
moveUp(this);
});
});
downButtons.forEach(button => {
button.addEventListener('click', function () {
moveDown(this);
});
});
window.hasEventListenersAdded = true; // Set a flag to indicate listeners are added
}
function moveUp(button) {
var li = button.parentNode;
if (li.previousElementSibling) {
li.parentNode.insertBefore(li, li.previousElementSibling);
}
}
function moveDown(button) {
var li = button.parentNode;
if (li.nextElementSibling) {
li.parentNode.insertBefore(li.nextElementSibling, li);
}
}
function updateOrder() {
document.querySelectorAll('.rank-list').forEach((list, index) => {
list.querySelectorAll('li').forEach((li, idx) => {
// Assuming each li has a hidden input as the last child
li.querySelector('input[type="hidden"]').value = li.getAttribute('data-answer-id');
});
});
}
const steps = form.querySelectorAll('.step');
const stepIndicators = document.querySelectorAll('.step-indicator');
const submitButton = form.querySelector('.submit');
let currentStep = 0;
// Prevent form submission
form.addEventListener('submit', function (event) {
// event.preventDefault();
console.log('Form submission prevented.');
// Here, you can add logic to handle the form data client-side,
// such as validating input or sending it via AJAX.
const formData = new FormData(form);
formData.forEach((value, key) => {
console.log(`${key}: ${value}`);
});
});
function showStep(index) {
steps.forEach((step, i) => {
step.style.display = i === index ? 'block' : 'none';
});
stepIndicators.forEach((indicator, i) => {
if (i === index) {
indicator.classList.add('active');
} else {
indicator.classList.remove('active');
}
});
submitButton.style.display = index === steps.length - 1 ? 'block' : 'none';
}
function goToNextStep() {
if (currentStep < steps.length - 1) {
currentStep++;
showStep(currentStep);
updateStepper();
}
}
function goToPrevStep() {
if (currentStep > 0) {
currentStep--;
showStep(currentStep);
updateStepper();
}
}
function updateStepper() {
const currentStepIndex = currentStep;
stepIndicators.forEach((indicator, i) => {
indicator.style.backgroundColor = i === currentStepIndex ? '#33b3ae' : ''; // Change to your primary color
});
}
// Event listeners for next/previous buttons
const nextButtons = form.querySelectorAll('.next');
nextButtons.forEach(button => {
button.addEventListener('click', goToNextStep);
});
const prevButtons = form.querySelectorAll('.prev');
prevButtons.forEach(button => {
button.addEventListener('click', goToPrevStep);
});
// Initialize the form at the first step
showStep(currentStep);
});
</script>
@* <script>
document.addEventListener("DOMContentLoaded", function () {
const form = document.getElementById('questionnaireForm');
const steps = form.querySelectorAll('.step');
const stepIndicators = document.querySelectorAll('.step-indicator');
const submitButton = form.querySelector('.submit');
let currentStep = 0;
document.addEventListener('DOMContentLoaded', function () {
const form = document.getElementById('questionnaireForm'); // Replace 'myForm' with your actual form ID
form.addEventListener('submit', function (event) {
event.preventDefault(); // Stop the form from submitting
console.log('Form submission prevented.');
// Here, you can add any logic to handle the form data client-side,
// such as validating input, organizing data, or sending it via AJAX.
// Example of gathering form data:
const formData = new FormData(form);
formData.forEach((value, key) => {
console.log(`${key}: ${value}`);
});
// Optionally, you could send the formData using fetch() or another AJAX method
});
});
function handleSubmit(event) {
event.preventDefault(); // Stop the form from submitting normally
const form = event.target; // Get the form that triggered the event
const formData = new FormData(form);
// Assuming you need to do something special with `SelectedAnswerIds`
const refinedFormData = new FormData();
formData.forEach((value, key) => {
if (key.includes("SelectedAnswerIds")) {
document.querySelectorAll(`input[name="${key}"]:checked`).forEach(checkbox => {
refinedFormData.append(key, checkbox.value); // Only append checked items
});
} else {
refinedFormData.append(key, value); // Append other data normally
}
});
// Debugging: log formData to ensure it's captured correctly
console.log('Prepared formData for submission:');
refinedFormData.forEach((value, key) => {
console.log(`${key}: ${value}`);
});
// Fetch API to submit the refined FormData
fetch(form.action, {
method: 'POST',
body: refinedFormData,
})
.then(response => response.json()) // Assuming JSON response
.then(data => {
console.log('Submission successful', data);
// Handle success (e.g., display a success message, redirect, etc.)
})
.catch(error => {
console.error('Submission failed', error);
// Handle errors (e.g., display error message)
});
}
function updateSelectedText(radio, text, index) {
console.log("Radio checked:", radio.checked); // Check if the radio is indeed checked
console.log("Text to set:", text); // What text is being set
console.log("Target hidden input ID:", 'selected_text_question' + index); // Which input we're targeting
var hiddenInput = document.getElementById('selected_text_question' + index);
if (radio.checked) {
hiddenInput.value = text;
console.log("Updated hidden input value:", hiddenInput.value); // Verify the value is set
}
}
function showStep(index) {
steps.forEach((step, i) => {
if (i === index) {
step.style.display = 'block';
} else {
step.style.display = 'none';
}
});
stepIndicators.forEach((indicator, i) => {
if (i === index) {
indicator.classList.add('active');
} else {
indicator.classList.remove('active');
}
});
if (index === steps.length - 1) {
submitButton.style.display = 'block';
} else {
submitButton.style.display = 'none';
}
}
function goToNextStep() {
if (currentStep < steps.length - 1) {
currentStep++;
showStep(currentStep);
}
}
function goToPrevStep() {
if (currentStep > 0) {
currentStep--;
showStep(currentStep);
}
}
const nextButtons = form.querySelectorAll('.next');
nextButtons.forEach(button => {
button.addEventListener('click', () => {
goToNextStep();
updateStepper();
});
});
const prevButtons = form.querySelectorAll('.prev');
prevButtons.forEach(button => {
button.addEventListener('click', () => {
goToPrevStep();
updateStepper();
});
});
function updateStepper() {
const currentStepIndex = currentStep;
stepIndicators.forEach((indicator, i) => {
if (i === currentStepIndex) {
indicator.style.backgroundColor = '#33b3ae'; // Change to your primary color
} else {
indicator.style.backgroundColor = ''; // Reset to default color for non-active steps
}
});
}
// Add submit event listener to the form
showStep(currentStep);
updateStepper();
$('.rating i').on('click', function () {
var value = $(this).data('value');
var questionIndex = $(this).closest('.rating').data('question');
var selectedStars = $(this).closest('.rating').find('i.selected').length;
// Unselect all stars
$(this).closest('.rating').find('i').removeClass('selected');
// Select the clicked star and all preceding stars
$(this).addClass('selected').prevAll().addClass('selected');
// Update the hidden input value if needed
$('input[name="question' + questionIndex + '_rating"]').val(value);
// Update the label with the number of selected stars
$(this).closest('.rating').next('.selected-count').text(selectedStars);
});
// Prevent the default action for the anchor tags within the rating
$('.rating a').on('click', function (e) {
e.preventDefault();
});
});
event.preventDefault();
</script> *@
}