From ab3daa46f6d1f0a1a511833a424a6a4d02e4a4c4 Mon Sep 17 00:00:00 2001 From: Qais Yousuf Date: Fri, 19 Apr 2024 15:11:18 +0200 Subject: [PATCH] Response questionnaire for multiple choice completed --- .../Controllers/OpenAIContentController.cs | 4 +- .../Controllers/QuestionnaireController.cs | 4 +- .../OpenAIContent/GenerateContent.cshtml | 4 +- .../QuestionnaireResponseController.cs | 147 +++++-- .../ResponseAnswerViewModel.cs | 8 + .../ResponseQuestionViewModel.cs | 18 + .../ResponseQuestionnaireViewModel.cs | 17 + .../DisplayQuestionnaire.cshtml | 390 +++++++++--------- Web/Views/_ViewImports.cshtml | 1 + Web/appsettings.json | 6 +- 10 files changed, 358 insertions(+), 241 deletions(-) create mode 100644 Web/ViewModel/QuestionnaireVM/ResponseAnswerViewModel.cs create mode 100644 Web/ViewModel/QuestionnaireVM/ResponseQuestionViewModel.cs create mode 100644 Web/ViewModel/QuestionnaireVM/ResponseQuestionnaireViewModel.cs diff --git a/Web/Areas/Admin/Controllers/OpenAIContentController.cs b/Web/Areas/Admin/Controllers/OpenAIContentController.cs index e7cf7e7..717abb2 100644 --- a/Web/Areas/Admin/Controllers/OpenAIContentController.cs +++ b/Web/Areas/Admin/Controllers/OpenAIContentController.cs @@ -65,7 +65,7 @@ namespace Web.Areas.Admin.Controllers // Prepare request body var requestBody = new { - model = "babbage-002", + model = "gpt-3.5-turbo", prompt = inputText, max_tokens = 100 @@ -77,8 +77,6 @@ namespace Web.Areas.Admin.Controllers // Make HTTP POST request to OpenAI API var response = await httpClient.PostAsync("https://api.openai.com/v1/completions", new StringContent(jsonContent, Encoding.UTF8, "application/json")); - // Check if request was successful - //response.EnsureSuccessStatusCode(); // Read response content string responseBody = await response.Content.ReadAsStringAsync(); diff --git a/Web/Areas/Admin/Controllers/QuestionnaireController.cs b/Web/Areas/Admin/Controllers/QuestionnaireController.cs index 1665029..5e8dc40 100644 --- a/Web/Areas/Admin/Controllers/QuestionnaireController.cs +++ b/Web/Areas/Admin/Controllers/QuestionnaireController.cs @@ -494,9 +494,9 @@ namespace Web.Areas.Admin.Controllers - var completeUrl = $"{Request.Scheme}://{Request.Host}/{questionnairePath}/{viewModel.QuestionnaireId}?token={tokenWithExpiry}"; + //var completeUrl = $"{Request.Scheme}://{Request.Host}/{questionnairePath}/{viewModel.QuestionnaireId}?token={tokenWithExpiry}"; - //var completeUrl = $"{Request.Scheme}://{Request.Host}/{questionnairePath}/{viewModel.QuestionnaireId}"; + var completeUrl = $"{Request.Scheme}://{Request.Host}/{questionnairePath}/{viewModel.QuestionnaireId}"; var toEmail = viewModel.Email; diff --git a/Web/Areas/Admin/Views/OpenAIContent/GenerateContent.cshtml b/Web/Areas/Admin/Views/OpenAIContent/GenerateContent.cshtml index 88e3623..e03903a 100644 --- a/Web/Areas/Admin/Views/OpenAIContent/GenerateContent.cshtml +++ b/Web/Areas/Admin/Views/OpenAIContent/GenerateContent.cshtml @@ -13,8 +13,8 @@
- - + +
diff --git a/Web/Controllers/QuestionnaireResponseController.cs b/Web/Controllers/QuestionnaireResponseController.cs index 3aac4d5..ef04688 100644 --- a/Web/Controllers/QuestionnaireResponseController.cs +++ b/Web/Controllers/QuestionnaireResponseController.cs @@ -1,19 +1,27 @@ -using Microsoft.AspNetCore.Mvc; +using Data; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Model; +using Newtonsoft.Json; using Services.Interaces; using System.Globalization; using System.Security.Cryptography; using System.Text; +using Web.ViewModel.AnswerVM; using Web.ViewModel.QuestionnaireVM; +using Web.ViewModel.QuestionVM; namespace Web.Controllers { public class QuestionnaireResponseController : Controller { private readonly IQuestionnaireRepository _questionnaireRepository; + private readonly SurveyContext _context; - public QuestionnaireResponseController(IQuestionnaireRepository questionnaireRepository) + public QuestionnaireResponseController(IQuestionnaireRepository questionnaireRepository,SurveyContext context) { _questionnaireRepository = questionnaireRepository; + _context = context; } public IActionResult Index() { @@ -28,49 +36,108 @@ namespace Web.Controllers return View(); } - public IActionResult DisplayQuestionnaire(int id, string token) + public IActionResult DisplayQuestionnaire(int id) { - // Check if the token is null or empty - if (string.IsNullOrEmpty(token)) - { - ViewBag.ErrorMessage = "The URL is invalid. Please provide a valid token."; - return View("Error"); - } - - // Split the token to extract the expiration date and time - string[] tokenParts = token.Split('|'); - if (tokenParts.Length != 2) - { - ViewBag.ErrorMessage = "The URL is invalid. Please provide a valid token."; - return View("Error"); - } - - string expiryDateTimeString = tokenParts[1]; - - // Parse the expiration datetime in UTC format - if (!DateTime.TryParseExact(expiryDateTimeString, "yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out DateTime expiryDateTimeUtc)) - { - ViewBag.ErrorMessage = "The URL is invalid. Please provide a valid token."; - return View("Error"); - } - - // Convert the expiration datetime to local time - DateTime expiryDateTimeLocal = expiryDateTimeUtc.ToLocalTime(); - - // Check if the token is expired (accounting for UTC+2 offset) - if (expiryDateTimeLocal < DateTime.Now.AddHours(2)) - { - - return RedirectToAction(nameof(Error)); - } - - // Retrieve the questionnaire using the numeric ID + var questionnaire = _questionnaireRepository.GetQuestionnaireWithQuestionAndAnswer(id); - return View(questionnaire); + return View(MapToViewModel(questionnaire)); + } + [HttpPost] + public IActionResult DisplayQuestionnaire([FromForm] ResponseQuestionnaireViewModel questionnaire) + { + + foreach (var question in questionnaire.Questions) + { + var dbQuestion = _context.Questions.Include(q => q.Answers).FirstOrDefault(q => q.Id == question.Id); + + if (dbQuestion != null) + { + foreach (var selectedId in question.SelectedAnswerIds) + { + var selectedAnswer = dbQuestion.Answers.FirstOrDefault(a => a.Id == selectedId); + if (selectedAnswer != null) + { + Console.WriteLine($"Selected Answer: {selectedAnswer.Text}"); + // Here you could further process each selected answer, e.g., saving user responses + } + } + } + } + return Ok(); + + + } - + private ResponseQuestionnaireViewModel MapToViewModel(Questionnaire questionnaire) + { + var viewModel = new ResponseQuestionnaireViewModel + { + Id = questionnaire.Id, + Title = questionnaire.Title, + Description = questionnaire.Description, + Questions = questionnaire.Questions.Select(q => new ResponseQuestionViewModel + { + Id = q.Id, + Text = q.Text, + Type = q.Type, + Answers = q.Answers.Select(a => new ResponseAnswerViewModel + { + Id = a.Id, + Text = a.Text + }).ToList() + }).ToList() + }; + + return viewModel; + } + + + + } } + + +//// Check if the token is null or empty +//if (string.IsNullOrEmpty(t)) +//{ +// ViewBag.ErrorMessage = "The URL is invalid. Please provide a valid token."; +// return View("Error"); +//} + +//// Split the token to extract the expiration date and time +//string[] tokenParts = t.Split('|'); +//if (tokenParts.Length != 2) +//{ +// ViewBag.ErrorMessage = "The URL is invalid. Please provide a valid token."; +// return View("Error"); +//} + +//string expiryDateTimeString = tokenParts[1]; + +//// Parse the expiration datetime in UTC format +//if (!DateTime.TryParseExact(expiryDateTimeString, "yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out DateTime expiryDateTimeUtc)) +//{ +// ViewBag.ErrorMessage = "The URL is invalid. Please provide a valid token."; +// return View("Error"); +//} + +//// Convert the expiration datetime to local time +//DateTime expiryDateTimeLocal = expiryDateTimeUtc.ToLocalTime(); + +//// Check if the token is expired (accounting for UTC+2 offset) +//if (expiryDateTimeLocal < DateTime.Now.AddHours(2)) +//{ + +// return RedirectToAction(nameof(Error)); +//} + +// Retrieve the questionnaire using the numeric ID + + + + + diff --git a/Web/ViewModel/QuestionnaireVM/ResponseAnswerViewModel.cs b/Web/ViewModel/QuestionnaireVM/ResponseAnswerViewModel.cs new file mode 100644 index 0000000..14acf22 --- /dev/null +++ b/Web/ViewModel/QuestionnaireVM/ResponseAnswerViewModel.cs @@ -0,0 +1,8 @@ +namespace Web.ViewModel.QuestionnaireVM +{ + public class ResponseAnswerViewModel + { + public int Id { get; set; } // Answer ID + public string? Text { get; set; } // Answer text + } +} diff --git a/Web/ViewModel/QuestionnaireVM/ResponseQuestionViewModel.cs b/Web/ViewModel/QuestionnaireVM/ResponseQuestionViewModel.cs new file mode 100644 index 0000000..f309f9b --- /dev/null +++ b/Web/ViewModel/QuestionnaireVM/ResponseQuestionViewModel.cs @@ -0,0 +1,18 @@ +using Model; +using Web.ViewModel.AnswerVM; + +namespace Web.ViewModel.QuestionnaireVM +{ + public class ResponseQuestionViewModel + { + public int Id { get; set; } // Question ID + public string? Text { get; set; } // Question text + public QuestionType Type { get; set; } // Question type + + // List of selectable answers + public List Answers { get; set; } = new List(); + + // IDs of selected answers, used for submitting form data + public List SelectedAnswerIds { get; set; } = new List(); + } +} diff --git a/Web/ViewModel/QuestionnaireVM/ResponseQuestionnaireViewModel.cs b/Web/ViewModel/QuestionnaireVM/ResponseQuestionnaireViewModel.cs new file mode 100644 index 0000000..259946b --- /dev/null +++ b/Web/ViewModel/QuestionnaireVM/ResponseQuestionnaireViewModel.cs @@ -0,0 +1,17 @@ +using Web.ViewModel.QuestionVM; + +namespace Web.ViewModel.QuestionnaireVM +{ + public class ResponseQuestionnaireViewModel + { + + public int Id { get; set; } // Questionnaire ID + public string? Title { get; set; } // Title of the questionnaire + public string? Description { get; set; } // Description of the questionnaire + + // Collection of questions + public List Questions { get; set; } = new List(); + + + } +} diff --git a/Web/Views/QuestionnaireResponse/DisplayQuestionnaire.cshtml b/Web/Views/QuestionnaireResponse/DisplayQuestionnaire.cshtml index 6ca85a0..4496c0a 100644 --- a/Web/Views/QuestionnaireResponse/DisplayQuestionnaire.cshtml +++ b/Web/Views/QuestionnaireResponse/DisplayQuestionnaire.cshtml @@ -1,4 +1,4 @@ -@model Questionnaire +@model ResponseQuestionnaireViewModel @{ ViewData["Title"] = "DisplayQuestionnaire"; Layout = "~/Views/Shared/_QuestionnaireResponse.cshtml"; @@ -124,12 +124,17 @@ -
-
+
+ + + + + +

@Model.Title

+

@Html.Raw(Model.Description)

-

@Model.Title

-

@Html.Raw(Model.Description)

+
@@ -141,7 +146,7 @@ var question = Model.Questions[i]; string stepClass = i == 0 ? "active" : ""; // Adjusted the index to start from the first question
- @((i + 1)). + @((i + 1)). @question.Type
} @@ -149,18 +154,28 @@
- - @for (int i = 0; i < Model.Questions.Count; i++) + @for (int i = 0; i < Model.Questions.Count; i++) + { + var question = Model.Questions[i]; + + + + + @for (int j = 0; j < question.Answers.Count; j++) { - var question = Model.Questions[i]; -
-

@(i + 1). @question.Text

-
+ var answer = question.Answers[j]; + + + + } +
+

@(i + 1). @question.Text

+
@switch (question.Type) { case QuestionType.Text:
- +
break; case QuestionType.CheckBox: @@ -173,32 +188,34 @@ @foreach (var answer in question.Answers) {
- -
+ } +
break; case QuestionType.TrueFalse:
- +
- +
break; case QuestionType.Open_ended: - + break; case QuestionType.Image: - + break; case QuestionType.Slider: - + 50 break; case QuestionType.Rating: -
- @foreach (var answer in question.Answers) - { - @* @answer.Id *@ - - - } -
- +
+ @foreach (var answer in question.Answers) + { + + } +
break; default: break; } - @* @switch (question.Type) - { - case QuestionType.Text: -
- -
- break; - case QuestionType.CheckBox: - case QuestionType.Multiple_choice: - case QuestionType.Rating: - case QuestionType.Likert: - case QuestionType.Matrix: - case QuestionType.Demographic: - case QuestionType.Ranking: -
- @foreach (var answer in question.Answers) - { -
- - -
- } -
- break; - case QuestionType.TrueFalse: -
- - -
-
- - -
- break; - case QuestionType.Open_ended: - - break; - case QuestionType.Image: - - break; - case QuestionType.Slider: - - 50 - - break; - - default: - - break; - } *@ -
- - -
- @if (i > 0) - { - - } - @if (i < Model.Questions.Count - 1) - { - - } -
-
- } +
+ @if (i > 0) + { + + } + @if (i < Model.Questions.Count - 1) + { + + } +
+
+ } + + - -
+
- - -
- - + + + @section Scripts { @@ -317,106 +269,158 @@ } + - } diff --git a/Web/Views/_ViewImports.cshtml b/Web/Views/_ViewImports.cshtml index 72a941f..341d088 100644 --- a/Web/Views/_ViewImports.cshtml +++ b/Web/Views/_ViewImports.cshtml @@ -1,5 +1,6 @@ @using Web @using Model @using Web.Models +@using Web.ViewModel.QuestionnaireVM @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @addTagHelper *,Web diff --git a/Web/appsettings.json b/Web/appsettings.json index 10b9cb6..08b448f 100644 --- a/Web/appsettings.json +++ b/Web/appsettings.json @@ -21,6 +21,10 @@ "MailJet": { "ApiKey": "f545eee3a4743464b9d25fb9c5ab3f6c", "SecretKey": "9fa430ef00873fdefe333fdc40ee3f8f" + }, + "OpenAI": { + "ApiKey": "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" + } - + }