Creating multiple question in the edit mode comppleted

This commit is contained in:
Qais Yousuf 2024-03-26 16:45:27 +01:00
parent 4b6f367545
commit 64280c8936
9 changed files with 516 additions and 203 deletions

View file

@ -221,75 +221,103 @@ namespace Web.Areas.Admin.Controllers
} }
// Update the questionnaire with the modified list of questions // Update the questionnaire with the modified list of questions
var newQuestions = new List<Question>();
// Update or add new questions // Update or add new questions
foreach (var questionViewModel in viewModel.Questions) foreach (var questionViewModel in viewModel.Questions)
{ {
var existingQuestion = existingQuestionnaire.Questions.FirstOrDefault(q => q.Id == questionViewModel.Id); var existingQuestion = existingQuestionnaire.Questions.FirstOrDefault(q => q.Id == questionViewModel.Id);
if(questionViewModel.Id !=0)
if (existingQuestion != null)
{ {
var answersToRemove = new List<Answer>(); if (existingQuestion != null)
existingQuestion.Text = questionViewModel.Text;
existingQuestion.Type = questionViewModel.Type;
foreach (var answerViewModel in questionViewModel.Answers)
{ {
// Check if the answer already exists var answersToRemove = new List<Answer>();
var existingAnswer = existingQuestion.Answers.FirstOrDefault(a => a.Id == answerViewModel.Id); existingQuestion.Text = questionViewModel.Text;
existingQuestion.Type = questionViewModel.Type;
if (answerViewModel.Id == 0)
foreach (var answerViewModel in questionViewModel.Answers)
{ {
// Check if the answer already exists
var existingAnswer = existingQuestion.Answers.FirstOrDefault(a => a.Id == answerViewModel.Id);
existingQuestion.Answers.Add(new Answer { Text = answerViewModel.Text }); if (answerViewModel.Id == 0)
{
existingQuestion.Answers.Add(new Answer { Text = answerViewModel.Text });
} }
else if (answerViewModel.Text == null) else if (answerViewModel.Text == null)
{ {
existingQuestion.Answers.Remove(existingAnswer); existingQuestion.Answers.Remove(existingAnswer);
await _questionnaire.Update(existingQuestionnaire); await _questionnaire.Update(existingQuestionnaire);
}
else if (existingAnswer != null)
{
existingAnswer.Text = answerViewModel.Text;
}
} }
else if (existingAnswer != null)
{
existingAnswer.Text = answerViewModel.Text;
}
} }
} }
else else
{ {
// Add new question // Create a new question
var newQuestion = new Question var newQuestion = new Question
{ {
Text = questionViewModel.Text, // Make sure question text is not null Text = questionViewModel.Text,
Type = questionViewModel.Type, // Make sure question type is not null Type = questionViewModel.Type,
Answers = new List<Answer>() // Initialize answers list Answers = new List<Answer>()
}; };
foreach (var answerViewModel in questionViewModel.Answers) foreach (var answerViewModel in questionViewModel.Answers)
{ {
// Add new answer if (!string.IsNullOrEmpty(answerViewModel.Text))
newQuestion.Answers.Add(new Answer { Text = answerViewModel.Text }); {
// Add new answer if text is not null or empty
newQuestion.Answers.Add(new Answer { Text = answerViewModel.Text });
}
} }
// Add new question to questionnaire // Add new question to the list of new questions
existingQuestionnaire.Questions.Add(newQuestion); newQuestions.Add(newQuestion);
} }
existingQuestionnaire.Questions.AddRange(newQuestions);
//else
//{
// // Add new question
// var newQuestion = new Question
// {
// Text = questionViewModel.Text, // Make sure question text is not null
// Type = questionViewModel.Type, // Make sure question type is not null
// Answers = new List<Answer>() // Initialize answers list
// };
// foreach (var answerViewModel in questionViewModel.Answers)
// {
// // Add new answer
// newQuestion.Answers.Add(new Answer { Text = answerViewModel.Text });
// }
// // Add new question to questionnaire
// existingQuestionnaire.Questions.Add(newQuestion);
//}
} }

View file

