Add 'Other' option to questionnaire for custom user input
This commit is contained in:
parent
908e241fd8
commit
d9f9b600d7
16 changed files with 3769 additions and 492 deletions
|
|
@ -21,6 +21,7 @@ namespace Model
|
||||||
[ForeignKey("QuestionId")]
|
[ForeignKey("QuestionId")]
|
||||||
public Question? Question { get; set; }
|
public Question? Question { get; set; }
|
||||||
|
|
||||||
|
public bool IsOtherOption { get; set; } = false;
|
||||||
public string? ConditionJson { get; set; }
|
public string? ConditionJson { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ namespace Model
|
||||||
public QuestionType QuestionType { get; set; }
|
public QuestionType QuestionType { get; set; }
|
||||||
public string? TextResponse { get; set; }
|
public string? TextResponse { get; set; }
|
||||||
public List<ResponseAnswer> ResponseAnswers { get; set; } = new List<ResponseAnswer>();
|
public List<ResponseAnswer> ResponseAnswers { get; set; } = new List<ResponseAnswer>();
|
||||||
|
public string? OtherText { get; set; }
|
||||||
public ResponseStatus Status { get; set; } = ResponseStatus.Shown;
|
public ResponseStatus Status { get; set; } = ResponseStatus.Shown;
|
||||||
public string? SkipReason { get; set; } // Why it was skipped (JSON of condition)
|
public string? SkipReason { get; set; } // Why it was skipped (JSON of condition)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,12 +93,8 @@ namespace Web.Areas.Admin.Controllers
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> Create(QuestionnaireViewModel viewmodel)
|
public async Task<IActionResult> Create(QuestionnaireViewModel viewmodel)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
{
|
{
|
||||||
|
|
||||||
var questionnaire = new Questionnaire
|
var questionnaire = new Questionnaire
|
||||||
{
|
{
|
||||||
Id = viewmodel.Id,
|
Id = viewmodel.Id,
|
||||||
|
|
@ -106,7 +102,6 @@ namespace Web.Areas.Admin.Controllers
|
||||||
Description = viewmodel.Description,
|
Description = viewmodel.Description,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
var questions = viewmodel.Questions;
|
var questions = viewmodel.Questions;
|
||||||
|
|
||||||
foreach (var questionViewModel in viewmodel.Questions)
|
foreach (var questionViewModel in viewmodel.Questions)
|
||||||
|
|
@ -121,30 +116,27 @@ namespace Web.Areas.Admin.Controllers
|
||||||
|
|
||||||
foreach (var answerViewModel in questionViewModel.Answers)
|
foreach (var answerViewModel in questionViewModel.Answers)
|
||||||
{
|
{
|
||||||
|
// Skip empty answers
|
||||||
|
if (string.IsNullOrWhiteSpace(answerViewModel.Text))
|
||||||
|
continue;
|
||||||
|
|
||||||
var answer = new Answer
|
var answer = new Answer
|
||||||
{
|
{
|
||||||
Text = answerViewModel.Text,
|
Text = answerViewModel.Text,
|
||||||
QuestionId = answerViewModel.QuestionId,
|
QuestionId = answerViewModel.QuestionId,
|
||||||
|
IsOtherOption = answerViewModel.IsOtherOption // NEW: Handle IsOtherOption property
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
question.Answers.Add(answer);
|
question.Answers.Add(answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
questionnaire.Questions.Add(question);
|
questionnaire.Questions.Add(question);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_questionnaire.Add(questionnaire);
|
_questionnaire.Add(questionnaire);
|
||||||
await _questionnaire.commitAsync();
|
await _questionnaire.commitAsync();
|
||||||
TempData["Success"] = "Questionnaire created successfully";
|
TempData["Success"] = "Questionnaire created successfully";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return RedirectToAction("Index");
|
return RedirectToAction("Index");
|
||||||
}
|
}
|
||||||
return View(viewmodel);
|
return View(viewmodel);
|
||||||
|
|
@ -201,10 +193,9 @@ namespace Web.Areas.Admin.Controllers
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> Edit(EditQuestionnaireViewModel viewModel)
|
public async Task<IActionResult> Edit(EditQuestionnaireViewModel viewModel)
|
||||||
{
|
{
|
||||||
|
|
||||||
var questionTypes = Enum.GetValues(typeof(QuestionType))
|
var questionTypes = Enum.GetValues(typeof(QuestionType))
|
||||||
.Cast<QuestionType>()
|
.Cast<QuestionType>()
|
||||||
.Select(e => new SelectListItem { Value = e.ToString(), Text = e.ToString() });
|
.Select(e => new SelectListItem { Value = e.ToString(), Text = e.ToString() });
|
||||||
ViewBag.QuestionTypes = questionTypes;
|
ViewBag.QuestionTypes = questionTypes;
|
||||||
|
|
||||||
if (ModelState.IsValid)
|
if (ModelState.IsValid)
|
||||||
|
|
@ -214,7 +205,7 @@ namespace Web.Areas.Admin.Controllers
|
||||||
|
|
||||||
if (existingQuestionnaire == null)
|
if (existingQuestionnaire == null)
|
||||||
{
|
{
|
||||||
return NotFound(); // Or handle not found case appropriately
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the existing questionnaire with the data from the view model
|
// Update the existing questionnaire with the data from the view model
|
||||||
|
|
@ -226,22 +217,13 @@ namespace Web.Areas.Admin.Controllers
|
||||||
// Iterate through existing questions and remove those not found in the view model
|
// Iterate through existing questions and remove those not found in the view model
|
||||||
foreach (var existingQuestion in existingQuestionnaire.Questions.ToList())
|
foreach (var existingQuestion in existingQuestionnaire.Questions.ToList())
|
||||||
{
|
{
|
||||||
// If the ID of the existing question is not found in the view model, remove it
|
|
||||||
if (!viewModel.Questions.Any(q => q.Id == existingQuestion.Id))
|
if (!viewModel.Questions.Any(q => q.Id == existingQuestion.Id))
|
||||||
{
|
{
|
||||||
existingQuestionnaire.Questions.Remove(existingQuestion);
|
existingQuestionnaire.Questions.Remove(existingQuestion);
|
||||||
|
|
||||||
}
|
}
|
||||||
await _questionnaire.Update(existingQuestionnaire);
|
await _questionnaire.Update(existingQuestionnaire);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the questionnaire with the modified list of questions
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var newQuestions = new List<Question>();
|
var newQuestions = new List<Question>();
|
||||||
|
|
||||||
// Update or add new questions
|
// Update or add new questions
|
||||||
|
|
@ -253,11 +235,9 @@ namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
if (existingQuestion != null)
|
if (existingQuestion != null)
|
||||||
{
|
{
|
||||||
var answersToRemove = new List<Answer>();
|
|
||||||
existingQuestion.Text = questionViewModel.Text;
|
existingQuestion.Text = questionViewModel.Text;
|
||||||
existingQuestion.Type = questionViewModel.Type;
|
existingQuestion.Type = questionViewModel.Type;
|
||||||
|
|
||||||
|
|
||||||
foreach (var answerViewModel in questionViewModel.Answers)
|
foreach (var answerViewModel in questionViewModel.Answers)
|
||||||
{
|
{
|
||||||
// Check if the answer already exists
|
// Check if the answer already exists
|
||||||
|
|
@ -265,32 +245,27 @@ namespace Web.Areas.Admin.Controllers
|
||||||
|
|
||||||
if (answerViewModel.Id == 0)
|
if (answerViewModel.Id == 0)
|
||||||
{
|
{
|
||||||
|
// NEW: Add IsOtherOption property when creating new answers
|
||||||
existingQuestion.Answers.Add(new Answer { Text = answerViewModel.Text });
|
existingQuestion.Answers.Add(new Answer
|
||||||
|
{
|
||||||
|
Text = answerViewModel.Text,
|
||||||
|
IsOtherOption = answerViewModel.IsOtherOption
|
||||||
|
});
|
||||||
}
|
}
|
||||||
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)
|
else if (existingAnswer != null)
|
||||||
{
|
{
|
||||||
|
|
||||||
existingAnswer.Text = answerViewModel.Text;
|
existingAnswer.Text = answerViewModel.Text;
|
||||||
|
// NEW: Update IsOtherOption property for existing answers
|
||||||
|
existingAnswer.IsOtherOption = answerViewModel.IsOtherOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Create a new question
|
// Create a new question
|
||||||
|
|
@ -305,52 +280,33 @@ namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(answerViewModel.Text))
|
if (!string.IsNullOrEmpty(answerViewModel.Text))
|
||||||
{
|
{
|
||||||
// Add new answer if text is not null or empty
|
// NEW: Add IsOtherOption property when creating new answers
|
||||||
newQuestion.Answers.Add(new Answer { Text = answerViewModel.Text });
|
newQuestion.Answers.Add(new Answer
|
||||||
|
{
|
||||||
|
Text = answerViewModel.Text,
|
||||||
|
IsOtherOption = answerViewModel.IsOtherOption
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add new question to the list of new questions
|
|
||||||
newQuestions.Add(newQuestion);
|
newQuestions.Add(newQuestion);
|
||||||
}
|
}
|
||||||
|
|
||||||
existingQuestionnaire.Questions.AddRange(newQuestions);
|
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);
|
|
||||||
//}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
await _questionnaire.Update(existingQuestionnaire);
|
await _questionnaire.Update(existingQuestionnaire);
|
||||||
|
|
||||||
TempData["Success"] = "Questionnaire updated successfully";
|
TempData["Success"] = "Questionnaire updated successfully";
|
||||||
return RedirectToAction(nameof(Index));
|
return RedirectToAction(nameof(Index));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If ModelState is not valid, re-display the form with validation errors
|
|
||||||
return View(viewModel);
|
return View(viewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IActionResult Delete(int id)
|
public IActionResult Delete(int id)
|
||||||
{
|
{
|
||||||
|
|
||||||
var questionTypes = Enum.GetValues(typeof(QuestionType)).Cast<QuestionType>();
|
var questionTypes = Enum.GetValues(typeof(QuestionType)).Cast<QuestionType>();
|
||||||
|
|
||||||
ViewBag.QuestionTypes = new SelectList(questionTypes);
|
ViewBag.QuestionTypes = new SelectList(questionTypes);
|
||||||
|
|
@ -358,7 +314,7 @@ namespace Web.Areas.Admin.Controllers
|
||||||
|
|
||||||
if (questionnaire == null)
|
if (questionnaire == null)
|
||||||
{
|
{
|
||||||
return NotFound(); // Or handle not found case appropriately
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
var viewModel = new QuestionnaireViewModel
|
var viewModel = new QuestionnaireViewModel
|
||||||
|
|
@ -375,7 +331,8 @@ namespace Web.Areas.Admin.Controllers
|
||||||
Answers = q.Answers.Select(a => new Answer
|
Answers = q.Answers.Select(a => new Answer
|
||||||
{
|
{
|
||||||
Id = a.Id,
|
Id = a.Id,
|
||||||
Text = a.Text
|
Text = a.Text,
|
||||||
|
IsOtherOption = a.IsOtherOption // NEW: Include IsOtherOption property
|
||||||
}).ToList()
|
}).ToList()
|
||||||
}).ToList()
|
}).ToList()
|
||||||
};
|
};
|
||||||
|
|
@ -422,7 +379,7 @@ namespace Web.Areas.Admin.Controllers
|
||||||
|
|
||||||
if (questionnaire == null)
|
if (questionnaire == null)
|
||||||
{
|
{
|
||||||
return NotFound(); // Or handle not found case appropriately
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
var viewModel = new QuestionnaireViewModel
|
var viewModel = new QuestionnaireViewModel
|
||||||
|
|
@ -439,7 +396,8 @@ namespace Web.Areas.Admin.Controllers
|
||||||
Answers = q.Answers.Select(a => new Answer
|
Answers = q.Answers.Select(a => new Answer
|
||||||
{
|
{
|
||||||
Id = a.Id,
|
Id = a.Id,
|
||||||
Text = a.Text
|
Text = a.Text,
|
||||||
|
IsOtherOption = a.IsOtherOption // NEW: Include IsOtherOption property
|
||||||
}).ToList()
|
}).ToList()
|
||||||
}).ToList()
|
}).ToList()
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,6 @@ using OfficeOpenXml;
|
||||||
using Services.Interaces;
|
using Services.Interaces;
|
||||||
using Web.ViewModel.QuestionnaireVM;
|
using Web.ViewModel.QuestionnaireVM;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace Web.Areas.Admin.Controllers
|
namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
public class UserResponseStatusController : Controller
|
public class UserResponseStatusController : Controller
|
||||||
|
|
@ -17,7 +15,7 @@ namespace Web.Areas.Admin.Controllers
|
||||||
private readonly SurveyContext _context;
|
private readonly SurveyContext _context;
|
||||||
private readonly IUserResponseRepository _userResponse;
|
private readonly IUserResponseRepository _userResponse;
|
||||||
|
|
||||||
public UserResponseStatusController(SurveyContext context,IUserResponseRepository userResponse)
|
public UserResponseStatusController(SurveyContext context, IUserResponseRepository userResponse)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_userResponse = userResponse;
|
_userResponse = userResponse;
|
||||||
|
|
@ -41,7 +39,6 @@ namespace Web.Areas.Admin.Controllers
|
||||||
return View(usersWithQuestionnaires);
|
return View(usersWithQuestionnaires);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<IActionResult> UserResponsesStatus(string userEmail)
|
public async Task<IActionResult> UserResponsesStatus(string userEmail)
|
||||||
{
|
{
|
||||||
var responses = await _context.Responses
|
var responses = await _context.Responses
|
||||||
|
|
@ -72,8 +69,6 @@ namespace Web.Areas.Admin.Controllers
|
||||||
return View(viewModel);
|
return View(viewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> DeleteSelected(string[] selectedEmails)
|
public async Task<IActionResult> DeleteSelected(string[] selectedEmails)
|
||||||
{
|
{
|
||||||
|
|
@ -95,8 +90,6 @@ namespace Web.Areas.Admin.Controllers
|
||||||
return RedirectToAction(nameof(Index));
|
return RedirectToAction(nameof(Index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public async Task<IActionResult> GenerateReport(string userEmail, string format)
|
public async Task<IActionResult> GenerateReport(string userEmail, string format)
|
||||||
{
|
{
|
||||||
var responses = await _context.Responses
|
var responses = await _context.Responses
|
||||||
|
|
@ -125,7 +118,6 @@ namespace Web.Areas.Admin.Controllers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private IActionResult GeneratePdfReport(List<Response> responses)
|
private IActionResult GeneratePdfReport(List<Response> responses)
|
||||||
{
|
{
|
||||||
var userName = responses.First().UserName;
|
var userName = responses.First().UserName;
|
||||||
|
|
@ -197,6 +189,15 @@ namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
table.AddCell(new PdfPCell(new Phrase("Answers:", cellFont)) { Padding = 5 });
|
table.AddCell(new PdfPCell(new Phrase("Answers:", cellFont)) { Padding = 5 });
|
||||||
var answers = string.Join(", ", detail.ResponseAnswers.Select(a => detail.Question.Answers.FirstOrDefault(ans => ans.Id == a.AnswerId)?.Text));
|
var answers = string.Join(", ", detail.ResponseAnswers.Select(a => detail.Question.Answers.FirstOrDefault(ans => ans.Id == a.AnswerId)?.Text));
|
||||||
|
|
||||||
|
// NEW: Include "Other" text if available
|
||||||
|
if (!string.IsNullOrEmpty(detail.OtherText))
|
||||||
|
{
|
||||||
|
answers += string.IsNullOrEmpty(answers)
|
||||||
|
? $"Other: {detail.OtherText}"
|
||||||
|
: $"; Other: {detail.OtherText}";
|
||||||
|
}
|
||||||
|
|
||||||
table.AddCell(new PdfPCell(new Phrase(answers, cellFont)) { Padding = 5 });
|
table.AddCell(new PdfPCell(new Phrase(answers, cellFont)) { Padding = 5 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -211,8 +212,6 @@ namespace Web.Areas.Admin.Controllers
|
||||||
return File(stream, "application/pdf", $"{userName}_report.pdf");
|
return File(stream, "application/pdf", $"{userName}_report.pdf");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private IActionResult GenerateExcelReport(List<Response> responses)
|
private IActionResult GenerateExcelReport(List<Response> responses)
|
||||||
{
|
{
|
||||||
var userName = responses.First().UserName;
|
var userName = responses.First().UserName;
|
||||||
|
|
@ -272,6 +271,15 @@ namespace Web.Areas.Admin.Controllers
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var answers = string.Join(", ", detail.ResponseAnswers.Select(a => detail.Question.Answers.FirstOrDefault(ans => ans.Id == a.AnswerId)?.Text));
|
var answers = string.Join(", ", detail.ResponseAnswers.Select(a => detail.Question.Answers.FirstOrDefault(ans => ans.Id == a.AnswerId)?.Text));
|
||||||
|
|
||||||
|
// NEW: Include "Other" text if available
|
||||||
|
if (!string.IsNullOrEmpty(detail.OtherText))
|
||||||
|
{
|
||||||
|
answers += string.IsNullOrEmpty(answers)
|
||||||
|
? $"Other: {detail.OtherText}"
|
||||||
|
: $"; Other: {detail.OtherText}";
|
||||||
|
}
|
||||||
|
|
||||||
worksheet.Cells[row, 4].Value = answers;
|
worksheet.Cells[row, 4].Value = answers;
|
||||||
}
|
}
|
||||||
row++;
|
row++;
|
||||||
|
|
@ -289,11 +297,6 @@ namespace Web.Areas.Admin.Controllers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public async Task<IActionResult> GenerateQuestionnairePdfReport(int questionnaireId)
|
public async Task<IActionResult> GenerateQuestionnairePdfReport(int questionnaireId)
|
||||||
{
|
{
|
||||||
var response = await _context.Responses
|
var response = await _context.Responses
|
||||||
|
|
@ -390,6 +393,15 @@ namespace Web.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
table.AddCell(new PdfPCell(new Phrase("Answers:", cellFont)) { Padding = 5 });
|
table.AddCell(new PdfPCell(new Phrase("Answers:", cellFont)) { Padding = 5 });
|
||||||
var answers = string.Join(", ", detail.ResponseAnswers.Select(a => detail.Question.Answers.FirstOrDefault(ans => ans.Id == a.AnswerId)?.Text));
|
var answers = string.Join(", ", detail.ResponseAnswers.Select(a => detail.Question.Answers.FirstOrDefault(ans => ans.Id == a.AnswerId)?.Text));
|
||||||
|
|
||||||
|
// NEW: Include "Other" text if available
|
||||||
|
if (!string.IsNullOrEmpty(detail.OtherText))
|
||||||
|
{
|
||||||
|
answers += string.IsNullOrEmpty(answers)
|
||||||
|
? $"Other: {detail.OtherText}"
|
||||||
|
: $"; Other: {detail.OtherText}";
|
||||||
|
}
|
||||||
|
|
||||||
table.AddCell(new PdfPCell(new Phrase(answers, cellFont)) { Padding = 5 });
|
table.AddCell(new PdfPCell(new Phrase(answers, cellFont)) { Padding = 5 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -421,7 +433,6 @@ namespace Web.Areas.Admin.Controllers
|
||||||
return GenerateExcelReportForQuestionnaire(response);
|
return GenerateExcelReportForQuestionnaire(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private IActionResult GenerateExcelReportForQuestionnaire(Response response)
|
private IActionResult GenerateExcelReportForQuestionnaire(Response response)
|
||||||
{
|
{
|
||||||
var userName = response.UserName;
|
var userName = response.UserName;
|
||||||
|
|
@ -445,7 +456,7 @@ namespace Web.Areas.Admin.Controllers
|
||||||
worksheet.Cells[5, 1].Value = $"{userName} ({userEmail})";
|
worksheet.Cells[5, 1].Value = $"{userName} ({userEmail})";
|
||||||
worksheet.Cells[5, 1, 5, 4].Merge = true;
|
worksheet.Cells[5, 1, 5, 4].Merge = true;
|
||||||
worksheet.Cells[5, 1, 5, 4].Style.Font.Size = 15;
|
worksheet.Cells[5, 1, 5, 4].Style.Font.Size = 15;
|
||||||
worksheet.Cells[5, 1, 5, 4].Style.Font.Bold =true;
|
worksheet.Cells[5, 1, 5, 4].Style.Font.Bold = true;
|
||||||
worksheet.Cells[5, 1, 5, 4].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
|
worksheet.Cells[5, 1, 5, 4].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
|
||||||
|
|
||||||
// Add a title
|
// Add a title
|
||||||
|
|
@ -486,6 +497,15 @@ namespace Web.Areas.Admin.Controllers
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var answers = string.Join(", ", detail.ResponseAnswers.Select(a => detail.Question.Answers.FirstOrDefault(ans => ans.Id == a.AnswerId)?.Text));
|
var answers = string.Join(", ", detail.ResponseAnswers.Select(a => detail.Question.Answers.FirstOrDefault(ans => ans.Id == a.AnswerId)?.Text));
|
||||||
|
|
||||||
|
// NEW: Include "Other" text if available
|
||||||
|
if (!string.IsNullOrEmpty(detail.OtherText))
|
||||||
|
{
|
||||||
|
answers += string.IsNullOrEmpty(answers)
|
||||||
|
? $"Other: {detail.OtherText}"
|
||||||
|
: $"; Other: {detail.OtherText}";
|
||||||
|
}
|
||||||
|
|
||||||
worksheet.Cells[row, 4].Value = answers;
|
worksheet.Cells[row, 4].Value = answers;
|
||||||
}
|
}
|
||||||
row++;
|
row++;
|
||||||
|
|
@ -500,81 +520,5 @@ namespace Web.Areas.Admin.Controllers
|
||||||
return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"{response.Questionnaire.Title}_{userEmail}.xlsx");
|
return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"{response.Questionnaire.Title}_{userEmail}.xlsx");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//private IActionResult GenerateExcelReportForQuestionnaire(Response response)
|
|
||||||
//{
|
|
||||||
// var userName = response.UserName;
|
|
||||||
// var userEmail = response.UserEmail;
|
|
||||||
|
|
||||||
// using (var package = new ExcelPackage())
|
|
||||||
// {
|
|
||||||
// var worksheet = package.Workbook.Worksheets.Add("Report");
|
|
||||||
|
|
||||||
// // Add a logo
|
|
||||||
// var logoPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images", "logo.png");
|
|
||||||
// if (System.IO.File.Exists(logoPath))
|
|
||||||
// {
|
|
||||||
// var logo = new FileInfo(logoPath);
|
|
||||||
// var picture = worksheet.Drawings.AddPicture("Logo", logo);
|
|
||||||
// picture.SetPosition(0, 0, 0, 0);
|
|
||||||
// picture.SetSize(300, 70); // Adjust the size as needed
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Add a title
|
|
||||||
// worksheet.Cells[6, 1].Value = $"Report for {response.Questionnaire.Title}";
|
|
||||||
// worksheet.Cells[6, 1, 6, 4].Merge = true;
|
|
||||||
// worksheet.Cells[6, 1, 6, 4].Style.Font.Size = 18;
|
|
||||||
// worksheet.Cells[6, 1, 6, 4].Style.Font.Bold = true;
|
|
||||||
// worksheet.Cells[6, 1, 6, 4].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
|
|
||||||
|
|
||||||
// // Add headers
|
|
||||||
// worksheet.Cells[7, 1].Value = "Survey";
|
|
||||||
// worksheet.Cells[7, 2].Value = "Submitted on";
|
|
||||||
// worksheet.Cells[7, 3].Value = "Question";
|
|
||||||
// worksheet.Cells[7, 4].Value = "Response";
|
|
||||||
|
|
||||||
// using (var range = worksheet.Cells[7, 1, 7, 4])
|
|
||||||
// {
|
|
||||||
// range.Style.Font.Bold = true;
|
|
||||||
// range.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
|
|
||||||
// range.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightGray);
|
|
||||||
// range.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Add data
|
|
||||||
// var row = 8;
|
|
||||||
// worksheet.Cells[row, 1].Value = response.Questionnaire.Title;
|
|
||||||
// worksheet.Cells[row, 2].Value = response.SubmissionDate.ToString();
|
|
||||||
// row++;
|
|
||||||
|
|
||||||
// foreach (var detail in response.ResponseDetails)
|
|
||||||
// {
|
|
||||||
// worksheet.Cells[row, 3].Value = detail.Question.Text;
|
|
||||||
|
|
||||||
// if (detail.QuestionType == QuestionType.Text || detail.QuestionType == QuestionType.Slider || detail.QuestionType == QuestionType.Open_ended)
|
|
||||||
// {
|
|
||||||
// worksheet.Cells[row, 4].Value = detail.TextResponse;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// var answers = string.Join(", ", detail.ResponseAnswers.Select(a => detail.Question.Answers.FirstOrDefault(ans => ans.Id == a.AnswerId)?.Text));
|
|
||||||
// worksheet.Cells[row, 4].Value = answers;
|
|
||||||
// }
|
|
||||||
// row++;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// worksheet.Cells.AutoFitColumns();
|
|
||||||
|
|
||||||
// var stream = new MemoryStream();
|
|
||||||
// package.SaveAs(stream);
|
|
||||||
// stream.Position = 0;
|
|
||||||
|
|
||||||
// return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"{response.Questionnaire.Title}_{userEmail}.xlsx");
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,10 +1,559 @@
|
||||||
|
@model QuestionnaireViewModel
|
||||||
@model QuestionnaireViewModel
|
|
||||||
|
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = "Create";
|
ViewData["Title"] = "Create";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Modern Design Enhancements */
|
||||||
|
@@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--primary-color: #6366f1;
|
||||||
|
--primary-light: #8b5cf6;
|
||||||
|
--primary-dark: #4338ca;
|
||||||
|
--success-color: #10b981;
|
||||||
|
--danger-color: #ef4444;
|
||||||
|
--warning-color: #f59e0b;
|
||||||
|
--info-color: #06b6d4;
|
||||||
|
--gray-50: #f8fafc;
|
||||||
|
--gray-100: #f1f5f9;
|
||||||
|
--gray-200: #e2e8f0;
|
||||||
|
--gray-300: #cbd5e1;
|
||||||
|
--gray-400: #94a3b8;
|
||||||
|
--gray-500: #64748b;
|
||||||
|
--gray-600: #475569;
|
||||||
|
--gray-700: #334155;
|
||||||
|
--gray-800: #1e293b;
|
||||||
|
--gray-900: #0f172a;
|
||||||
|
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||||
|
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||||
|
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||||
|
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
||||||
|
--shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);
|
||||||
|
--border-radius-sm: 8px;
|
||||||
|
--border-radius-md: 12px;
|
||||||
|
--border-radius-lg: 16px;
|
||||||
|
--border-radius-xl: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: linear-gradient(135deg, #f1f5f9 0%, #e2e8f0 100%);
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 1200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enhanced Card Design */
|
||||||
|
.card {
|
||||||
|
background: white;
|
||||||
|
border-radius: var(--border-radius-xl);
|
||||||
|
box-shadow: var(--shadow-2xl);
|
||||||
|
border: 1px solid var(--gray-200);
|
||||||
|
overflow: hidden;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--gray-800);
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
position: relative;
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: 60px;
|
||||||
|
height: 4px;
|
||||||
|
background: linear-gradient(135deg, var(--primary-color), var(--primary-light));
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-body {
|
||||||
|
padding: 3rem;
|
||||||
|
background: var(--gray-50);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-footer {
|
||||||
|
background: white;
|
||||||
|
padding: 2.5rem;
|
||||||
|
border-top: 1px solid var(--gray-200);
|
||||||
|
display: flex;
|
||||||
|
gap: 1.5rem;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Form Enhancements */
|
||||||
|
.mb-3 {
|
||||||
|
margin-bottom: 2rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
border: 2px solid var(--gray-200);
|
||||||
|
border-radius: var(--border-radius-md);
|
||||||
|
padding: 1rem 1.25rem;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
background: white;
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
|
width: 100%;
|
||||||
|
min-height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control:focus {
|
||||||
|
border-color: var(--primary-color);
|
||||||
|
background: white;
|
||||||
|
box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.1), var(--shadow-md);
|
||||||
|
outline: none;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-label {
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--gray-700);
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enhanced Select Styling */
|
||||||
|
select.form-control {
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
background-color: white;
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
|
||||||
|
background-position: right 0.75rem center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 1.25em 1.25em;
|
||||||
|
padding-right: 2.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
select.form-control:focus {
|
||||||
|
background-color: white;
|
||||||
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236366f1' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
|
||||||
|
background-position: right 0.75rem center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 1.25em 1.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
select.form-control option {
|
||||||
|
padding: 0.75rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--gray-900);
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Textarea specific styling */
|
||||||
|
textarea.form-control {
|
||||||
|
min-height: 120px;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Button Enhancements */
|
||||||
|
.btn {
|
||||||
|
border-radius: var(--border-radius-md);
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
border: none;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: -100%;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
|
||||||
|
transition: left 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:hover::before {
|
||||||
|
left: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-light) 100%);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover {
|
||||||
|
background: linear-gradient(135deg, var(--primary-dark) 0%, var(--primary-color) 100%);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: var(--shadow-lg);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-success {
|
||||||
|
background: linear-gradient(135deg, var(--success-color) 0%, #059669 100%);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-success:hover {
|
||||||
|
background: linear-gradient(135deg, #059669 0%, #047857 100%);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: var(--shadow-lg);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-danger {
|
||||||
|
background: linear-gradient(135deg, var(--danger-color) 0%, #dc2626 100%);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-danger:hover {
|
||||||
|
background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: var(--shadow-lg);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-info {
|
||||||
|
background: linear-gradient(135deg, var(--info-color) 0%, #0891b2 100%);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-info:hover {
|
||||||
|
background: linear-gradient(135deg, #0891b2 0%, #0e7490 100%);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: var(--shadow-lg);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-warning {
|
||||||
|
background: linear-gradient(135deg, var(--warning-color) 0%, #d97706 100%);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-warning:hover {
|
||||||
|
background: linear-gradient(135deg, #d97706 0%, #b45309 100%);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: var(--shadow-lg);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Questions Container */
|
||||||
|
#questions-container {
|
||||||
|
background: white;
|
||||||
|
border-radius: var(--border-radius-lg);
|
||||||
|
padding: 3rem;
|
||||||
|
margin: 2rem 0;
|
||||||
|
box-shadow: var(--shadow-xl);
|
||||||
|
border: 1px solid var(--gray-200);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#questions-container::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 4px;
|
||||||
|
background: linear-gradient(90deg, var(--primary-color), var(--primary-light), var(--success-color));
|
||||||
|
}
|
||||||
|
|
||||||
|
#questions-container h3 {
|
||||||
|
font-size: 1.75rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--gray-800);
|
||||||
|
margin-bottom: 3rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Question Group Styling */
|
||||||
|
.question-group {
|
||||||
|
background: var(--gray-50);
|
||||||
|
border-radius: var(--border-radius-lg);
|
||||||
|
padding: 2.5rem;
|
||||||
|
margin-bottom: 2.5rem;
|
||||||
|
border: 2px solid var(--gray-200);
|
||||||
|
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.question-group::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 4px;
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(135deg, var(--primary-color), var(--primary-light));
|
||||||
|
transform: scaleY(0);
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
transform-origin: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
.question-group:hover {
|
||||||
|
border-color: var(--primary-color);
|
||||||
|
box-shadow: var(--shadow-xl);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.question-group:hover::before {
|
||||||
|
transform: scaleY(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.question-group.collapsed {
|
||||||
|
background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);
|
||||||
|
border-color: var(--success-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.question-group label {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--gray-800);
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Answers Container */
|
||||||
|
.answers-container {
|
||||||
|
background: white;
|
||||||
|
border-radius: var(--border-radius-md);
|
||||||
|
padding: 2rem;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
border: 1px solid var(--gray-200);
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.answers-container label {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--gray-800);
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Answer Group Styling */
|
||||||
|
.answer-group {
|
||||||
|
background: var(--gray-50);
|
||||||
|
border-radius: var(--border-radius-md);
|
||||||
|
padding: 1.5rem;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
border: 1px solid var(--gray-200);
|
||||||
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.answer-group:hover {
|
||||||
|
border-color: var(--primary-color);
|
||||||
|
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Other Option Styling */
|
||||||
|
.other-option-group {
|
||||||
|
background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%);
|
||||||
|
border: 2px solid var(--warning-color);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.other-option-group::before {
|
||||||
|
content: "OTHER OPTION";
|
||||||
|
position: absolute;
|
||||||
|
top: -12px;
|
||||||
|
left: 20px;
|
||||||
|
background: var(--warning-color);
|
||||||
|
color: white;
|
||||||
|
padding: 0.375rem 1rem;
|
||||||
|
border-radius: var(--border-radius-sm);
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add Question Button */
|
||||||
|
#add-question-btn {
|
||||||
|
background: linear-gradient(135deg, var(--success-color) 0%, #059669 100%);
|
||||||
|
color: white;
|
||||||
|
padding: 1.25rem 2.5rem;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 700;
|
||||||
|
border-radius: var(--border-radius-lg);
|
||||||
|
margin: 2rem auto;
|
||||||
|
box-shadow: var(--shadow-lg);
|
||||||
|
border: none;
|
||||||
|
display: block;
|
||||||
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#add-question-btn:hover {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
box-shadow: var(--shadow-2xl);
|
||||||
|
background: linear-gradient(135deg, #059669 0%, #047857 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Alert Enhancements */
|
||||||
|
.alert {
|
||||||
|
border-radius: var(--border-radius-md);
|
||||||
|
padding: 1.25rem 1.5rem;
|
||||||
|
margin: 1.5rem 0;
|
||||||
|
border: none;
|
||||||
|
font-weight: 500;
|
||||||
|
box-shadow: var(--shadow-sm);
|
||||||
|
animation: slideDown 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-success {
|
||||||
|
background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%);
|
||||||
|
color: #065f46;
|
||||||
|
border-left: 4px solid var(--success-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-info {
|
||||||
|
background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%);
|
||||||
|
color: #0c4a6e;
|
||||||
|
border-left: 4px solid var(--info-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-danger {
|
||||||
|
background: linear-gradient(135deg, #fee2e2 0%, #fecaca 100%);
|
||||||
|
color: #991b1b;
|
||||||
|
border-left: 4px solid var(--danger-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Horizontal Rules */
|
||||||
|
hr {
|
||||||
|
border: none;
|
||||||
|
height: 2px;
|
||||||
|
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-light) 100%);
|
||||||
|
margin: 2rem 0;
|
||||||
|
border-radius: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr.border-4 {
|
||||||
|
height: 4px;
|
||||||
|
background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-light) 100%);
|
||||||
|
margin: 3rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Container Enhancements */
|
||||||
|
.container-ms {
|
||||||
|
background: white;
|
||||||
|
border-radius: var(--border-radius-md);
|
||||||
|
box-shadow: var(--shadow-md);
|
||||||
|
border: 1px solid var(--gray-200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive Design */
|
||||||
|
@@media (max-width: 768px) {
|
||||||
|
.card-body
|
||||||
|
|
||||||
|
{
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#questions-container {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.question-group {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-footer {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animations */
|
||||||
|
@@keyframes slideDown {
|
||||||
|
from
|
||||||
|
|
||||||
|
{
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-in {
|
||||||
|
animation: fadeIn 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@keyframes fadeIn {
|
||||||
|
from
|
||||||
|
|
||||||
|
{
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enhanced Focus States */
|
||||||
|
.btn:focus,
|
||||||
|
.form-control:focus {
|
||||||
|
outline: 2px solid var(--primary-color);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Typography Enhancements */
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: -0.025em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Icon styling */
|
||||||
|
.bi {
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validation styling */
|
||||||
|
.text-danger {
|
||||||
|
color: var(--danger-color) !important;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<div class="container mt-4">
|
<div class="container mt-4">
|
||||||
<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">
|
||||||
|
|
@ -24,17 +573,17 @@
|
||||||
<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="container p-5 shadow bg-body-tertiary rounded">
|
<div class="container p-5 shadow bg-body-tertiary rounded" id="questions-container">
|
||||||
<div id="questions-container" class="mx-md-3 mx-lg-3 px-md-3 px-lg-3 mx-sm-0 px-sm-0">
|
<div class="mx-md-3 mx-lg-3 px-md-3 px-lg-3 mx-sm-0 px-sm-0">
|
||||||
<h3 class="text-primary font-weight-bold">Create Questions</h3>
|
<h3 class="text-primary font-weight-bold">Create Questions</h3>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@for (int i = 0; i < Model.Questions?.Count; i++)
|
@for (int i = 0; i < Model.Questions?.Count; i++)
|
||||||
{
|
{
|
||||||
<div class="question-group" data-question-index="@i">
|
<div class="question-group fade-in" data-question-index="@i">
|
||||||
<label>Question @(i + 1)</label>
|
<label>Question @(i + 1)</label>
|
||||||
<textarea name="Questions[@i].Text" class="form-control">@Model.Questions[i].Text</textarea>
|
<textarea name="Questions[@i].Text" class="form-control">@Model.Questions[i].Text</textarea>
|
||||||
<select name="Questions[@i].Type" asp-items="ViewBag.QuestionTypes" class="form-control question-type">
|
<select name="Questions[@i].Type" asp-items="ViewBag.QuestionTypes" class="form-control question-type">
|
||||||
|
|
||||||
<!-- Include options for question types... -->
|
<!-- Include options for question types... -->
|
||||||
<div class="container-sm"></div>
|
<div class="container-sm"></div>
|
||||||
</select>
|
</select>
|
||||||
|
|
@ -44,10 +593,12 @@
|
||||||
{
|
{
|
||||||
<div class="answer-group">
|
<div class="answer-group">
|
||||||
<input type="text" name="Questions[@i].Answers[@j].Text" class="form-control" value="@Model.Questions?[i]?.Answers?[j]?.Text" />
|
<input type="text" name="Questions[@i].Answers[@j].Text" class="form-control" value="@Model.Questions?[i]?.Answers?[j]?.Text" />
|
||||||
|
<input type="hidden" name="Questions[@i].Answers[@j].IsOtherOption" value="@Model.Questions?[i]?.Answers?[j]?.IsOtherOption" />
|
||||||
<button type="button" class="btn btn-sm btn-danger shadow remove-answer">Remove Answer</button>
|
<button type="button" class="btn btn-sm btn-danger shadow remove-answer">Remove Answer</button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<button type="button" class="btn btn-sm btn-success shadow add-answer"><i class="bi bi-plus-square"></i> Create Answer</button>
|
<button type="button" class="btn btn-sm btn-success shadow add-answer"><i class="bi bi-plus-square"></i> Create Answer</button>
|
||||||
|
<button type="button" class="btn btn-sm btn-info shadow add-other-option"><i class="bi bi-pencil-square"></i> Add "Other" Option</button>
|
||||||
<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> |
|
||||||
|
|
@ -60,7 +611,7 @@
|
||||||
<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"> <i class="bi bi-floppy2-fill"></i> Save questionnaire</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>
|
||||||
|
|
@ -85,14 +636,15 @@
|
||||||
<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>
|
||||||
|
|
||||||
<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 fade-in" data-question-index="${questionIndex}">
|
||||||
<label>Question ${questionIndex + 1}</label>
|
<label>Question ${questionIndex + 1}</label>
|
||||||
<textarea name="Questions[${questionIndex}].Text" class="form-control" placeholder="new question"></textarea>
|
<textarea name="Questions[${questionIndex}].Text" class="form-control" placeholder="new question"></textarea>
|
||||||
<br>
|
<br>
|
||||||
|
|
@ -108,14 +660,15 @@
|
||||||
newQuestionHtml += `</select>`;
|
newQuestionHtml += `</select>`;
|
||||||
|
|
||||||
// Add answers input fields
|
// Add answers input fields
|
||||||
|
|
||||||
newQuestionHtml += `<div class="container-ms mx-5 py-2 px-5 ">`;
|
newQuestionHtml += `<div class="container-ms mx-5 py-2 px-5 ">`;
|
||||||
newQuestionHtml += `<div class="answers-container" data-question-index="${questionIndex}"><br>`;
|
newQuestionHtml += `<div class="answers-container" data-question-index="${questionIndex}"><br>`;
|
||||||
newQuestionHtml += `<label class="h3">Create Answers:</label>`;
|
newQuestionHtml += `<label class="h3">Create Answers:</label>`;
|
||||||
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 += `<input type="hidden" name="Questions[${questionIndex}].Answers[0].IsOtherOption" value="false"/>`;
|
||||||
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 shadow mt-2"><i class="bi bi-plus-lg"></i> Add Answer</button>`;
|
||||||
|
newQuestionHtml += `<button type="button" class="btn btn-sm btn-info add-other-option shadow mt-2 ml-2"><i class="bi bi-pencil-square"></i> Add "Other" Option</button>`;
|
||||||
newQuestionHtml += `<hr class="border m-2">`
|
newQuestionHtml += `<hr class="border m-2">`
|
||||||
newQuestionHtml += `</div> `;
|
newQuestionHtml += `</div> `;
|
||||||
newQuestionHtml += `</div>`;
|
newQuestionHtml += `</div>`;
|
||||||
|
|
@ -132,15 +685,17 @@
|
||||||
questionIndex++;
|
questionIndex++;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add regular answer
|
||||||
$("#questions-container").on("click", ".add-answer", function () {
|
$("#questions-container").on("click", ".add-answer", function () {
|
||||||
var questionIndex = $(this).closest('.answers-container').data('question-index');
|
var questionIndex = $(this).closest('.answers-container').data('question-index');
|
||||||
var answerIndex = $(this).closest('.answers-container').find('.answer-group').length;
|
var answerIndex = $(this).closest('.answers-container').find('.answer-group').length;
|
||||||
|
|
||||||
var answerGroupHtml = `
|
var answerGroupHtml = `
|
||||||
<div class="answer-group">
|
<div class="answer-group fade-in">
|
||||||
<br>
|
<br>
|
||||||
<label class="control-label">Answer ${answerIndex + 1}</label>
|
<label class="control-label">Answer ${answerIndex + 1}</label>
|
||||||
<input type="text" class="form-control" name="Questions[${questionIndex}].Answers[${answerIndex}].Text" placeholder="new answer"/>
|
<input type="text" class="form-control" name="Questions[${questionIndex}].Answers[${answerIndex}].Text" placeholder="new answer"/>
|
||||||
|
<input type="hidden" name="Questions[${questionIndex}].Answers[${answerIndex}].IsOtherOption" value="false"/>
|
||||||
<button type="button" class="btn btn-danger btn-sm mt-1 remove-answer"><i class="bi bi-trash3-fill"></i></button>
|
<button type="button" class="btn btn-danger btn-sm mt-1 remove-answer"><i class="bi bi-trash3-fill"></i></button>
|
||||||
<br>
|
<br>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
@ -149,6 +704,34 @@
|
||||||
$(this).prev('.answer-group').find('.remove-answer').show();
|
$(this).prev('.answer-group').find('.remove-answer').show();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add "Other" option
|
||||||
|
$("#questions-container").on("click", ".add-other-option", function () {
|
||||||
|
var questionIndex = $(this).closest('.answers-container').data('question-index');
|
||||||
|
var answerIndex = $(this).closest('.answers-container').find('.answer-group').length;
|
||||||
|
|
||||||
|
// Check if "Other" option already exists
|
||||||
|
var existingOther = $(this).closest('.answers-container').find('.other-option-group');
|
||||||
|
if (existingOther.length > 0) {
|
||||||
|
alert('An "Other" option already exists for this question.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var otherOptionHtml = `
|
||||||
|
<div class="answer-group other-option-group fade-in">
|
||||||
|
<br>
|
||||||
|
<label class="control-label"><strong>Other Option ${answerIndex + 1}</strong></label>
|
||||||
|
<div class="alert alert-info" role="alert">
|
||||||
|
<small><i class="bi bi-info-circle"></i> This will allow users to write their own answer</small>
|
||||||
|
</div>
|
||||||
|
<input type="text" class="form-control" name="Questions[${questionIndex}].Answers[${answerIndex}].Text" placeholder="Other (please specify)" value="Other (please specify)"/>
|
||||||
|
<input type="hidden" name="Questions[${questionIndex}].Answers[${answerIndex}].IsOtherOption" value="true"/>
|
||||||
|
<button type="button" class="btn btn-warning btn-sm mt-1 remove-answer"><i class="bi bi-trash3-fill"></i> Remove Other Option</button>
|
||||||
|
<br>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
$(this).before(otherOptionHtml);
|
||||||
|
});
|
||||||
|
|
||||||
// Remove answer dynamically
|
// Remove answer dynamically
|
||||||
$("#questions-container").on("click", ".remove-answer", function () {
|
$("#questions-container").on("click", ".remove-answer", function () {
|
||||||
$(this).closest('.answer-group').remove();
|
$(this).closest('.answer-group').remove();
|
||||||
|
|
@ -160,14 +743,13 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
// 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('.form-control').attr('disabled', true); // Disable question text and answer input fields
|
questionGroup.find('.form-control').attr('disabled', true);
|
||||||
questionGroup.find('.question-type').attr('disabled', true); // Disable question type select field
|
questionGroup.find('.question-type').attr('disabled', true);
|
||||||
questionGroup.find('.answers-container').slideUp();
|
questionGroup.find('.answers-container').slideUp();
|
||||||
questionGroup.addClass('collapsed');
|
questionGroup.addClass('collapsed');
|
||||||
|
|
||||||
|
|
@ -182,8 +764,8 @@
|
||||||
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('.form-control').attr('disabled', false); // Enable question text and answer input fields
|
questionGroup.find('.form-control').attr('disabled', false);
|
||||||
questionGroup.find('.question-type').attr('disabled', false); // Enable question type select field
|
questionGroup.find('.question-type').attr('disabled', false);
|
||||||
questionGroup.find('.answers-container').slideDown();
|
questionGroup.find('.answers-container').slideDown();
|
||||||
questionGroup.removeClass('collapsed');
|
questionGroup.removeClass('collapsed');
|
||||||
|
|
||||||
|
|
@ -193,12 +775,10 @@
|
||||||
|
|
||||||
// Enable form fields before form submission
|
// Enable form fields before form submission
|
||||||
$("form").submit(function () {
|
$("form").submit(function () {
|
||||||
$(this).find('.form-control').prop('disabled', false); // Enable all form fields before submission
|
$(this).find('.form-control').prop('disabled', false);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -98,6 +98,44 @@
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* NEW: Styles for "Other" text responses */
|
||||||
|
.other-text-response {
|
||||||
|
background-color: #fff3cd;
|
||||||
|
border: 1px solid #ffeaa7;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.other-text-label {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #856404;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 0.85em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.other-text-content {
|
||||||
|
color: #495057;
|
||||||
|
font-style: italic;
|
||||||
|
line-height: 1.3;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left: 3px solid #ffc107;
|
||||||
|
}
|
||||||
|
|
||||||
|
.other-option-badge {
|
||||||
|
background-color: #ffc107;
|
||||||
|
color: #212529;
|
||||||
|
font-size: 0.7em;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 3px;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="container-fluid mt-3">
|
<div class="container-fluid mt-3">
|
||||||
|
|
@ -244,11 +282,32 @@
|
||||||
<div class="d-flex flex-wrap gap-1">
|
<div class="d-flex flex-wrap gap-1">
|
||||||
@foreach (var answer in responseDetail.ResponseAnswers)
|
@foreach (var answer in responseDetail.ResponseAnswers)
|
||||||
{
|
{
|
||||||
var answerText = question.Answers.FirstOrDefault(a => a.Id == answer.AnswerId)?.Text;
|
var answerObj = question.Answers.FirstOrDefault(a => a.Id == answer.AnswerId);
|
||||||
<span class="badge bg-success">@answerText</span>
|
var answerText = answerObj?.Text;
|
||||||
|
<span class="badge bg-success">
|
||||||
|
@answerText
|
||||||
|
@if (answerObj?.IsOtherOption == true)
|
||||||
|
{
|
||||||
|
<span class="other-option-badge">Other</span>
|
||||||
|
}
|
||||||
|
</span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@* NEW: Display "Other" text if available *@
|
||||||
|
@if (!string.IsNullOrEmpty(responseDetail.OtherText))
|
||||||
|
{
|
||||||
|
<div class="other-text-response">
|
||||||
|
<div class="other-text-label">
|
||||||
|
<i class="bi bi-pencil-square me-1"></i>
|
||||||
|
Custom "Other" Response:
|
||||||
|
</div>
|
||||||
|
<div class="other-text-content">
|
||||||
|
@responseDetail.OtherText
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -311,10 +370,10 @@
|
||||||
var responsesData = [
|
var responsesData = [
|
||||||
@foreach (var response in Model.Responses)
|
@foreach (var response in Model.Responses)
|
||||||
{
|
{
|
||||||
@foreach (var detail in response.ResponseDetails.Where(d => d.QuestionType == QuestionType.Slider))
|
@foreach (var detail in response.ResponseDetails.Where(d => d.QuestionType == QuestionType.Slider))
|
||||||
{
|
{
|
||||||
@:['@response.Questionnaire.Title - @response.SubmissionDate.ToString("yyyy-MMMM-dd HH:mm")', getDescriptiveValue(@(detail.TextResponse != null ? int.Parse(detail.TextResponse) : 0))],
|
@:['@response.Questionnaire.Title - @response.SubmissionDate.ToString("yyyy-MMMM-dd HH:mm")', getDescriptiveValue(@(detail.TextResponse != null ? int.Parse(detail.TextResponse) : 0))],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -363,21 +422,21 @@
|
||||||
data.addColumn('number', 'Total Answers');
|
data.addColumn('number', 'Total Answers');
|
||||||
|
|
||||||
var userSurveySummaryData = @Html.Raw(JsonConvert.SerializeObject(
|
var userSurveySummaryData = @Html.Raw(JsonConvert.SerializeObject(
|
||||||
Model.Responses
|
Model.Responses
|
||||||
.GroupBy(response => response.UserEmail)
|
.GroupBy(response => response.UserEmail)
|
||||||
.Select(g => new
|
.Select(g => new
|
||||||
{
|
{
|
||||||
UserName = g.First().UserName,
|
UserName = g.First().UserName,
|
||||||
TotalSurveys = g.Count(),
|
TotalSurveys = g.Count(),
|
||||||
TotalQuestions = g.SelectMany(r => r.ResponseDetails).Count(),
|
TotalQuestions = g.SelectMany(r => r.ResponseDetails).Count(),
|
||||||
TotalAnswers = g.SelectMany(r => r.ResponseDetails.SelectMany(rd => rd.ResponseAnswers)).Count()
|
TotalAnswers = g.SelectMany(r => r.ResponseDetails.SelectMany(rd => rd.ResponseAnswers)).Count()
|
||||||
})
|
})
|
||||||
.ToList()
|
.ToList()
|
||||||
));
|
));
|
||||||
|
|
||||||
userSurveySummaryData.forEach(function (row) {
|
userSurveySummaryData.forEach(function (row) {
|
||||||
data.addRow([row.UserName, row.TotalSurveys, row.TotalQuestions, row.TotalAnswers]);
|
data.addRow([row.UserName, row.TotalSurveys, row.TotalQuestions, row.TotalAnswers]);
|
||||||
});
|
});
|
||||||
|
|
||||||
var options = {
|
var options = {
|
||||||
title: 'User Survey Summary',
|
title: 'User Survey Summary',
|
||||||
|
|
@ -395,45 +454,45 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
google.charts.load('current', { packages: ['corechart'] });
|
google.charts.load('current', { packages: ['corechart'] });
|
||||||
google.charts.setOnLoadCallback(drawSurveyQuestionsAnswersSummaryCharts);
|
google.charts.setOnLoadCallback(drawSurveyQuestionsAnswersSummaryCharts);
|
||||||
|
|
||||||
function drawSurveyQuestionsAnswersSummaryCharts() {
|
function drawSurveyQuestionsAnswersSummaryCharts() {
|
||||||
var surveyQuestionsSummaryData = @Html.Raw(JsonConvert.SerializeObject(
|
var surveyQuestionsSummaryData = @Html.Raw(JsonConvert.SerializeObject(
|
||||||
Model.Responses
|
Model.Responses
|
||||||
.GroupBy(response => response.Questionnaire.Title)
|
.GroupBy(response => response.Questionnaire.Title)
|
||||||
.Select(g => new
|
.Select(g => new
|
||||||
{
|
{
|
||||||
SurveyTitle = g.Key,
|
SurveyTitle = g.Key,
|
||||||
SurveyId = g.First().Questionnaire.Id,
|
SurveyId = g.First().Questionnaire.Id,
|
||||||
TotalQuestions = g.SelectMany(r => r.ResponseDetails).Count(),
|
TotalQuestions = g.SelectMany(r => r.ResponseDetails).Count(),
|
||||||
TotalAnswers = g.SelectMany(r => r.ResponseDetails.SelectMany(rd => rd.ResponseAnswers)).Count()
|
TotalAnswers = g.SelectMany(r => r.ResponseDetails.SelectMany(rd => rd.ResponseAnswers)).Count()
|
||||||
})
|
})
|
||||||
.ToList()
|
.ToList()
|
||||||
));
|
));
|
||||||
|
|
||||||
surveyQuestionsSummaryData.forEach(function (row) {
|
surveyQuestionsSummaryData.forEach(function (row) {
|
||||||
drawSingleSurveyChart(row.SurveyTitle, row.SurveyId, row.TotalQuestions, row.TotalAnswers);
|
drawSingleSurveyChart(row.SurveyTitle, row.SurveyId, row.TotalQuestions, row.TotalAnswers);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawSingleSurveyChart(surveyTitle, surveyId, totalQuestions, totalAnswers) {
|
function drawSingleSurveyChart(surveyTitle, surveyId, totalQuestions, totalAnswers) {
|
||||||
var data = new google.visualization.DataTable();
|
var data = new google.visualization.DataTable();
|
||||||
data.addColumn('string', 'Category');
|
data.addColumn('string', 'Category');
|
||||||
data.addColumn('number', 'Count');
|
data.addColumn('number', 'Count');
|
||||||
|
|
||||||
data.addRow(['Questions', totalQuestions]);
|
data.addRow(['Questions', totalQuestions]);
|
||||||
data.addRow(['Answers', totalAnswers]);
|
data.addRow(['Answers', totalAnswers]);
|
||||||
|
|
||||||
var options = {
|
var options = {
|
||||||
|
|
||||||
is3D: true,
|
is3D: true,
|
||||||
titleTextStyle: { color: '#17a2b8', fontSize: 16, bold: true },
|
titleTextStyle: { color: '#17a2b8', fontSize: 16, bold: true },
|
||||||
};
|
};
|
||||||
|
|
||||||
var chart = new google.visualization.PieChart(document.getElementById('survey_questions_answers_summary_chart_div_' + surveyId));
|
var chart = new google.visualization.PieChart(document.getElementById('survey_questions_answers_summary_chart_div_' + surveyId));
|
||||||
chart.draw(data, options);
|
chart.draw(data, options);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
|
|
||||||
|
|
@ -179,7 +179,6 @@ namespace Web.Controllers
|
||||||
}
|
}
|
||||||
catch (System.Text.Json.JsonException ex)
|
catch (System.Text.Json.JsonException ex)
|
||||||
{
|
{
|
||||||
// Log error if needed
|
|
||||||
Console.WriteLine($"Error parsing tracking data: {ex.Message}");
|
Console.WriteLine($"Error parsing tracking data: {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -209,7 +208,10 @@ namespace Web.Controllers
|
||||||
: null,
|
: null,
|
||||||
ResponseAnswers = answeredQuestion.SelectedAnswerIds
|
ResponseAnswers = answeredQuestion.SelectedAnswerIds
|
||||||
.Select(aid => new ResponseAnswer { AnswerId = aid })
|
.Select(aid => new ResponseAnswer { AnswerId = aid })
|
||||||
.ToList()
|
.ToList(),
|
||||||
|
|
||||||
|
// ✅ NEW: Handle Other Text
|
||||||
|
OtherText = GetOtherTextForQuestion(answeredQuestion, dbQuestion)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else if (skippedInfo != null)
|
else if (skippedInfo != null)
|
||||||
|
|
@ -252,6 +254,34 @@ namespace Web.Controllers
|
||||||
return responseDetails;
|
return responseDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ✅ NEW METHOD: Extract other text for a question
|
||||||
|
private string GetOtherTextForQuestion(ResponseQuestionViewModel answeredQuestion, Question dbQuestion)
|
||||||
|
{
|
||||||
|
if (answeredQuestion.OtherTexts == null || !answeredQuestion.OtherTexts.Any())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var otherTexts = new List<string>();
|
||||||
|
|
||||||
|
// Loop through selected answers and check if any are "other" options
|
||||||
|
foreach (var selectedAnswerId in answeredQuestion.SelectedAnswerIds)
|
||||||
|
{
|
||||||
|
// Find the corresponding answer in the database
|
||||||
|
var dbAnswer = dbQuestion.Answers.FirstOrDefault(a => a.Id == selectedAnswerId);
|
||||||
|
|
||||||
|
// If this answer is an "other" option and has custom text
|
||||||
|
if (dbAnswer != null && dbAnswer.IsOtherOption && answeredQuestion.OtherTexts.ContainsKey(selectedAnswerId))
|
||||||
|
{
|
||||||
|
var customText = answeredQuestion.OtherTexts[selectedAnswerId];
|
||||||
|
if (!string.IsNullOrWhiteSpace(customText))
|
||||||
|
{
|
||||||
|
otherTexts.Add($"{dbAnswer.Text}: {customText}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return otherTexts.Any() ? string.Join("; ", otherTexts) : null;
|
||||||
|
}
|
||||||
|
|
||||||
private int GetQuestionNumber(int questionId, List<Question> allQuestions)
|
private int GetQuestionNumber(int questionId, List<Question> allQuestions)
|
||||||
{
|
{
|
||||||
return allQuestions.FindIndex(q => q.Id == questionId) + 1;
|
return allQuestions.FindIndex(q => q.Id == questionId) + 1;
|
||||||
|
|
@ -265,7 +295,11 @@ namespace Web.Controllers
|
||||||
bool hasAnswerResponse = question.SelectedAnswerIds != null &&
|
bool hasAnswerResponse = question.SelectedAnswerIds != null &&
|
||||||
question.SelectedAnswerIds.Any();
|
question.SelectedAnswerIds.Any();
|
||||||
|
|
||||||
return hasTextResponse || hasAnswerResponse;
|
// ✅ NEW: Check for other text responses
|
||||||
|
bool hasOtherTextResponse = question.OtherTexts != null &&
|
||||||
|
question.OtherTexts.Any(kv => !string.IsNullOrWhiteSpace(kv.Value));
|
||||||
|
|
||||||
|
return hasTextResponse || hasAnswerResponse || hasOtherTextResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add this class for JSON deserialization
|
// Add this class for JSON deserialization
|
||||||
|
|
@ -438,7 +472,8 @@ namespace Web.Controllers
|
||||||
{
|
{
|
||||||
Id = a.Id,
|
Id = a.Id,
|
||||||
Text = a.Text,
|
Text = a.Text,
|
||||||
ConditionJson = a.ConditionJson // Add this line
|
IsOtherOption = a.IsOtherOption, // ← ADD THIS LINE!
|
||||||
|
ConditionJson = a.ConditionJson
|
||||||
}).ToList()
|
}).ToList()
|
||||||
}).ToList()
|
}).ToList()
|
||||||
};
|
};
|
||||||
|
|
|
||||||
844
Web/Migrations/20250813151802_AddIsOtherOptionToAnswer.Designer.cs
generated
Normal file
844
Web/Migrations/20250813151802_AddIsOtherOptionToAnswer.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,844 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Web.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(SurveyContext))]
|
||||||
|
[Migration("20250813151802_AddIsOtherOptionToAnswer")]
|
||||||
|
partial class AddIsOtherOptionToAnswer
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "8.0.4")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("RoleNameIndex")
|
||||||
|
.HasFilter("[NormalizedName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoles", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Address", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("CVR")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("City")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Country")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Mobile")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PostalCode")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("State")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Street")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Addresss");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Answer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ConditionJson")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsOtherOption")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<int>("QuestionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Text")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionId");
|
||||||
|
|
||||||
|
b.ToTable("Answers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ApplicationUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||||
|
.HasColumnType("datetimeoffset");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedEmail")
|
||||||
|
.HasDatabaseName("EmailIndex");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedUserName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("UserNameIndex")
|
||||||
|
.HasFilter("[NormalizedUserName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUsers", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Banner", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LinkUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Banners");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Footer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("CreatedBy")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUlr")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastUpdated")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Owner")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Sitecopyright")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UpdatedBy")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Footers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.FooterSocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("FooterId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SocialId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("FooterId", "SocialId");
|
||||||
|
|
||||||
|
b.HasIndex("SocialId");
|
||||||
|
|
||||||
|
b.ToTable("FooterSocialMedias");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Page", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("BannerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("FooterId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Slug")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BannerId");
|
||||||
|
|
||||||
|
b.HasIndex("FooterId");
|
||||||
|
|
||||||
|
b.ToTable("Pages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Question", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("QuestionnaireId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Text")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionnaireId");
|
||||||
|
|
||||||
|
b.ToTable("Questions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Questionnaire", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Questionnaires");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Response", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("QuestionnaireId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("SubmissionDate")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("UserEmail")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionnaireId");
|
||||||
|
|
||||||
|
b.ToTable("Responses");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseAnswer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("AnswerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ResponseDetailId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ResponseDetailId");
|
||||||
|
|
||||||
|
b.ToTable("ResponseAnswers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseDetail", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("QuestionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("QuestionType")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ResponseId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("SkipReason")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("TextResponse")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionId");
|
||||||
|
|
||||||
|
b.HasIndex("ResponseId");
|
||||||
|
|
||||||
|
b.ToTable("ResponseDetails");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.SentNewsletterEamil", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Body")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Geo")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("IpAddress")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsBlocked")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsBounced")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsClicked")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDelivered")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsOpened")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSent")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSpam")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsUnsubscribed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ReceivedActivity")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("RecipientEmail")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("SentDate")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Subject")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SentNewsletterEamils");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.SocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Url")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SocialMedia");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Subscription", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSubscribed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Subscriptions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Answer", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Question", "Question")
|
||||||
|
.WithMany("Answers")
|
||||||
|
.HasForeignKey("QuestionId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Question");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.FooterSocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Footer", "Footer")
|
||||||
|
.WithMany("FooterSocialMedias")
|
||||||
|
.HasForeignKey("FooterId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.SocialMedia", "SocialMedia")
|
||||||
|
.WithMany("FooterSocialMedias")
|
||||||
|
.HasForeignKey("SocialId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Footer");
|
||||||
|
|
||||||
|
b.Navigation("SocialMedia");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Page", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Banner", "banner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.Footer", "footer")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("FooterId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("banner");
|
||||||
|
|
||||||
|
b.Navigation("footer");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Question", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Questionnaire", "Questionnaire")
|
||||||
|
.WithMany("Questions")
|
||||||
|
.HasForeignKey("QuestionnaireId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Questionnaire");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Response", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Questionnaire", "Questionnaire")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("QuestionnaireId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Questionnaire");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseAnswer", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ResponseDetail", "ResponseDetail")
|
||||||
|
.WithMany("ResponseAnswers")
|
||||||
|
.HasForeignKey("ResponseDetailId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("ResponseDetail");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseDetail", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Question", "Question")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("QuestionId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.Response", "Response")
|
||||||
|
.WithMany("ResponseDetails")
|
||||||
|
.HasForeignKey("ResponseId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Question");
|
||||||
|
|
||||||
|
b.Navigation("Response");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Footer", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("FooterSocialMedias");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Question", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Answers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Questionnaire", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Questions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Response", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("ResponseDetails");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseDetail", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("ResponseAnswers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.SocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("FooterSocialMedias");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
Web/Migrations/20250813151802_AddIsOtherOptionToAnswer.cs
Normal file
29
Web/Migrations/20250813151802_AddIsOtherOptionToAnswer.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Web.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddIsOtherOptionToAnswer : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "IsOtherOption",
|
||||||
|
table: "Answers",
|
||||||
|
type: "bit",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "IsOtherOption",
|
||||||
|
table: "Answers");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
847
Web/Migrations/20250813162055_AddOtherTextToResponseDetail.Designer.cs
generated
Normal file
847
Web/Migrations/20250813162055_AddOtherTextToResponseDetail.Designer.cs
generated
Normal file
|
|
@ -0,0 +1,847 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Web.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(SurveyContext))]
|
||||||
|
[Migration("20250813162055_AddOtherTextToResponseDetail")]
|
||||||
|
partial class AddOtherTextToResponseDetail
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "8.0.4")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("RoleNameIndex")
|
||||||
|
.HasFilter("[NormalizedName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoles", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Address", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("CVR")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("City")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Country")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Mobile")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PostalCode")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("State")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Street")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Addresss");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Answer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ConditionJson")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsOtherOption")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<int>("QuestionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Text")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionId");
|
||||||
|
|
||||||
|
b.ToTable("Answers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ApplicationUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||||
|
.HasColumnType("datetimeoffset");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("nvarchar(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedEmail")
|
||||||
|
.HasDatabaseName("EmailIndex");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedUserName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("UserNameIndex")
|
||||||
|
.HasFilter("[NormalizedUserName] IS NOT NULL");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUsers", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Banner", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LinkUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Banners");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Footer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("CreatedBy")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUlr")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastUpdated")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Owner")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Sitecopyright")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UpdatedBy")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Footers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.FooterSocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("FooterId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SocialId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("FooterId", "SocialId");
|
||||||
|
|
||||||
|
b.HasIndex("SocialId");
|
||||||
|
|
||||||
|
b.ToTable("FooterSocialMedias");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Page", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("BannerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("FooterId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Slug")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BannerId");
|
||||||
|
|
||||||
|
b.HasIndex("FooterId");
|
||||||
|
|
||||||
|
b.ToTable("Pages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Question", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("QuestionnaireId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Text")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionnaireId");
|
||||||
|
|
||||||
|
b.ToTable("Questions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Questionnaire", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Questionnaires");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Response", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("QuestionnaireId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("SubmissionDate")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("UserEmail")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionnaireId");
|
||||||
|
|
||||||
|
b.ToTable("Responses");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseAnswer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("AnswerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ResponseDetailId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ResponseDetailId");
|
||||||
|
|
||||||
|
b.ToTable("ResponseAnswers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseDetail", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("OtherText")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("QuestionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("QuestionType")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ResponseId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("SkipReason")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("TextResponse")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("QuestionId");
|
||||||
|
|
||||||
|
b.HasIndex("ResponseId");
|
||||||
|
|
||||||
|
b.ToTable("ResponseDetails");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.SentNewsletterEamil", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Body")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Geo")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("IpAddress")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsBlocked")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsBounced")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsClicked")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsDelivered")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsOpened")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSent")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSpam")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool>("IsUnsubscribed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ReceivedActivity")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("RecipientEmail")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("SentDate")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Subject")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SentNewsletterEamils");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.SocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Url")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SocialMedia");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Subscription", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSubscribed")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Subscriptions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ApplicationUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Answer", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Question", "Question")
|
||||||
|
.WithMany("Answers")
|
||||||
|
.HasForeignKey("QuestionId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Question");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.FooterSocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Footer", "Footer")
|
||||||
|
.WithMany("FooterSocialMedias")
|
||||||
|
.HasForeignKey("FooterId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.SocialMedia", "SocialMedia")
|
||||||
|
.WithMany("FooterSocialMedias")
|
||||||
|
.HasForeignKey("SocialId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Footer");
|
||||||
|
|
||||||
|
b.Navigation("SocialMedia");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Page", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Banner", "banner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("BannerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.Footer", "footer")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("FooterId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("banner");
|
||||||
|
|
||||||
|
b.Navigation("footer");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Question", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Questionnaire", "Questionnaire")
|
||||||
|
.WithMany("Questions")
|
||||||
|
.HasForeignKey("QuestionnaireId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Questionnaire");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Response", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Questionnaire", "Questionnaire")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("QuestionnaireId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Questionnaire");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseAnswer", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.ResponseDetail", "ResponseDetail")
|
||||||
|
.WithMany("ResponseAnswers")
|
||||||
|
.HasForeignKey("ResponseDetailId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("ResponseDetail");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseDetail", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Model.Question", "Question")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("QuestionId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Model.Response", "Response")
|
||||||
|
.WithMany("ResponseDetails")
|
||||||
|
.HasForeignKey("ResponseId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Question");
|
||||||
|
|
||||||
|
b.Navigation("Response");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Footer", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("FooterSocialMedias");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Question", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Answers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Questionnaire", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Questions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.Response", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("ResponseDetails");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.ResponseDetail", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("ResponseAnswers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Model.SocialMedia", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("FooterSocialMedias");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Web.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddOtherTextToResponseDetail : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "OtherText",
|
||||||
|
table: "ResponseDetails",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "OtherText",
|
||||||
|
table: "ResponseDetails");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -209,6 +209,9 @@ namespace Web.Migrations
|
||||||
b.Property<string>("ConditionJson")
|
b.Property<string>("ConditionJson")
|
||||||
.HasColumnType("nvarchar(max)");
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsOtherOption")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
b.Property<int>("QuestionId")
|
b.Property<int>("QuestionId")
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
|
@ -522,6 +525,9 @@ namespace Web.Migrations
|
||||||
|
|
||||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("OtherText")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
b.Property<int>("QuestionId")
|
b.Property<int>("QuestionId")
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
public string? Text { get; set; } // Answer text
|
public string? Text { get; set; } // Answer text
|
||||||
|
|
||||||
public int? Count { get; set; }
|
public int? Count { get; set; }
|
||||||
|
public bool IsOtherOption { get; set; } = false;
|
||||||
public string? ConditionJson { get; set; } // Add this line for conditional logic
|
public string? ConditionJson { get; set; } // Add this line for conditional logic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,5 +16,7 @@ namespace Web.ViewModel.QuestionnaireVM
|
||||||
public List<int> SelectedAnswerIds { get; set; } = new List<int>();
|
public List<int> SelectedAnswerIds { get; set; } = new List<int>();
|
||||||
|
|
||||||
public List<string> SelectedText { get; set; } = new List<string>();
|
public List<string> SelectedText { get; set; } = new List<string>();
|
||||||
|
|
||||||
|
public Dictionary<int, string> OtherTexts { get; set; } = new Dictionary<int, string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,59 @@
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Other Option Styling */
|
||||||
|
.other-option-container {
|
||||||
|
position: relative;
|
||||||
|
background: linear-gradient(135deg, rgba(245, 158, 11, 0.1) 0%, rgba(217, 119, 6, 0.05) 100%);
|
||||||
|
border: 1px solid rgba(245, 158, 11, 0.2);
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 16px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.other-option-badge {
|
||||||
|
background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
|
||||||
|
color: white;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-left: 8px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.other-text-container {
|
||||||
|
margin-top: 12px;
|
||||||
|
padding: 12px;
|
||||||
|
background: var(--surface-secondary);
|
||||||
|
border-radius: 12px;
|
||||||
|
border: 1px solid var(--border-accent);
|
||||||
|
animation: morphIn 0.3s ease;
|
||||||
|
display: none !important; /* Initially hidden */
|
||||||
|
}
|
||||||
|
|
||||||
|
.other-text-container.show {
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.other-text-input {
|
||||||
|
background: var(--surface-glass);
|
||||||
|
border: 1px solid var(--border-subtle);
|
||||||
|
color: var(--text-primary);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
resize: vertical;
|
||||||
|
min-height: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.other-text-input:focus {
|
||||||
|
border-color: var(--accent-primary);
|
||||||
|
box-shadow: 0 0 0 3px rgba(74, 144, 164, 0.15);
|
||||||
|
background: rgba(26, 42, 64, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
/* Next-Gen Buttons */
|
/* Next-Gen Buttons */
|
||||||
.btn {
|
.btn {
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
|
|
@ -1011,9 +1064,34 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@foreach (var answer in question.Answers)
|
@foreach (var answer in question.Answers)
|
||||||
{
|
{
|
||||||
<div class="form-check mb-2">
|
<div class="form-check mb-2 @(answer.IsOtherOption ? "other-option-container" : "")">
|
||||||
<input class="form-check-input" id="question@(i)_answer@(answer.Id)" type="checkbox" name="Questions[@i].SelectedAnswerIds" value="@answer.Id" data-condition="@answer.ConditionJson">
|
<input class="form-check-input @(answer.IsOtherOption ? "other-option-input" : "")"
|
||||||
<label class="form-check-label" for="question@(i)_answer@(answer.Id)">@answer.Text</label>
|
id="question@(i)_answer@(answer.Id)"
|
||||||
|
type="checkbox"
|
||||||
|
name="Questions[@i].SelectedAnswerIds"
|
||||||
|
value="@answer.Id"
|
||||||
|
data-condition="@answer.ConditionJson"
|
||||||
|
data-question-index="@i"
|
||||||
|
data-answer-id="@answer.Id"
|
||||||
|
data-is-other="@answer.IsOtherOption.ToString().ToLower()">
|
||||||
|
<label class="form-check-label" for="question@(i)_answer@(answer.Id)">
|
||||||
|
@answer.Text
|
||||||
|
@if (answer.IsOtherOption)
|
||||||
|
{
|
||||||
|
<span class="other-option-badge">Other Option</span>
|
||||||
|
}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
@if (answer.IsOtherOption)
|
||||||
|
{
|
||||||
|
<div class="other-text-container" id="otherText_@(i)_@(answer.Id)" style="display: none;">
|
||||||
|
<textarea class="form-control other-text-input"
|
||||||
|
name="Questions[@i].OtherTexts[@answer.Id]"
|
||||||
|
id="otherTextArea_@(i)_@(answer.Id)"
|
||||||
|
rows="3"
|
||||||
|
placeholder="Please specify..."></textarea>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1023,9 +1101,34 @@
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
@foreach (var answer in question.Answers)
|
@foreach (var answer in question.Answers)
|
||||||
{
|
{
|
||||||
<div class="form-check mb-2">
|
<div class="form-check mb-2 @(answer.IsOtherOption ? "other-option-container" : "")">
|
||||||
<input class="form-check-input answer-input" type="radio" id="question@(i)_answer@(answer.Id)" name="Questions[@i].SelectedAnswerIds" value="@answer.Id" data-condition="@answer.ConditionJson">
|
<input class="form-check-input answer-input @(answer.IsOtherOption ? "other-option-input" : "")"
|
||||||
<label class="form-check-label" for="question@(i)_answer@(answer.Id)">@answer.Text</label>
|
type="radio"
|
||||||
|
id="question@(i)_answer@(answer.Id)"
|
||||||
|
name="Questions[@i].SelectedAnswerIds"
|
||||||
|
value="@answer.Id"
|
||||||
|
data-condition="@answer.ConditionJson"
|
||||||
|
data-question-index="@i"
|
||||||
|
data-answer-id="@answer.Id"
|
||||||
|
data-is-other="@answer.IsOtherOption.ToString().ToLower()">
|
||||||
|
<label class="form-check-label" for="question@(i)_answer@(answer.Id)">
|
||||||
|
@answer.Text
|
||||||
|
@if (answer.IsOtherOption)
|
||||||
|
{
|
||||||
|
<span class="other-option-badge">Other Option</span>
|
||||||
|
}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
@if (answer.IsOtherOption)
|
||||||
|
{
|
||||||
|
<div class="other-text-container" id="otherText_@(i)_@(answer.Id)" style="display: none;">
|
||||||
|
<textarea class="form-control other-text-input"
|
||||||
|
name="Questions[@i].OtherTexts[@answer.Id]"
|
||||||
|
id="otherTextArea_@(i)_@(answer.Id)"
|
||||||
|
rows="3"
|
||||||
|
placeholder="Please specify..."></textarea>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1232,6 +1335,81 @@
|
||||||
const form = document.getElementById('questionnaireForm');
|
const form = document.getElementById('questionnaireForm');
|
||||||
if (!form) { console.error('Form not found!'); return; }
|
if (!form) { console.error('Form not found!'); return; }
|
||||||
|
|
||||||
|
// ===== OTHER OPTION FUNCTIONALITY =====
|
||||||
|
// Handle showing/hiding text areas for "Other" options
|
||||||
|
function initializeOtherOptions() {
|
||||||
|
console.log('Initializing other options...');
|
||||||
|
|
||||||
|
// Handle checkbox other options
|
||||||
|
$(document).on('change', 'input[type="checkbox"]', function() {
|
||||||
|
console.log('Checkbox changed:', this);
|
||||||
|
const $checkbox = $(this);
|
||||||
|
const isOther = $checkbox.attr('data-is-other') === 'true';
|
||||||
|
|
||||||
|
if (isOther) {
|
||||||
|
console.log('Other checkbox detected');
|
||||||
|
const questionIndex = $checkbox.attr('data-question-index');
|
||||||
|
const answerId = $checkbox.attr('data-answer-id');
|
||||||
|
const $textContainer = $(`#otherText_${questionIndex}_${answerId}`);
|
||||||
|
const $textArea = $(`#otherTextArea_${questionIndex}_${answerId}`);
|
||||||
|
|
||||||
|
console.log('Looking for container:', `#otherText_${questionIndex}_${answerId}`);
|
||||||
|
console.log('Container found:', $textContainer.length);
|
||||||
|
|
||||||
|
if ($checkbox.is(':checked')) {
|
||||||
|
console.log('Showing text container');
|
||||||
|
$textContainer.addClass('show').slideDown(300);
|
||||||
|
$textArea.focus();
|
||||||
|
$textArea.prop('required', true);
|
||||||
|
} else {
|
||||||
|
console.log('Hiding text container');
|
||||||
|
$textContainer.removeClass('show').slideUp(300);
|
||||||
|
$textArea.val('');
|
||||||
|
$textArea.prop('required', false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle radio button other options
|
||||||
|
$(document).on('change', 'input[type="radio"]', function() {
|
||||||
|
console.log('Radio button changed:', this);
|
||||||
|
const $radio = $(this);
|
||||||
|
const questionIndex = $radio.attr('data-question-index');
|
||||||
|
const isOther = $radio.attr('data-is-other') === 'true';
|
||||||
|
|
||||||
|
// First, hide all other text containers for this question
|
||||||
|
if (questionIndex) {
|
||||||
|
console.log('Hiding all other containers for question:', questionIndex);
|
||||||
|
$(`.other-text-container[id^="otherText_${questionIndex}_"]`).removeClass('show').slideUp(300);
|
||||||
|
$(`.other-text-input[id^="otherTextArea_${questionIndex}_"]`).prop('required', false).val('');
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is an other option and it's selected, show its text container
|
||||||
|
if (isOther && $radio.is(':checked')) {
|
||||||
|
console.log('Other radio selected');
|
||||||
|
const answerId = $radio.attr('data-answer-id');
|
||||||
|
const $textContainer = $(`#otherText_${questionIndex}_${answerId}`);
|
||||||
|
const $textArea = $(`#otherTextArea_${questionIndex}_${answerId}`);
|
||||||
|
|
||||||
|
console.log('Showing text container for radio');
|
||||||
|
$textContainer.addClass('show').slideDown(300);
|
||||||
|
$textArea.focus();
|
||||||
|
$textArea.prop('required', true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Debug: List all other option inputs
|
||||||
|
console.log('Other option inputs found:', $('input[data-is-other="true"]').length);
|
||||||
|
$('input[data-is-other="true"]').each(function() {
|
||||||
|
console.log('Other input:', this, 'Question:', $(this).attr('data-question-index'), 'Answer:', $(this).attr('data-answer-id'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize other options functionality when DOM is ready
|
||||||
|
$(document).ready(function() {
|
||||||
|
initializeOtherOptions();
|
||||||
|
});
|
||||||
|
|
||||||
// Tracking
|
// Tracking
|
||||||
let questionsShownArray = [1];
|
let questionsShownArray = [1];
|
||||||
let questionsSkippedArray = [];
|
let questionsSkippedArray = [];
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue