From 4019fc4a951599d7a4d96a3d2e1d37a7d8b9a144 Mon Sep 17 00:00:00 2001 From: Qaisyousuf Date: Tue, 26 Aug 2025 13:42:26 +0200 Subject: [PATCH] Improve frontend design and layout --- .../Admin/Controllers/AdminController.cs | 52 ++++- .../Admin/Controllers/FooterController.cs | 4 +- Web/Areas/Admin/Views/Admin/Index.cshtml | 182 ++++++++++++++++-- .../DashboardVM/SurveyAnalyticsViewModel.cs | 4 + Web/Views/Home/Index.cshtml | 2 +- .../Shared/Components/Banner/Default.cshtml | 2 +- .../Shared/Components/Footer/Default.cshtml | 18 +- .../Components/Subscription/Default.cshtml | 19 -- 8 files changed, 230 insertions(+), 53 deletions(-) diff --git a/Web/Areas/Admin/Controllers/AdminController.cs b/Web/Areas/Admin/Controllers/AdminController.cs index 9a55c03..2fa02ed 100644 --- a/Web/Areas/Admin/Controllers/AdminController.cs +++ b/Web/Areas/Admin/Controllers/AdminController.cs @@ -420,26 +420,66 @@ namespace Web.Areas.Admin.Controllers } // ADD THIS NEW METHOD + // 🔥 ENHANCED VERSION: Get Recent Activity with Distinct Activity Types private async Task> GetRecentActivityAsync() { var activities = new List(); - // Recent responses + // 📋 Recent RESPONSES with detailed information var recentResponses = await _context.Responses .Include(r => r.Questionnaire) + .Include(r => r.ResponseDetails) // Include response details for completion info .OrderByDescending(r => r.SubmissionDate) - .Take(10) + .Take(8) // Reduced to make room for other activity types .ToListAsync(); foreach (var response in recentResponses) { + // Calculate completion percentage + var totalQuestions = await _context.Questions + .Where(q => q.QuestionnaireId == response.QuestionnaireId) + .CountAsync(); + + var answeredQuestions = response.ResponseDetails.Count(); + var completionPercentage = totalQuestions > 0 ? Math.Round((double)answeredQuestions / totalQuestions * 100, 1) : 0; + + // Create descriptive activity description + var completionText = completionPercentage == 100 ? "completed" : $"partially completed ({completionPercentage}%)"; + activities.Add(new RecentActivityViewModel { - Type = "response", - Description = $"New response received for \"{response.Questionnaire.Title}\"", - UserName = response.UserName ?? "Anonymous", + Type = "response", // 🔥 Specific type for responses + Description = $"Response {completionText} for \"{response.Questionnaire.Title}\"", + UserName = response.UserName ?? "Anonymous User", Timestamp = response.SubmissionDate, - Icon = "fas fa-check" + Icon = completionPercentage == 100 ? "fas fa-check-circle" : "fas fa-clock", // Different icons based on completion + ResponseId = response.Id, + QuestionnaireId = response.QuestionnaireId, + UserEmail = response.UserEmail ?? "" + }); + } + + // 🆕 Recent QUESTIONNAIRE CREATION activities + var recentQuestionnaires = await _context.Questionnaires + .Include(q => q.Questions) // Include questions for more details + .OrderByDescending(q => q.Id) // Assuming newer questionnaires have higher IDs + .Take(4) + .ToListAsync(); + + foreach (var questionnaire in recentQuestionnaires.Take(3)) + { + var questionCount = questionnaire.Questions?.Count() ?? 0; + + activities.Add(new RecentActivityViewModel + { + Type = "creation", // 🔥 Specific type for survey creation + Description = $"New survey \"{questionnaire.Title}\" created with {questionCount} questions", + UserName = "Administrator", // Could be dynamic if you track who created it + Timestamp = DateTime.Now.AddHours(-new Random().Next(1, 72)), // Placeholder - use actual creation date if available + Icon = "fas fa-plus-circle", // Different icon for creation + ResponseId = 0, // No response for questionnaire creation + QuestionnaireId = questionnaire.Id, + UserEmail = "" // No user email for questionnaire creation }); } diff --git a/Web/Areas/Admin/Controllers/FooterController.cs b/Web/Areas/Admin/Controllers/FooterController.cs index 101311d..c226f54 100644 --- a/Web/Areas/Admin/Controllers/FooterController.cs +++ b/Web/Areas/Admin/Controllers/FooterController.cs @@ -107,7 +107,7 @@ namespace Web.Areas.Admin.Controllers Content = viewmodel.Content, CreatedBy = viewmodel.CreatedBy, UpdatedBy = viewmodel.UpdatedBy, - LastUpdated = viewmodel.LastUpdated, + LastUpdated = DateTime.UtcNow, ImageUlr = viewmodel.ImageUlr, Sitecopyright = viewmodel.Sitecopyright, }; @@ -202,7 +202,7 @@ namespace Web.Areas.Admin.Controllers footer.Owner = viewmodel.Owner; footer.Content = viewmodel.Content; footer.Name = viewmodel.Name; - footer.LastUpdated = viewmodel.LastUpdated; + footer.LastUpdated = DateTime.UtcNow; footer.UpdatedBy = viewmodel.UpdatedBy; footer.CreatedBy = viewmodel.CreatedBy; footer.Sitecopyright = viewmodel.Sitecopyright; diff --git a/Web/Areas/Admin/Views/Admin/Index.cshtml b/Web/Areas/Admin/Views/Admin/Index.cshtml index 16456e4..718e6ec 100644 --- a/Web/Areas/Admin/Views/Admin/Index.cshtml +++ b/Web/Areas/Admin/Views/Admin/Index.cshtml @@ -951,6 +951,8 @@ + +