@ -51,17 +51,17 @@
<input type="hidden" name="Questions[@i].Answers" /> <input type="hidden" name="Questions[@i].Answers" />
</div> </div>
<button type="button" class="btn btn-sm p-3 btn-danger shadow remove-question">Remove Question <i class="bi bi-trash3-fill"></i></button> | <button type="button" class="btn btn-sm p-3 btn-danger shadow remove-question">Remove Question <i class="bi bi-trash3-fill"></i></button> |
<button type="button" class="btn btn-sm btn-primary shadow m-3 save-question">Save Question</button> <button type="button" class="btn btn-sm btn-primary shadow m-3 save-question"><i class="bi bi-floppy"></i> Save Question</button>
<button type="button" class="btn btn-sm btn-secondary shadow edit-question" style="display: none;">Edit Question</button> <button type="button" class="btn btn-sm btn-primary shadow edit-question" style="display: none;"><i class="bi bi-pencil-square"></i> Edit Question</button>
</div> </div>
} }
</div> </div>
</div> </div>
<button type="button" id="add-question-btn" class="btn btn-md btn-success shadow"><i class="bi bi-plus-square"></i> Create New Question</button> <button type="button" id="add-question-btn" class="btn btn-md btn-success shadow"><i class="bi bi-plus-square"></i> Create New Question</button>
</div> </div>
<div class="mt-3 card-footer"> <div class="mt-3 card-footer">
<button type="submit" class="btn btn-primary shadow">Submit</button> <button type="submit" class="btn btn-primary shadow"> <i class="bi bi-floppy2-fill"></i> Save questionnaire</button>
| <a asp-action="Index" class="btn btn-info shadow">Back to list</a> | <a asp-action="Index" class="btn btn-info shadow">Back to list</a>
</div> </div>
</form> </form>
@ -73,14 +73,16 @@
@section Scripts { @section Scripts {
<script src="https://cdnjs.cloudflare.com/ajax/libs/ckeditor/4.11.4/ckeditor.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/ckeditor/4.11.4/ckeditor.js"></script>
<script> <script>
CKEDITOR.replace("Description"); CKEDITOR.replace("Description");
</script> </script>
@{ @{
<partial name="_ValidationScriptsPartial" /> <partial name="_ValidationScriptsPartial" />
} }
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script> <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
@ -88,12 +90,11 @@
<script> <script>
$(document).ready(function () { $(document).ready(function () {
var questionIndex = @Model.Questions?.Count; var questionIndex = @Model.Questions?.Count;
$("#add-question-btn").click(function () { $("#add-question-btn").click(function () {
var newQuestionHtml = ` var newQuestionHtml = `
<div class="question-group" data-question-index="${questionIndex}"> <div class="question-group" data-question-index="${questionIndex}">
<label>Question ${questionIndex + 1}</label> <label>Question ${questionIndex + 1}</label>
<textarea name="Questions[${questionIndex}].Text" class="form-control"></textarea> <textarea name="Questions[${questionIndex}].Text" class="form-control" placeholder="new question"></textarea>
<br> <br>
<label class=h5>Select question type</label> <label class=h5>Select question type</label>
<select name="Questions[${questionIndex}].Type" class="form-control question-type-${questionIndex}">`; <select name="Questions[${questionIndex}].Type" class="form-control question-type-${questionIndex}">`;
@ -114,17 +115,16 @@
newQuestionHtml += `<div class="answer-group" data-answer-index="0"><hr class="border border-primary border-1 opacity-35">`; newQuestionHtml += `<div class="answer-group" data-answer-index="0"><hr class="border border-primary border-1 opacity-35">`;
newQuestionHtml += `<label>Answer 1</label>`; newQuestionHtml += `<label>Answer 1</label>`;
newQuestionHtml += `<input type="text" name="Questions[${questionIndex}].Answers[0].Text" class="form-control" placeholder="new answer"/><br>`; newQuestionHtml += `<input type="text" name="Questions[${questionIndex}].Answers[0].Text" class="form-control" placeholder="new answer"/><br>`;
newQuestionHtml += `<button type="button" class="btn btn-sm btn-success add-answer shadow mt-2"><i class="bi bi-plus-lg"></i> Add Answer</button>`;
newQuestionHtml += `<button type="button" class="btn btn-sm btn-success add-answer mt-2"><i class="bi bi-plus-lg"></i> Add Answer</button>`;
newQuestionHtml += `<hr class="border m-2">` newQuestionHtml += `<hr class="border m-2">`
newQuestionHtml += `</div> `; newQuestionHtml += `</div> `;
newQuestionHtml += `</div>`; newQuestionHtml += `</div>`;
newQuestionHtml += `</div> `; newQuestionHtml += `</div> `;
// Add Remove Question button // Add Remove Question button
newQuestionHtml += `<button type="button" class="btn btn-sm btn-danger m-4 remove-question"><i class="bi bi-trash3-fill"></i> Remove Question </button>`; newQuestionHtml += `<button type="button" class="btn btn-sm btn-danger shadow m-4 remove-question"><i class="bi bi-trash3-fill"></i> Remove Question </button>`;
newQuestionHtml += `<button type="button" class="btn btn-sm btn-primary save-question">Save Question</button>`; newQuestionHtml += `<button type="button" class="btn btn-sm btn-primary shadow save-question"><i class="bi bi-floppy"></i> Save Question</button>`;
newQuestionHtml += `<button type="button" class="btn btn-sm btn-secondary edit-question" style="display: none;">Edit Question</button>`; newQuestionHtml += `<button type="button" class="btn btn-sm btn-info shadow edit-question" style="display: none;"><i class="bi bi-pencil-square"></i> Edit Question</button>`;
newQuestionHtml += `<hr class="border border-primary border-4 opacity-75 mb-5">` newQuestionHtml += `<hr class="border border-primary border-4 opacity-75 mb-5">`
newQuestionHtml += `</div>`; newQuestionHtml += `</div>`;
@ -160,26 +160,42 @@
}); });
// Save question // Save question
$("#questions-container").on("click", ".save-question", function () { $("#questions-container").on("click", ".save-question", function () {
var questionGroup = $(this).closest('.question-group'); var questionGroup = $(this).closest('.question-group');
questionGroup.find('.edit-question').show(); questionGroup.find('.edit-question').show();
questionGroup.find('.remove-question').hide(); questionGroup.find('.remove-question').hide();
questionGroup.find('.save-question').hide(); questionGroup.find('.save-question').hide();
questionGroup.find('.question-type').hide(); // Hide question type questionGroup.find('.form-control').attr('disabled', true); // Disable question text and answer input fields
questionGroup.find('.question-type').attr('disabled', true); // Disable question type select field
questionGroup.find('.answers-container').slideUp(); questionGroup.find('.answers-container').slideUp();
questionGroup.addClass('collapsed'); questionGroup.addClass('collapsed');
// Show success message
var successMessage = $('<div class="alert alert-success" role="alert">Question created successfully!</div>');
questionGroup.prepend(successMessage);
}); });
// Edit question // Function to edit a question
$("#questions-container").on("click", ".edit-question", function () { $("#questions-container").on("click", ".edit-question", function () {
var questionGroup = $(this).closest('.question-group'); var questionGroup = $(this).closest('.question-group');
questionGroup.find('.save-question').show(); questionGroup.find('.save-question').show();
questionGroup.find('.remove-question').show(); questionGroup.find('.remove-question').show();
questionGroup.find('.edit-question').hide(); questionGroup.find('.edit-question').hide();
questionGroup.find('.question-type').show(); // Show question type questionGroup.find('.form-control').attr('disabled', false); // Enable question text and answer input fields
questionGroup.find('.question-type').attr('disabled', false); // Enable question type select field
questionGroup.find('.answers-container').slideDown(); questionGroup.find('.answers-container').slideDown();
questionGroup.removeClass('collapsed'); questionGroup.removeClass('collapsed');
// Remove any existing success message
questionGroup.find('.alert-success').remove();
}); });
// Enable form fields before form submission
$("form").submit(function () {
$(this).find('.form-control').prop('disabled', false); // Enable all form fields before submission
});
}); });
</script> </script>

View file

@ -7,7 +7,16 @@
<div class="card justify-content-center p-4 shadow rounded"> <div class="card justify-content-center p-4 shadow rounded">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Delete questionnaire</h5> <h5 class="card-title">Delete questionnaire</h5>
<h6 class="text-danger">Are you sure you want to delete this questionnaire: <span class="badge bg-danger p-2 shadow rounded">@Model.Title</span></h6> @* <h6 class="text-danger">Are you sure you want to delete this questionnaire: <span class="badge bg-danger p-2 shadow rounded">@Model.Title</span></h6> *@
<h6 class="text-danger">
Are you sure you want to delete:
<span class="badge bg-danger p-2 shadow rounded">
<span class="item-title ">@Html.Raw(Model.Title.Length >= 30 ? Model.Title.Substring(0, 30) : Model.Title)</span>
<span class="more-title " style="display:none;">@(Model.Title.Length > 30 ? Model.Title.Substring(20) : "")</span>
</span>
<button id="readMoreBtn" type="button" class="btn btn-link">Read More</button>
</h6>
<div class="row"> <div class="row">
<!-- 12 columns for textboxes --> <!-- 12 columns for textboxes -->
@ -55,7 +64,7 @@
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<p id="deleteMessage">Are you sure you want to delete this <span class="badge badge-danger">@Model.Title</span>questionnaire</p> <p id="deleteMessage">Are you sure you want to delete this questionnaire</p>
<p class="text-danger">If you delete, you can't recover it.</p> <p class="text-danger">If you delete, you can't recover it.</p>
<input type="text" class="form-control" id="deleteConfirmation" placeholder="Type the questionnaire name to confirm"> <input type="text" class="form-control" id="deleteConfirmation" placeholder="Type the questionnaire name to confirm">
</div> </div>
@ -143,6 +152,14 @@
} }
}); });
}); });
$(document).ready(function () {
$("#readMoreBtn").click(function () {
$("#readMore").toggle();
$(this).text(function (_, text) {
return text === "Read More" ? "Read Less" : "Read More";
});
});
});
}); });

View file

@ -9,7 +9,6 @@
<div class="container-fluid d-flex justify-content-center"> <div class="container-fluid d-flex justify-content-center">
<div class="card "> <div class="card ">
<div class="card-header"> <div class="card-header">
Details Details
@ -18,8 +17,19 @@
<div class="card-body shadow rounded "> <div class="card-body shadow rounded ">
<div class="card-title"> <div class="card-title">
<h5 class="font-weight-bold">Details of questionnaire <span class="badge bg-light p-2 rounded">@Model.Title</span></h5>
<h4>Questionnaire details</h4>
<br />
<div>
<span class="badge badge-primary shadow m-1 p-2">Questionnaire</span>
</div>
<div>
<span class="badge badge-success shadow m-1 p-2">Question</span>
</div>
<div>
<span class="badge badge-info shadow m-1 p-2">Answer</span>
</div>
</div> </div>
<table class="table table-bordered table-responsive table-hover "> <table class="table table-bordered table-responsive table-hover ">
@ -35,8 +45,29 @@
<tbody> <tbody>
<tr> <tr>
<th scope="row"><span class="badge p-2 m-1 bg-primary shadow-sm rounded">@Model.Id</span></th> <th scope="row"><span class="badge p-2 m-1 bg-primary shadow-sm rounded">@Model.Id</span></th>
<th scope="row"><span class="badge p-2 m-1 bg-primary shadow-sm">@Model.Title</span></th> <th scope="row">
<th scope="row"><span class="badge p-2 m-1 bg-primary shadow-sm">@Html.Raw(@Model.Description)</span></th> <div class="title-container">
<div class="title-text">
<span class="item-title ">@Html.Raw(Model.Title.Length >= 30 ? Model.Title.Substring(0, 30) : Model.Title)</span>
<span class="more-title " style="display:none;">@(Model.Title.Length > 30 ? Model.Title.Substring(20) : "")</span>
<a href="#" id="ReadMore" class="read-more-title-btn ">Read More</a>
</div>
</div>
</th>
<th scope="row">
<div class="description-container">
<div class="description-text">
<span class="item-description">@Html.Raw(Model.Description.Length >= 30 ? Model.Description.Substring(0, 30) : Model.Title)</span>
<span class="more-text " style="display:none;">@(Model.Description.Length > 30 ? Model.Description.Substring(30) : "")</span>
<a href="#" id="ReadMore" class="read-more-btn ">Read More</a>
</div>
</div>
</th>
<td class="h6"> <td class="h6">
<table> <table>
@ -52,7 +83,18 @@
<tr> <tr>
<td> <span class="badge p-2 m-1 bg-success ">@question.Id</span></td> <td> <span class="badge p-2 m-1 bg-success ">@question.Id</span></td>
<td> <td>
<span class="badge p-2 m-1 bg-success ">@question.Text</span> <div class="question-container">
<div class="question-text">
<span class="badge badge-success p-2">
<span class="item-question">@Html.Raw(question.Text.Length >= 30 ? question.Text.Substring(0, 30) : question.Text)</span>
<span class="more-question" style="display:none;">@(question.Text.Length > 30 ? question.Text.Substring(30) : "")</span>
<a href="#" id="ReadMore" class="read-more-btn-question mt-1 text-white ">Read More</a>
</span>
</div>
</div>
</td> </td>
<td> <td>
<span class="badge p-2 m-1 bg-success ">@question.Type</span> <span class="badge p-2 m-1 bg-success ">@question.Type</span>
@ -91,13 +133,76 @@
</table> </table>
<footer> <footer>
<a class="btn btn-primary" asp-action="Index">Back to List</a> <a class="btn btn-primary" asp-action="Index">Back to List</a>
</footer> </footer>
</div> </div>
</div> </div>
</div> </div>
@section Scripts {
<script>
$(document).ready(function () {
$('.read-more-btn').click(function () {
var $descriptionText = $(this).closest('.description-container').find('.description-text');
var $moreText = $descriptionText.find('.more-text');
var $toggleMore = $descriptionText.find('.toggle-more');
if ($moreText.is(':visible')) {
$moreText.slideUp();
$toggleMore.fadeIn();
} else {
$moreText.slideDown();
$toggleMore.fadeOut();
}
$(this).text(function (i, text) {
return text === "Read More" ? "Read Less" : "Read More";
});
});
$('.read-more-title-btn').click(function () {
var $titleText = $(this).closest('.title-container').find('.title-text');
var $moreTitle = $titleText.find('.more-title');
var $toggleMore = $titleText.find('.toggle-more');
if ($moreTitle.is(':visible')) {
$moreTitle.slideUp();
$toggleMore.fadeIn();
} else {
$moreTitle.slideDown();
$toggleMore.fadeOut();
}
$(this).text(function (i, text) {
return text === "Read More" ? "Read Less" : "Read More";
});
});
$('.read-more-btn-question').click(function () {
var $titleText = $(this).closest('.question-container').find('.question-text');
var $moreTitle = $titleText.find('.more-question');
var $toggleMore = $titleText.find('.toggle-more');
if ($moreTitle.is(':visible')) {
$moreTitle.slideUp();
$toggleMore.fadeIn();
} else {
$moreTitle.slideDown();
$toggleMore.fadeOut();
}
$(this).text(function (i, text) {
return text === "Read More" ? "Read Less" : "Read More";
});
});
});
</script>
}

