diff --git a/Web/Areas/Admin/Controllers/UserResponseStatusController.cs b/Web/Areas/Admin/Controllers/UserResponseStatusController.cs index eafd36b..330b23d 100644 --- a/Web/Areas/Admin/Controllers/UserResponseStatusController.cs +++ b/Web/Areas/Admin/Controllers/UserResponseStatusController.cs @@ -1,10 +1,15 @@ using Data; +using iTextSharp.text; +using iTextSharp.text.pdf; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Model; +using OfficeOpenXml; using Services.Interaces; using Web.ViewModel.QuestionnaireVM; + + namespace Web.Areas.Admin.Controllers { public class UserResponseStatusController : Controller @@ -67,34 +72,269 @@ namespace Web.Areas.Admin.Controllers } - //public async Task UserResponsesStatus(string userEmail) + + [HttpPost] + public async Task DeleteSelected(string[] selectedEmails) + { + if (selectedEmails == null || selectedEmails.Length == 0) + { + return RedirectToAction(nameof(Index)); + } + + var responsesToDelete = await _context.Responses + .Where(r => selectedEmails.Contains(r.UserEmail)) + .ToListAsync(); + + if (responsesToDelete.Any()) + { + _context.Responses.RemoveRange(responsesToDelete); + await _context.SaveChangesAsync(); + } + + return RedirectToAction(nameof(Index)); + } + + + + public async Task GenerateReport(string userEmail, string format) + { + var responses = await _context.Responses + .Include(r => r.Questionnaire) + .Include(r => r.ResponseDetails) + .ThenInclude(rd => rd.Question) + .ThenInclude(q => q.Answers) + .Include(r => r.ResponseDetails) + .ThenInclude(rd => rd.ResponseAnswers) + .Where(r => r.UserEmail == userEmail) + .ToListAsync(); + + if (responses == null || !responses.Any()) + { + return NotFound(); + } + + switch (format.ToLower()) + { + case "pdf": + return GeneratePdfReport(responses); + case "excel": + return GenerateExcelReport(responses); + default: + return BadRequest("Unsupported report format."); + } + } + + + private IActionResult GeneratePdfReport(List responses) + { + var userName = responses.First().UserName; + var userEmail = responses.First().UserEmail; + + var stream = new MemoryStream(); + var document = new Document(PageSize.A4, 50, 50, 25, 25); + var writer = PdfWriter.GetInstance(document, stream); + writer.CloseStream = false; // Prevent the stream from being closed when the document is closed + + document.Open(); + + // Add a title + var titleFont = FontFactory.GetFont(FontFactory.HELVETICA_BOLD, 18, BaseColor.BLACK); + var title = new Paragraph($"Report for {userName} ({userEmail})", titleFont) + { + Alignment = Element.ALIGN_CENTER, + SpacingAfter = 20 + }; + document.Add(title); + + // Add a logo + var logoPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "images", "logo.png"); + if (System.IO.File.Exists(logoPath)) + { + var logo = Image.GetInstance(logoPath); + logo.ScaleToFit(100f, 100f); + logo.Alignment = Image.ALIGN_CENTER; + document.Add(logo); + } + + // Add a table for each response + var headerFont = FontFactory.GetFont(FontFactory.HELVETICA_BOLD, 14, BaseColor.WHITE); + var cellFont = FontFactory.GetFont(FontFactory.HELVETICA, 12, BaseColor.BLACK); + + foreach (var response in responses) + { + var table = new PdfPTable(2) + { + WidthPercentage = 100, + SpacingBefore = 20, + SpacingAfter = 20 + }; + table.SetWidths(new float[] { 1, 3 }); + + var cell = new PdfPCell(new Phrase($"Survey: {response.Questionnaire.Title}", headerFont)) + { + Colspan = 2, + BackgroundColor = new BaseColor(0, 150, 0), + HorizontalAlignment = Element.ALIGN_CENTER, + Padding = 10 + }; + table.AddCell(cell); + + table.AddCell(new PdfPCell(new Phrase("Submitted on:", cellFont)) { Padding = 5 }); + table.AddCell(new PdfPCell(new Phrase(response.SubmissionDate.ToString(), cellFont)) { Padding = 5 }); + + foreach (var detail in response.ResponseDetails) + { + table.AddCell(new PdfPCell(new Phrase("Question:", cellFont)) { Padding = 5 }); + table.AddCell(new PdfPCell(new Phrase(detail.Question.Text, cellFont)) { Padding = 5 }); + + if (detail.QuestionType == QuestionType.Text || detail.QuestionType == QuestionType.Slider || detail.QuestionType == QuestionType.Open_ended) + { + table.AddCell(new PdfPCell(new Phrase("Answer:", cellFont)) { Padding = 5 }); + table.AddCell(new PdfPCell(new Phrase(detail.TextResponse, cellFont)) { Padding = 5 }); + } + else + { + 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)); + table.AddCell(new PdfPCell(new Phrase(answers, cellFont)) { Padding = 5 }); + } + } + + document.Add(table); + } + + document.Close(); + writer.Close(); + + stream.Position = 0; + return File(stream, "application/pdf", $"{userName}_report.pdf"); + } + + + + private IActionResult GenerateExcelReport(List responses) + { + var userName = responses.First().UserName; + var userEmail = responses.First().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 {userName} ({userEmail})"; + 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; + foreach (var response in responses) + { + 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++; + } + row++; + } + + worksheet.Cells.AutoFitColumns(); + + var stream = new MemoryStream(); + package.SaveAs(stream); + stream.Position = 0; + + return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"{userName}_report.xlsx"); + } + } + + + //private IActionResult GenerateExcelReport(List responses) //{ - // var responses = await _context.Responses - // .Include(r => r.Questionnaire) - // .Include(r => r.ResponseDetails) - // .ThenInclude(rd => rd.Question) - // .Include(r => r.ResponseDetails) - - // .ThenInclude(rd => rd.ResponseAnswers) - // .Where(r => r.UserEmail == userEmail) - // .ToListAsync(); - - // if (responses == null || !responses.Any()) - // { - // return NotFound(); - // } - // var userName = responses.First().UserName; + // var userEmail = responses.First().UserEmail; - // var viewModel = new UserResponsesViewModel + // using (var package = new ExcelPackage()) // { - // UserName = userName, - // UserEmail = userEmail, - // Responses = responses - // }; + // var worksheet = package.Workbook.Worksheets.Add("Report"); - // return View(viewModel); + // worksheet.Cells[1, 1].Value = $"Report for {userName} ({userEmail})"; + // worksheet.Cells[2, 1].Value = "Survey"; + // worksheet.Cells[2, 2].Value = "Submitted on"; + // worksheet.Cells[2, 3].Value = "Question"; + // worksheet.Cells[2, 4].Value = "Response"; + + // var row = 3; + // foreach (var response in responses) + // { + // 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++; + // } + // row++; + // } + + // var stream = new MemoryStream(); + // package.SaveAs(stream); + // stream.Position = 0; + + // return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"{userName}_report.xlsx"); + // } //} - } } diff --git a/Web/Areas/Admin/Views/UserResponseStatus/Index.cshtml b/Web/Areas/Admin/Views/UserResponseStatus/Index.cshtml index dfde84e..228130a 100644 --- a/Web/Areas/Admin/Views/UserResponseStatus/Index.cshtml +++ b/Web/Areas/Admin/Views/UserResponseStatus/Index.cshtml @@ -1,36 +1,36 @@ @model IEnumerable @{ - ViewData["Title"] = "User Responses status"; + ViewData["Title"] = "User Responses Status"; } - -
-
+
+ +
-
-