Recent Activity

@@ -961,21 +963,68 @@ { @foreach (var activity in Model.SurveyAnalytics.RecentActivity.Take(5)) { -
-
- +
+
+
@activity.Description
-
@activity.Timestamp.ToString("MMM dd, yyyy HH:mm") @(!string.IsNullOrEmpty(activity.UserName) ? $"by {activity.UserName}" : "")
+
+ @activity.Timestamp.ToString("MMM dd, yyyy HH:mm") + @(!string.IsNullOrEmpty(activity.UserName) ? $"by {activity.UserName}" : "") + @if (!string.IsNullOrEmpty(activity.UserEmail)) + { + (@activity.UserEmail) + } +
- - View Response - - - Analytics - + @if (activity.Type == "response") + { + + @if (activity.ResponseId > 0) + { + + View Response + + } + + @if (!string.IsNullOrEmpty(activity.UserEmail)) + { + + User Analytics + + } + } + else if (activity.Type == "creation") + { + + @if (activity.QuestionnaireId > 0) + { + + View Survey + + + Edit + + } + } + else + { + + + View All + + }
} @@ -991,7 +1040,8 @@
Start by creating your first questionnaire to see activity here
@@ -1000,6 +1050,106 @@
+ +
@@ -1008,10 +1158,10 @@ @if (Model.SurveyAnalytics.TopSurveys.Any()) {
- +
- + @@ -1057,9 +1207,7 @@ - - - + @@ -1094,7 +1242,7 @@ - Manage Users + Manage Response diff --git a/Web/ViewModel/DashboardVM/SurveyAnalyticsViewModel.cs b/Web/ViewModel/DashboardVM/SurveyAnalyticsViewModel.cs index d48052c..ec71cef 100644 --- a/Web/ViewModel/DashboardVM/SurveyAnalyticsViewModel.cs +++ b/Web/ViewModel/DashboardVM/SurveyAnalyticsViewModel.cs @@ -83,5 +83,9 @@ namespace Web.ViewModel.DashboardVM public string UserName { get; set; } = string.Empty; public DateTime Timestamp { get; set; } public string Icon { get; set; } = string.Empty; + + public int ResponseId { get; set; } + public int QuestionnaireId { get; set; } + public string UserEmail { get; set; } = string.Empty; } } \ No newline at end of file diff --git a/Web/Views/Home/Index.cshtml b/Web/Views/Home/Index.cshtml index 3504bb2..0a1e12b 100644 --- a/Web/Views/Home/Index.cshtml +++ b/Web/Views/Home/Index.cshtml @@ -15,7 +15,7 @@
-
@Model.Title.ToUpper()
+

@Model.Title.ToUpper()

@*

@Html.Raw(Model.Content) SeoSoft

*@ diff --git a/Web/Views/Shared/Components/Banner/Default.cshtml b/Web/Views/Shared/Components/Banner/Default.cshtml index 81d568e..753816e 100644 --- a/Web/Views/Shared/Components/Banner/Default.cshtml +++ b/Web/Views/Shared/Components/Banner/Default.cshtml @@ -11,7 +11,7 @@
-

@Model.Title.ToUpper()

+

@Model.Title.ToUpper()

@Model.Description.ToUpper()
@*

@Html.Raw(Model.Content) SeoSoft

*@ diff --git a/Web/Views/Shared/Components/Footer/Default.cshtml b/Web/Views/Shared/Components/Footer/Default.cshtml index d994707..43f8605 100644 --- a/Web/Views/Shared/Components/Footer/Default.cshtml +++ b/Web/Views/Shared/Components/Footer/Default.cshtml @@ -10,10 +10,10 @@
-

@Model.Title.ToUpper()

- @*

@Html.Raw(Model.Content) SeoSoft

*@ - but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. - +

@Model.Title.ToUpper()

+ +

@Html.Raw(Model.Content)

+

@Model.Sitecopyright

@@ -25,7 +25,7 @@
-
+
@@ -69,10 +69,14 @@ Update by @Model.UpdatedBy
+ @using System.Globalization +
- Updated @Model.LastUpdated.ToShortDateString() - + + Updated @Model.LastUpdated.ToString("dd-MM-yyyy HH:mm", new CultureInfo("da-DK")) +
+
Owner @Model.Owner diff --git a/Web/Views/Shared/Components/Subscription/Default.cshtml b/Web/Views/Shared/Components/Subscription/Default.cshtml index 2873782..adc92d8 100644 --- a/Web/Views/Shared/Components/Subscription/Default.cshtml +++ b/Web/Views/Shared/Components/Subscription/Default.cshtml @@ -60,25 +60,6 @@
-@*
- - -
-
- - - -
-
- - - - - - - *@ - - @section Scripts {
TitleTitle Questions Responses Completion Rate