View file

@ -24,7 +24,13 @@
<textarea asp-for="Description" class="form-control"></textarea> <textarea asp-for="Description" class="form-control"></textarea>
<span asp-validation-for="Description" class="text-danger"></span> <span asp-validation-for="Description" class="text-danger"></span>
</div> </div>
<div class="card shadow rounded" id="customCard"> <div class="card shadow rounded" id="customCard">
<div class="text-center">
<h4 class="text-primary font-weight-bold">Edit existing questions or add new question</h4>
</div>
<div id="questionsContainer"> <div id="questionsContainer">
@for (int i = 0; i < Model.Questions.Count; i++) @for (int i = 0; i < Model.Questions.Count; i++)
{ {
@ -44,10 +50,15 @@
</div> </div>
</div> </div>
<input type="hidden" asp-for="Questions[i].Id" /> <input type="hidden" asp-for="Questions[i].Id" />
<div class="question-title"> @* <div class="question-title">
@Model.Questions[i].Text @Model.Questions[i].Text
<button type="button" class="btn btn-primary m-4 btn-sm shadow editQuestion"><i class="bi bi-pencil-square"></i> Edit question</button>| <button type="button" class="btn btn-primary m-4 btn-sm shadow editQuestion"><i class="bi bi-pencil-square"></i> Edit question</button>|
</div> *@
<div class="question-title mt-2">
<span class="item-question">@Html.Raw(Model.Questions[i].Text.Length >= 30 ? Model.Questions[i].Text.Substring(0, 30) : Model.Questions[i].Text)</span>
<span class="more-question" style="display:none;">@Html.Raw(Model.Questions[i].Text.Length >= 30 ? Model.Questions[i].Text.Substring(30) : "")</span>
<button type="button" class="btn btn-primary btn-sm shadow read-more-btn"> Read More</button> | <button type="button" class="btn btn-primary btn-sm shadow editQuestion"><i class="bi bi-pencil-square"></i> Edit </button> | <button type="button" class="btn btn-danger btn-sm shadow removeQuestion"><i class="bi bi-trash"></i> Remove </button>
</div> </div>
<div class="question-details" style="display: none;"> <div class="question-details" style="display: none;">
<div class="form-group"> <div class="form-group">
@ -76,20 +87,22 @@
</div> </div>
<button type="button" class="btn btn-success btn-sm mb-1 shadow addAnswer"><i class="bi bi-plus-square"></i> Add new Answer</button> <button type="button" class="btn btn-success btn-sm mb-1 shadow addAnswer"><i class="bi bi-plus-square"></i> Add new Answer</button>
</div> </div>
<button type="button" class="btn btn-primary btn-ms ml-5 mt-3 shadow saveQuestion" style="display: none;"><i class="bi bi-floppy"></i> Save question</button> <button type="button" class="btn btn-primary btn-sm ml-5 shadow saveQuestion" style="display: none;"><i class="bi bi-floppy"></i> Save question</button>
<!-- Remove Question Button --> <!-- Remove Question Button -->
<div class="d-block"> <div class="d-block">
@Model.Questions[i].Text
<button type="button" class="btn btn-danger btn-sm mt-2 shadow removeQuestion"><i class="bi bi-trash"></i> Remove question</button> <button type="button" class="btn btn-danger btn-sm mt-2 shadow removeQuestion1" style="display:none;"><i class="bi bi-trash"></i> Remove question</button>
</div> <button type="button" class="btn btn-danger btn-sm mt-2 shadow removeQuestion3" style="display:none;"><i class="bi bi-trash"></i> Remove question</button>
</div>
</div> </div>
} }
</div> </div>
</div> </div>
<button type="button" class="btn btn-success btn-sm ml-4 mt-3 shadow" id="addNewQuestion"><i class="bi bi-plus"></i> Add New Question</button> <button type="button" class="btn btn-success btn-sm ml-4 mt-3 shadow" id="addNewQuestion"><i class="bi bi-plus"></i> Add New Question</button>
<div class="m-4"> <div class="m-4">
@ -102,7 +115,23 @@
</div> </div>
</div> </div>
<div class="modal fade" id="confirmDeleteModal" tabindex="-1" aria-labelledby="confirmDeleteModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="confirmDeleteModalLabel">Confirm Deletion</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Are you sure you want to delete this question?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-danger confirm-delete">Delete</button>
</div>
</div>
</div>
</div>
@section Scripts { @section Scripts {
@ -127,11 +156,11 @@
var newAnswerIndex = questionContainer.find('.answers .form-group').length; var newAnswerIndex = questionContainer.find('.answers .form-group').length;
var answerHtml = ` var answerHtml = `
<div class="form-group"> <div class="form-group">
<label class="control-label">Answer</label> <label class="control-label">Answer</label>
<input type="text" name="Questions[${newQuestionIndex}].Answers[${newAnswerIndex}].Text" class="form-control" /> <input type="text" name="Questions[${newQuestionIndex}].Answers[${newAnswerIndex}].Text" class="form-control" placeholder="Enter answer" />
<button type="button" class="btn btn-danger btn-sm mt-1 removeAnswer"><i class="bi bi-trash3"></i></button> <button type="button" class="btn btn-danger btn-sm mt-1 removeAnswer"><i class="bi bi-trash3"></i></button>
</div>`; </div>`;
// Append the new answer to the specific question // Append the new answer to the specific question
questionContainer.find('.answers').append(answerHtml); questionContainer.find('.answers').append(answerHtml);
@ -149,6 +178,8 @@
questionContainer.find('.question-details').show(); questionContainer.find('.question-details').show();
questionContainer.find('.editQuestion').hide(); questionContainer.find('.editQuestion').hide();
questionContainer.find('.saveQuestion').show(); questionContainer.find('.saveQuestion').show();
questionContainer.find('.removeQuestion').show();
questionContainer.find('.removeQuestion1').show();
}); });
// Function to save question details // Function to save question details
@ -159,10 +190,10 @@
var questionText = questionContainer.find('.question-details input[name^="Questions"]').val(); var questionText = questionContainer.find('.question-details input[name^="Questions"]').val();
// Apply styles for success (green text color) // Apply styles for success (green text color)
titleTextElement.css('color', '#28a745'); // Set the success text color // titleTextElement.css('color', '#28a745'); // Set the success text color
// Add checkmark icon before the text // // Add checkmark icon before the text
titleTextElement.prepend('<span class="check-icon">&#x2714; </span>'); // titleTextElement.prepend('<span class="check-icon">&#x2714; </span>');
// Show the original question title // Show the original question title
titleTextElement.show(); titleTextElement.show();
@ -173,143 +204,139 @@
// Show the edit button and hide the save button // Show the edit button and hide the save button
questionContainer.find('.editQuestion').show(); questionContainer.find('.editQuestion').show();
questionContainer.find('.saveQuestion').hide(); questionContainer.find('.saveQuestion').hide();
questionContainer.find('.removeQuestion1').hide();
// // questionContainer.find('.removeQuestion3').show();
// var successMessage = $('<div class="alert alert-success" role="alert">Question updated successfully!</div>');
// $(this).closest('.question').find('.question-title').prepend(successMessage);
// successMessage.fadeIn();
}); });
// Function to remove a question // Function to remove a question
$(document).on('click', '.removeQuestion', function () { $(document).on('click', '.removeQuestion, .removeQuestion1, .removeQuestion3', function () {
$(this).closest('.question').remove(); // Store a reference to the question being removed
}); var questionToRemove = $(this).closest('.question');
// Show the confirmation modal
$('#confirmDeleteModal').modal('show');
// Handle deletion confirmation
$('.confirm-delete').click(function () {
// Remove the question
questionToRemove.remove();
// Hide the modal after deletion
$('#confirmDeleteModal').modal('hide');
});
});
// $(document).on('click', '.removeQuestion1', function () {
// $(this).closest('.question').remove();
// });
// $(document).on('click', '.removeQuestion3', function () {
// $(this).closest('.question').remove();
// });
// Function to add a new question
// Function to add a new question
// Function to add a new question
$('.read-more-btn').click(function () {
var $questionTitle = $(this).closest('.question-title');
var $moreQuestion = $questionTitle.find('.more-question');
var $readMoreBtn = $(this);
if ($moreQuestion.is(':visible')) {
$moreQuestion.hide(); // Hide the "Read More" text
$readMoreBtn.text('Read More'); // Change button text to "Read More"
} else {
$moreQuestion.show(); // Show the "Read More" text
$readMoreBtn.text('Read Less'); // Change button text to "Read Less"
}
});
// Function to add a new question // Function to add a new question
$('#addNewQuestion').click(function () { $('#addNewQuestion').click(function () {
var newQuestionIndex = $('.question').length; var newQuestionIndex = $('.question').length;
var questionHtml = ` var questionHtml = `
<div class="question"> <div class="question">
<div class="question-separator"> <!-- Question separator -->
<!-- Container for the first half of the line --> <div class="question-separator">
<div class="line-container"> <div class="line-container">
<hr class="border border-primary border-4 opacity-75 line-start"> <hr class="border border-primary border-4 opacity-75 line-start">
</div> </div>
<!-- Container for the next question text --> <div class="next-question-container mt-2">
<div class="next-question-container mt-2"> <p><span class="badge badge-primary">NEXT QUESTION</span></p>
<p><span class="badge badge-primary">NEXT QUESTION</span></p> </div>
</div> <div class="line-container">
<!-- Container for the second half of the line --> <hr class="border border-primary border-4 opacity-75 line-end">
<div class="line-container">
<hr class="border border-primary border-4 opacity-75 line-end">
</div>
</div>
<div class="question-title" style="display:none;">
<h6 class="text-success">Question created</h6>
<button type="button" class="btn btn-primary btn-ms ml-5 mt-3 editQuestion"><i class="bi bi-floppy"></i> Edit question</button>
</div>
<div class="question-details">
<div class="form-group">
<label class="control-label">Question</label>
<input type="text" class="form-control" name="Questions[${newQuestionIndex}].Text" placeholder="Enter question text"/>
</div>
<div class="form-group">
<label class="control-label">Question Type</label>
<select class="form-control">
<option value="0">Multiple Choice</option>
<option value="1">Text</option>
</select>
</div>
<div class="answers">
<div class="form-group">
<label class="control-label">Answer</label>
<input type="text" class="form-control" name="Questions[${newQuestionIndex}].Answers[0].Text" placeholder="Enter answer"/>
<button type="button" class="btn btn-danger btn-sm mt-1 removeAnswer"><i class="bi bi-trash3"></i></button>
</div> </div>
</div> </div>
<button type="button" class="btn btn-success btn-sm mb-1 addAnswer"><i class="bi bi-plus-square"></i> Add new Answer</button> <!-- Question title with success message -->
</div> <div class="question-title" style="display:none;">
<button type="button" class="btn btn-primary btn-ms ml-5 mt-3 saveQuestion"><i class="bi bi-floppy"></i> Save question</button>
<div class="d-block"> <button type="button" class="btn btn-primary btn-sm ml-5 mt-2 editQuestion"><i class="bi bi-floppy"></i> Edit question</button>|
<button type="button" class="btn btn-danger btn-sm mt-2 removeQuestion"><i class="bi bi-trash"></i> Remove question</button> <button type="button" class="btn btn-danger btn-sm mt-2 shadow removeQuestion3"><i class="bi bi-trash"></i> Remove question</button>
</div> </div>
</div>`; <!-- Question details -->
<div class="question-details">
<div class="form-group">
<label class="control-label">Question</label>
<input type="text" class="form-control" name="Questions[${newQuestionIndex}].Text" placeholder="Enter question text"/>
</div>
<div class="form-group">
<label class="control-label">Question Type</label>
<select class="form-control" name="Questions[${newQuestionIndex}].Type">
<option value="0">Text</option>
<option value="1">CheckBox</option>
<option value="2">TrueFalse</option>
<option value="3">Multiple_choice</option>
<option value="4">Rating</option>
<option value="5">Likert</option>
<option value="6">Matrix</option>
<option value="7">Open_ended</option>
<option value="8">Demographic</option>
<option value="9">Ranking</option>
<option value="10">Image</option>
<option value="11">Slider</option>
</select>
</div>
<div class="answers">
<div class="form-group">
<label class="control-label">Answer</label>
<input type="text" class="form-control" name="Questions[${newQuestionIndex}].Answers[0].Text" placeholder="Enter answer"/>
<button type="button" class="btn btn-danger btn-sm mt-1 removeAnswer"><i class="bi bi-trash3"></i></button>
</div>
</div>
<button type="button" class="btn btn-success btn-sm ml-5 mt-0 addAnswer"><i class="bi bi-plus-square"></i> Add new Answer</button>
</div>
<!-- Save and remove buttons -->
<div class="d-flex mt-4">
<button type="button" class="btn btn-primary btn-sm ml-5 mt-2 saveQuestion"><i class="bi bi-floppy"></i> Save question</button>
<div class="d-block">
<button type="button" class="btn btn-danger ml-5 btn-sm mt-2 shadow removeQuestion1"><i class="bi bi-trash"></i> Remove question</button>
</div>
</div>
</div>`;
// Append the new question HTML to the container
$('#questionsContainer').append(questionHtml); $('#questionsContainer').append(questionHtml);
// Show success message
// var successMessage = $('<div class="alert alert-success" role="alert">Question created successfully!</div>');
// $('.question-title').prepend(successMessage);
// successMessage.fadeIn().delay(2000).fadeOut();
}); });
}); });
</script> </script>
@* <script>
$(document).ready(function () {
// Function to add a new answer
$(document).on('click', '.addAnswer', function () {
var questionContainer = $(this).closest('.question');
var newQuestionIndex = questionContainer.index();
// Correctly find the length of answers for the specific question
var newAnswerIndex = questionContainer.find('.answers .form-group').length;
var answerHtml = `
<div class="form-group">
<label class="control-label">Answer</label>
<input type="text" name="Questions[${newQuestionIndex}].Answers[${newAnswerIndex}].Text" class="form-control" />
<button type="button" class="btn btn-danger btn-sm mt-1 removeAnswer"><i class="bi bi-trash3"></i></button>
</div>`;
// Append the new answer to the specific question
questionContainer.find('.answers').append(answerHtml);
});
// Function to remove an answer (including dynamically added answers)
$(document).on('click', '.removeAnswer', function () {
$(this).closest('.form-group').remove();
});
// Function to toggle question edit mode
$(document).on('click', '.editQuestion', function () {
var questionContainer = $(this).closest('.question');
questionContainer.find('.question-title').hide();
questionContainer.find('.question-details').show();
questionContainer.find('.editQuestion').hide();
questionContainer.find('.saveQuestion').show();
// Add a line below the editQuestion button
// var lineHtml = '<hr class="border border-primary border-4 opacity-75 mt-3 mb-3">';
// questionContainer.find('.editQuestion').before(lineHtml);
});
// Function to save question details
$(document).on('click', '.saveQuestion', function () {
var questionContainer = $(this).closest('.question');
var titleTextElement = questionContainer.find('.question-title');
// Apply styles for success (green text color)
titleTextElement.css('color', '#28a745'); // Set the success text color
// Add checkmark icon before the text
titleTextElement.prepend('<span class="check-icon">&#x2714; </span>');
// Show the original question title
titleTextElement.show();
// Hide the question details
questionContainer.find('.question-details').hide();
// Show the edit button and hide the save button
questionContainer.find('.editQuestion').show();
questionContainer.find('.saveQuestion').hide();
});
$(document).on('click', '.removeQuestion', function () {
$(this).closest('.question').remove();
});
});
</script> *@
} }

