Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
51037a9
Add Feedback class to PC2.Models with properties
ScottProgrammer88 Jan 30, 2025
c6e74d0
Add DbSet<Feedback> to ApplicationDbContext
ScottProgrammer88 Jan 30, 2025
d27489f
Add Feedback table and update Discriminator column
ScottProgrammer88 Jan 30, 2025
9501475
Add FeedbackViewModel class to PC2.Models namespace
ScottProgrammer88 Jan 30, 2025
51efcb6
Add "View Feedback" link to navigation menu
ScottProgrammer88 Jan 30, 2025
fe62aeb
Add user feedback table to ViewFeedback.cshtml
ScottProgrammer88 Jan 30, 2025
7b09967
Add feedback form feature and admin feedback view
ScottProgrammer88 Feb 5, 2025
df2b291
Improve HTML table structure and styling in feedback view
ScottProgrammer88 Feb 10, 2025
ba76eeb
Add XML documentation to Feedback class and properties
ScottProgrammer88 Feb 11, 2025
ce1dfde
Enhance Feedback Form with Success Alert and Improved User Input Hand…
ScottProgrammer88 Feb 11, 2025
b73474f
Control feedback form visibility and add error logging
ScottProgrammer88 Feb 11, 2025
fd4a380
Add XML documentation to FeedbackViewModel class
ScottProgrammer88 Feb 11, 2025
5d5b207
Rename FoundResource to IsResourceFound across project
ScottProgrammer88 Feb 16, 2025
5e63f14
Rename FoundResource to IsResourceFound in Feedback table
ScottProgrammer88 Feb 16, 2025
9e89fb3
Make Feedback property virtual in ApplicationDbContext
ScottProgrammer88 Feb 16, 2025
0344bfa
Add IsReviewed property to Feedback and FeedbackViewModel
ScottProgrammer88 Feb 17, 2025
484c617
Add IsReviewed column to Feedback table
ScottProgrammer88 Feb 17, 2025
17891fa
Update page title, table styling, and add new columns
ScottProgrammer88 Feb 17, 2025
28fabe7
Add EditFeedback view with form for editing feedback
ScottProgrammer88 Feb 17, 2025
9fc2a19
Add view for deleting feedback with confirmation
ScottProgrammer88 Feb 17, 2025
547fe2f
Enhance feedback management in ResourcesController
ScottProgrammer88 Feb 17, 2025
95e9f31
Refactored and improved resource guide and feedback handling
ScottProgrammer88 Feb 25, 2025
ac5d227
Merge branch 'main' into feature/resource-guide-search-feedback
ScottProgrammer88 Feb 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
214 changes: 214 additions & 0 deletions PC2/Controllers/ResourcesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using Microsoft.AspNetCore.Mvc;
using PC2.Data;
using PC2.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;

namespace PC2.Controllers
{
Expand Down Expand Up @@ -29,15 +31,21 @@ public IActionResult Index()
public async Task<IActionResult> ResourceGuide(int categoryID)
{
ResourceGuideModel resourceGuide = new ResourceGuideModel();

ViewData["ShowFeedbackForm"] = false;

if (categoryID != 0)
{
resourceGuide.Agencies = await AgencyDB.GetSpecificAgenciesAsync(_context, categoryID);
resourceGuide.Category = await AgencyCategoryDB.GetAgencyCategory(_context, categoryID);
TrackResourceGuideTelemetry("Manual/Category", resourceGuide.Category.AgencyCategoryName);

ViewData["ShowFeedbackForm"] = true;
}

await AgencyDB.GetDataForDataLists(_context, resourceGuide);


return View(resourceGuide);
}

Expand Down Expand Up @@ -69,12 +77,15 @@ public async Task<IActionResult> ResourceGuide(ResourceGuideModel searchModel)
UserSearchedByAgency = searchModel.UserSearchedByAgency
};

ViewBag.ShowFeedbackForm = false;