Response status

+ - - - @foreach (var item in Model) { - + - }
+ + Name Email SurveyAction
+ + @item.UserName @item.UserEmail @@ -44,12 +44,11 @@ View Responses status
- +
@@ -57,6 +56,13 @@
- - - +@section Scripts { + +} diff --git a/Web/Areas/Admin/Views/UserResponseStatus/UserResponsesStatus.cshtml b/Web/Areas/Admin/Views/UserResponseStatus/UserResponsesStatus.cshtml index a2dae27..4a67337 100644 --- a/Web/Areas/Admin/Views/UserResponseStatus/UserResponsesStatus.cshtml +++ b/Web/Areas/Admin/Views/UserResponseStatus/UserResponsesStatus.cshtml @@ -40,7 +40,7 @@ justify-content: center; width: 40px; height: 40px; - background-color: #007bff; + background-color: #aed5ff; color: white; border-radius: 50%; font-size: 14px; @@ -56,6 +56,8 @@ } + +

Back to list @@ -63,24 +65,34 @@

-

User Responses

- @Model.UserName (@Model.UserEmail) -
+ +
@Model.UserName (@Model.UserEmail)
+

Total responses: @Model.Responses.Count()

+ + + Generate PDF Report + + + Generate Excel Report + +
+
@foreach (var response in Model.Responses) {
- @response.Questionnaire.Title + @response.Questionnaire.Title
-
Survey: @response.Questionnaire.Title
-

Submitted on: @response.SubmissionDate

+
@response.Questionnaire.Title
+
Submitted on: @response.SubmissionDate
+

Total questions: @response.Questionnaire.Questions.Count()

@@ -154,104 +166,7 @@
-@*
-

- Back to list -

-
-
-

User Responses

- @Model.UserName (@Model.UserEmail) -
- -
- @foreach (var response in Model.Responses) - { -
-
-
Survey: @response.Questionnaire.Title
-

Submitted on: @response.SubmissionDate

- - - - - -
- - - - - - - - - @foreach (var detail in response.ResponseDetails) - { - - - - - } - -
QuestionResponse
@detail.Question.Text - @if (detail.QuestionType == QuestionType.Text || detail.QuestionType == QuestionType.Slider || detail.QuestionType == QuestionType.Open_ended) - { -
    -
  • - Question type - @detail.QuestionType -
  • - -
-
- -
    -
  • - - Answer - @detail.TextResponse -
  • -
- - } - else - { - -
    -
  • - Question type - @detail.QuestionType -
  • - -
-
- -
    - - @foreach (var answer in detail.ResponseAnswers) - { - - -
  • - Answer - @detail.Question.Answers.FirstOrDefault(a => a.Id == answer.AnswerId)?.Text -
  • - } - -
- - } -
-
-
-
- } -
-
-
*@ @section Scripts { diff --git a/Web/Web.csproj b/Web/Web.csproj index 890ab12..8733259 100644 --- a/Web/Web.csproj +++ b/Web/Web.csproj @@ -12,7 +12,9 @@ + + @@ -33,7 +35,6 @@ - diff --git a/Web/wwwroot/Images/logo.png b/Web/wwwroot/Images/logo.png new file mode 100644 index 0000000..5c15acc Binary files /dev/null and b/Web/wwwroot/Images/logo.png differ