View file

@ -3,6 +3,8 @@
@{ @{
ViewData["Title"] = "Questionnaire"; ViewData["Title"] = "Questionnaire";
} }
<div class="container-fluid d-flex justify-content-center"> <div class="container-fluid d-flex justify-content-center">
<partial name="_Notification" /> <partial name="_Notification" />
@ -33,8 +35,28 @@
<tr class="table-secondary"> <tr class="table-secondary">
<td>@item.Id</td> <td>@item.Id</td>
<td> @item.Title</td> @* <td> @item.Title</td> *@
<td>@Html.Raw(item.Description)</td> <td>
<div class="title-container">
<div class="title-text">
<span class="item-title">@Html.Raw(item.Title.Length >= 30 ? item.Title.Substring(0, 30) : item.Title)</span>
<span class="more-title" style="display:none;">@(item.Title.Length > 30 ? item.Title.Substring(30) : "")</span>
<a href="#" id="ReadMore" class="read-more-title-btn">Read More</a>
</div>
</div>
</td>
@* <td>@Html.Raw(item.Description)</td> *@
<td>
<!-- Display only a portion of the description initially -->
<div class="description-container">
<div class="description-text">
<span class="item-description">@Html.Raw(item.Description.Length >= 30 ? item.Description.Substring(0, 30) : item.Title)</span>
<span class="more-text" style="display:none;">@(item.Description.Length > 30 ? item.Description.Substring(30) : "")</span>
<a href="#" id="ReadMore" class=" read-more-btn">Read More</a>
</div>
</div>
</td>
<td> <td>
@* <button type="button" class="btn btn-primary btn-sm"> @* <button type="button" class="btn btn-primary btn-sm">
@ -80,4 +102,46 @@
</div> </div>
@section Scripts{
<script>
$(document).ready(function () {
$('.read-more-btn').click(function () {
var $descriptionText = $(this).closest('.description-container').find('.description-text');
var $moreText = $descriptionText.find('.more-text');
var $toggleMore = $descriptionText.find('.toggle-more');
if ($moreText.is(':visible')) {
$moreText.slideUp();
$toggleMore.fadeIn();
} else {
$moreText.slideDown();
$toggleMore.fadeOut();
}
$(this).text(function (i, text) {
return text === "Read More" ? "Read Less" : "Read More";
});
});
$('.read-more-title-btn').click(function () {
var $titleText = $(this).closest('.title-container').find('.title-text');
var $moreTitle = $titleText.find('.more-title');
var $toggleMore = $titleText.find('.toggle-more');
if ($moreTitle.is(':visible')) {
$moreTitle.slideUp();
$toggleMore.fadeIn();
} else {
$moreTitle.slideDown();
$toggleMore.fadeOut();
}
$(this).text(function (i, text) {
return text === "Read More" ? "Read Less" : "Read More";
});
});
});
</script>
}

