Sending the survey to multiple users created

This commit is contained in:
Qais Yousuf 2024-05-01 17:51:38 +02:00
parent 644893ded8
commit d733b2cdb1
6 changed files with 167 additions and 118 deletions

View file

@ -465,120 +465,69 @@ namespace Web.Areas.Admin.Controllers
{
if (ModelState.IsValid)
{
var questionnairePath = _configuration["Email:Questionnaire"];
int surveyId = viewModel.QuestionnaireId;
var userEmailEncoded = HttpUtility.UrlEncode(viewModel.Email);
DateTime currentDateTime;
if (viewModel.ExpirationDateTime.HasValue)
{
currentDateTime = viewModel.ExpirationDateTime.Value;
}
else
{
currentDateTime = DateTime.Now;
}
// Calculate the expiration date and time by adding 5 minutes to the current date and time
DateTime expiryDateTime = currentDateTime;
// Generate a unique token, for example, using a cryptographic library or a GUID
DateTime currentDateTime = viewModel.ExpirationDateTime.HasValue ? viewModel.ExpirationDateTime.Value : DateTime.Now;
DateTime expiryDateTime = currentDateTime; // This line might need adjustment if you are actually setting an expiry.
string token = Guid.NewGuid().ToString();
// Append the expiration date and time to the token (you might want to encrypt it for security)
string tokenWithExpiry = $"{token}|{expiryDateTime.ToString("yyyy-MM-ddTHH:mm:ssZ")}";
var completeUrl = $"{Request.Scheme}://{Request.Host}/{questionnairePath}/{viewModel.QuestionnaireId}?t={tokenWithExpiry}&E={userEmailEncoded}";
//var completeUrl = $"{Request.Scheme}://{Request.Host}/{questionnairePath}/{viewModel.QuestionnaireId}?t={tokenWithExpiry}&E={userEmail}";
//var completeUrl = $"{Request.Scheme}://{Request.Host}/{questionnairePath}/{viewModel.QuestionnaireId}";
var toEmail = viewModel.Email;
var emailList = viewModel.Emails.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(email => email.Trim())
.ToList();
var question = _questionnaire.GetQuesById(viewModel.Id);
var subject = question.Title;
// Construct the email body with HTML formatting
bool allEmailsSent = true;
foreach (var email in emailList)
{
var userName = email.Substring(0, email.IndexOf('@')); // This assumes the email is valid and contains an '@'
userName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(userName.Replace(".", " ")); // Optional: Improve formatting, replace dots and capitalize names
var userEmailEncoded = HttpUtility.UrlEncode(email);
var completeUrl = $"{Request.Scheme}://{Request.Host}/{questionnairePath}/{viewModel.QuestionnaireId}?t={tokenWithExpiry}&E={userEmailEncoded}";
string emailBody = $@"
<html>
<head>
<style>
/* Inline CSS styles */
body {{
font-family: Arial, sans-serif;
}}
.container {{
max-width: 600px;
margin: 0 auto;
padding: 20px;
border: 0.5px solid #ccc;
border-radius: 5px;
background-color: #f9f9f9;
}}
.button {{
display: inline-block;
padding: 10px 20px;
background-color: #007bff;
color: #ffffff;
text-decoration: none;
border-radius: 4px;
}}
.button:hover {{
background-color: #0056b3;
}}
body {{ font-family: Arial, sans-serif; }}
.container {{ max-width: 600px; margin: 0 auto; padding: 20px; border: 0.5px solid #ccc; border-radius: 5px; background-color: #f9f9f9; }}
.button {{ display: inline-block; padding: 10px 20px; background-color: #007bff; color: #ffffff; text-decoration: none; border-radius: 4px; }}
.button:hover {{ background-color: #0056b3; }}
</style>
</head>
<body>
<div class='container'>
<h4>Hey {viewModel.Name},</h4>
<h4>Hey {userName},</h4>
<h5>{subject}</h5>
<p>Thank you for participating in our survey. Your feedback is valuable to us.</p>
<p>Please click the button below to start the survey:</p>
<p class=""text-danger"">The survey will be expire :{expiryDateTime.ToLongDateString()} Time: {expiryDateTime.ToShortTimeString()} </p>
<p class='text-danger'>The survey will expire: {expiryDateTime.ToLongDateString()} Time: {expiryDateTime.ToShortTimeString()}</p>
<div style='text-align: center;'>
<a href='{completeUrl}' class='button'>Start Survey</a>
<br>
</div><br>
<p><strong>Søren Eggert Lundsteen Olsen</strong><br>
Seosoft ApS<br>
<hr>
Hovedgaden 3
Jordrup<br>
Hovedgaden 3 Jordrup<br>
Kolding 6064<br>
Denmark</p>
</div>
</body>
</html>";
// Call the SendConfirmationEmailAsync method to send the email
var emailSend = new EmailToSend(toEmail, subject, emailBody);
var emailSend = new EmailToSend(email, subject, emailBody);
bool emailSent = await _emailServices.SendConfirmationEmailAsync(emailSend);
if (emailSent)
if (!emailSent)
{
// Email sent successfully
// You can redirect to a success page or return a success message
TempData["Success"] = "Questionnaire sent successfully";
return RedirectToAction(nameof(Index));
allEmailsSent = false;
ModelState.AddModelError(string.Empty, "Failed to send questionnaire via email to: " + email);
}
else
}
if (allEmailsSent)
{
// Email failed to send
// You can return an error message or handle it as needed
ModelState.AddModelError(string.Empty, "Failed to send questionnaire via email.");
TempData["Success"] = "Questionnaire sent successfully to all recipients.";
return RedirectToAction(nameof(Index));
}
}

View file

@ -4,7 +4,8 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Model;
using Web.ViewModel.QuestionnaireVM;
using Web.ViewModel.QuestionVM;
using System.IO;
namespace Web.Areas.Admin.Controllers
{
@ -109,6 +110,35 @@ namespace Web.Areas.Admin.Controllers
}
//[HttpGet]
//public IActionResult GenerateReport(int id)
//{
// var viewModel = GetQuestionnaireData(id);
// if (viewModel == null)
// {
// return NotFound("No questionnaire found with the given ID.");
// }
// var webReport = new WebReport();
// // Load your FastReport report design
// webReport.Report.Load(Path.Combine(env.WebRootPath, "Reports", "QuestionnaireReport.frx"));
// // Register the data source
// webReport.Report.RegisterData(new[] { viewModel }, "Questionnaire");
// webReport.Report.Prepare();
// using (MemoryStream ms = new MemoryStream())
// {
// webReport.Report.Export(new FastReport.Export.PdfSimple.PDFSimpleExport(), ms);
// return File(ms.ToArray(), "application/pdf", "QuestionnaireReport.pdf");
// }
//}
}
}

View file

@ -20,16 +20,13 @@
<span asp-validation-for="QuestionnaireId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Email" class="control-label"></label>
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
<label asp-for="Emails" class="control-label">Email Addresses (separate with commas)</label>
<textarea asp-for="Emails" class="form-control"></textarea>
<span asp-validation-for="Emails" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ExpirationDateTime" class="control-label"></label>
<input asp-for="ExpirationDateTime" class="form-control"/>

View file

@ -110,6 +110,70 @@
</div>
@* @section Scripts {
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', { 'packages': ['corechart', 'bar','line','table'] }); // Ensure 'bar' package is loaded if using BarChart
google.charts.setOnLoadCallback(drawCharts);
function drawCharts() {
@foreach (var question in Model.Questions.Select((value, index) => new { Value = value, Index = index }))
{
<text>
var type = '@question.Value.Type.ToString()';
console.log('Type:', type); // Debug output to check type
var chartContainer = document.getElementById('chart_div_@question.Value.Id');
var chart; // Declare chart variable here for scope
var data = new google.visualization.DataTable();
data.addColumn('string', 'Option');
data.addColumn('number', 'Count');
</text>
if (question.Value.Type == QuestionType.Text || question.Value.Type == QuestionType.Slider || question.Value.Type == QuestionType.Open_ended)
{
<text>
console.log('Initializing Bar Chart'); // Debug output
</text>
@foreach (var item in question.Value.SelectedText)
{
<text>
data.addRow(['@Html.Raw(item)', @question.Value.Answers]);
</text>
}
<text>
chart = new google.visualization.Table(chartContainer);
</text>
} else {
<text>
console.log('Initializing Pie Chart'); // Debug output
</text>
@foreach (var answer in question.Value.Answers)
{
<text>
data.addRow(['@Html.Raw(answer.Text)', @answer.Count]);
</text>
}
<text>
chart = new google.visualization.PieChart(chartContainer);
</text>
}
<text>
var options = {
'title': 'Question @(question.Index + 1): @Html.Raw(question.Value.Text)',
is3D: type !== "Text" && type !== "Slider" && type !== "Open_ended", // Only use 3D for Pie Charts
'titleTextStyle': { color: '#17a2b8', fontSize: 12, bold: true },
'colors': ['#cc0000', '#00cc00', '#0000cc', '#cccc00', '#00cccc', '#cc00cc', '#008080', '#808000', '#800080', '#800000', '#808080', '#404040']
};
chart.draw(data, options); // Draw chart outside conditional blocks
</text>
}
}
</script>
}
*@
@section Scripts {
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
@ -152,7 +216,13 @@
data.addRow(['@Html.Raw(item)', 1]);
</text>
}
<text>
// Initialize Bar Chart for Text, Slider, or Open-ended questions
var chart = new google.visualization.BarChart(chartContainer);
</text>
}
else
{
@foreach (var answer in question.Value.Answers)
@ -167,7 +237,9 @@
'title': 'Question @(question.Index + 1): @Html.Raw(question.Value.Text)',
is3D: true,
'titleTextStyle': { color: '#17a2b8', fontSize: 12, bold: true },
'colors': colors
'colors': colors,
'pieSliceText': 'percentage', // Display percentages on the chart slices
'tooltip': { text: 'percentage' } // Configure tooltip to show percentage
};
if (chartContainer) {

View file

@ -8,10 +8,10 @@ namespace Web.ViewModel.QuestionnaireVM
{
public int Id { get; set; }
[Required]
public string? Name { get; set; }
[Required]
public string? Email { get; set; }
public string? Emails { get; set; }
[Required]
[DisplayName("Set expiration date and time for the URL")]

View file

@ -21,6 +21,7 @@
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="8.0.2" />
<PackageReference Include="OpenAI" Version="1.11.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.4" />
</ItemGroup>
<ItemGroup>