if (!string.IsNullOrEmpty(searchModel.UserSearchedByAgency))
{
if (searchModel.SearchedAgency != null)
{
TrackResourceGuideTelemetry("Agency", searchModel.SearchedAgency);
resourceGuide.Agencies = await AgencyDB.GetAgenciesByName(_context, searchModel.SearchedAgency);
ViewData["ShowFeedbackForm"] = true;
}
}
else if (!string.IsNullOrEmpty(searchModel.UserSearchedByCityOrService))
Expand All @@ -87,18 +98,21 @@ public async Task<IActionResult> ResourceGuide(ResourceGuideModel searchModel)
searchModel.SearchedCategory, searchModel.SearchedCity);
resourceGuide.CurrentCity = searchModel.SearchedCity;
resourceGuide.Category = await AgencyCategoryDB.GetAgencyCategory(_context, searchModel.SearchedCategory);
ViewData["ShowFeedbackForm"] = true;
}
else if (searchModel.SearchedCategory != null)
{
TrackResourceGuideTelemetry("Service", $"{searchModel.SearchedCategory}");
resourceGuide.Category = await AgencyCategoryDB.GetAgencyCategory(_context, searchModel.SearchedCategory);
resourceGuide.Agencies = await AgencyDB.GetSpecificAgenciesAsync(_context, resourceGuide.Category.AgencyCategoryId);
ViewData["ShowFeedbackForm"] = true;
}
else if (searchModel.SearchedCity != null)
{
TrackResourceGuideTelemetry("City", searchModel.SearchedCity);
resourceGuide.CurrentCity = searchModel.SearchedCity;
resourceGuide.Agencies = await AgencyDB.GetSpecificAgenciesAsync(_context, searchModel.SearchedCity);
ViewData["ShowFeedbackForm"] = true;
}
}

Expand Down Expand Up @@ -148,5 +162,205 @@ public IActionResult VirtualCloset()

return View(newsletterFiles);
}

/// <summary>
/// Submits user feedback.
/// </summary>
/// <param name="model">The feedback model containing user input.</param>
/// <returns>A redirect to the ResourceGuide action on success,
/// or the ResourceGuide view if the model is invalid.</returns>
[HttpPost]
public async Task<IActionResult> SubmitFeedback(Feedback model)
{
if (ModelState.IsValid)
{
model.SubmittedAt = DateTime.UtcNow;
_context.Feedback.Add(model);
await _context.SaveChangesAsync();

TempData["SuccessMessage"] = "Thank you for your feedback!";
return RedirectToAction("ResourceGuide");
}

return RedirectToAction("ResourceGuide");
}

/// <summary>
/// Allows administrators to view feedback submitted by users.
/// This method retrieves and displays all feedback entries from the database, ordered by submission date.
/// </summary>
/// <returns>
/// A view displaying the list of feedback, including their comments and submission dates.
/// </returns>
[Authorize(Roles = IdentityHelper.Admin)]
[HttpGet]
public async Task<IActionResult> ViewFeedback()
{
List<FeedbackViewModel> feedbackList = await _context.Feedback
.OrderByDescending(f => f.SubmittedAt)
.Select(f => new FeedbackViewModel
{
Id = f.Id,
IsResourceFound = f.IsResourceFound ? "Yes" : "No",
Comments = f.Comments,
FormattedSubmittedAt = f.SubmittedAt.ToString("yyyy-MM-dd HH:mm"),
IsReviewed = f.IsReviewed
})
.ToListAsync();

return View(feedbackList);
}

/// <summary>
/// Allows administrators to view and edit feedback submitted by users.
/// This method retrieves the feedback based on its ID and prepares it for editing.
/// </summary>
/// <param name="id">The ID of the feedback to edit.</param>
/// <returns>
/// A view displaying the feedback details, ready for editing, or a 404 error if the feedback does not exist.
/// </returns>
[Authorize(Roles = IdentityHelper.Admin)]
[HttpGet]
public async Task<IActionResult> EditFeedback(int id)
{
Feedback? feedback = await _context.Feedback.FindAsync(id);
if (feedback == null)
{
return NotFound();
}

FeedbackViewModel viewModel = new()
{
Id = feedback.Id,
IsResourceFound = feedback.IsResourceFound ? "Yes" : "No",
Comments = feedback.Comments,
FormattedSubmittedAt = feedback.SubmittedAt.ToString("yyyy-MM-dd HH:mm"),
IsReviewed = feedback.IsReviewed
};

return View(viewModel);
}