View file

@ -13,6 +13,7 @@ namespace Web.ViewModel.QuestionnaireVM
[Required] [Required]
[Display(Name ="Questionnaire title")] [Display(Name ="Questionnaire title")]
[StringLength(100, ErrorMessage = "Title must be between 1 and 40 characters.", MinimumLength = 1)]
public string? Title { get; set; } public string? Title { get; set; }
[Required] [Required]
public string? Description { get; set; } public string? Description { get; set; }

View file

@ -15,6 +15,7 @@ namespace Web.ViewModel.QuestionnaireVM
} }
public int Id { get; set; } public int Id { get; set; }
[Required] [Required]
[StringLength(100, ErrorMessage = "Title must be between 1 and 40 characters.", MinimumLength = 1)]
public string? Title { get; set; } public string? Title { get; set; }
[Required] [Required]
public string? Description { get; set; } public string? Description { get; set; }

View file

@ -34,7 +34,7 @@
--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
} }
/*_______________________________________________________________________________start of the custom CSS_____________________________________________________________*/
.question { .question {
margin:1rem 2rem 0rem 2rem; margin:1rem 2rem 0rem 2rem;
} }
@ -77,6 +77,60 @@
margin: 0; margin: 0;
} }
/*.description-container {
display: flex;
align-items: center;
}
.description-text {
display: flex;
align-items: center;
}
.item-description {
flex-grow: 1;
white-space: normal;
overflow: hidden;
text-overflow: ellipsis;
}*/
/* Add your custom CSS styles here */
/*.question-container {
display: flex;
align-items: center;
}
.question-text {
display: flex;
align-items: center;
}
.item-question {
flex-grow: 1;
white-space: normal;
overflow: hidden;
text-overflow: ellipsis;
}
.more-question {*/
/* Add your more question styles here */
/*display: none;
}*/
#ReadMore{
margin-top:-13px;
margin-left:10px;
text-decoration:underline;
}
#add-question-btn{
margin:1rem 0 0 2rem;
}
/*_______________________________________________________________________________end of the custom CSS_____________________________________________________________*/
*, *,
*::before, *::before,
*::after { *::after {