/// <summary>
/// Updates the feedback submitted by a user.
/// This method processes the edits made by the administrator and updates the feedback in the database.
/// </summary>
/// <param name="model">The feedback view model containing the updated data.</param>
/// <returns>
/// A redirect to the "ViewFeedback" action if the feedback is successfully updated.
/// A view with validation errors if the model is invalid.
/// </returns>
[Authorize(Roles = IdentityHelper.Admin)]
[HttpPost]
public async Task<IActionResult> EditFeedback(FeedbackViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}

Feedback? feedback = await _context.Feedback.FindAsync(model.Id);
if (feedback == null)
{
return NotFound();
}

feedback.Comments = model.Comments;
feedback.IsReviewed = model.IsReviewed;

_context.Feedback.Update(feedback);
await _context.SaveChangesAsync();

return RedirectToAction(nameof(ViewFeedback));
}

/// <summary>
/// Allows administrators to view the confirmation page for deleting feedback.
/// This method retrieves the feedback based on its ID and presents a confirmation page to the user.
/// </summary>
/// <param name="id">The ID of the feedback to delete.</param>
/// <returns>
/// A view displaying the feedback to confirm deletion, or a 404 error if the feedback does not exist.
/// </returns>
[Authorize(Roles = IdentityHelper.Admin)]
[HttpGet]
public async Task<IActionResult> DeleteFeedback(int id)
{
Feedback? feedback = await _context.Feedback.FindAsync(id);
if (feedback == null)
{
return NotFound();
}

return View(feedback);
}

/// <summary>
/// Deletes the specified feedback from the database.
/// This method removes the feedback entry from the database after confirmation.
/// </summary>
/// <param name="id">The ID of the feedback to delete.</param>
/// <returns>
/// A redirect to the "ViewFeedback" action after the feedback has been deleted.
/// </returns>
[Authorize(Roles = IdentityHelper.Admin)]
[HttpPost, ActionName("DeleteFeedback")]
public async Task<IActionResult> DeleteConfirmed(int id)
{
Feedback? feedback = await _context.Feedback.FindAsync(id);
if (feedback == null)
{
return NotFound();
}

_context.Feedback.Remove(feedback);
await _context.SaveChangesAsync();

return RedirectToAction(nameof(ViewFeedback));
}

/// <summary>
/// Displays a view for marking a feedback entry as reviewed.
/// </summary>
/// <param name="id">The ID of the feedback entry to mark as reviewed.</param>
/// <returns>The MarkAsReviewed view with the feedback data.</returns>
[HttpGet]
public async Task<IActionResult> MarkAsReviewed(int? id)
{
if (id == null)
{
return NotFound();
}

Feedback? feedback = await _context.Feedback.FindAsync(id);
if (feedback == null)
{
return NotFound();
}

return View(feedback);
}

/// <summary>
/// Marks a feedback entry as reviewed.
/// </summary>
/// <param name="id">The ID of the feedback entry to mark as reviewed.</param>
/// <returns>A redirect to the ViewFeedback action.</returns>
[Authorize(Roles = IdentityHelper.Admin)]
[HttpPost]
public async Task<IActionResult> MarkAsReviewed(int id)
{
Feedback? feedback = await _context.Feedback.FindAsync(id);
if (feedback == null)
{
return NotFound();
}

feedback.IsReviewed = true;
await _context.SaveChangesAsync();

return RedirectToAction("ViewFeedback");
}

}
}
1 change: 1 addition & 0 deletions PC2/Data/ApplicationDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ protected override void ConfigureConventions(ModelConfigurationBuilder builder)
public virtual DbSet<NewsletterFile> NewsletterFile { get; set; }

public virtual DbSet<HousingProgram> HousingProgram { get; set; }
public virtual DbSet<Feedback> Feedback { get; set; }
}

internal class DateOnlyConverter : ValueConverter<DateOnly, DateTime>
Expand Down
Loading