using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using PlotLine.Services; using PlotLine.ViewModels; namespace PlotLine.Controllers; [Authorize] public sealed class FeatureRequestsController( ICurrentUserService currentUser, IFeatureRequestService featureRequests) : Controller { [HttpGet] public async Task Index() { var userId = RequireUserId(); var requests = await featureRequests.ListForUserAsync(userId); return View(new FeatureRequestIndexViewModel { Requests = requests }); } [HttpGet] public IActionResult Create() { return View(new FeatureRequestCreateViewModel()); } [HttpPost] [ValidateAntiForgeryToken] public async Task Create(FeatureRequestCreateViewModel model) { if (!ModelState.IsValid) { return View(WithOptions(model)); } var created = await featureRequests.CreateAsync(RequireUserId(), model); TempData["FeatureRequestMessage"] = "Your feature request has been submitted."; return RedirectToAction(nameof(Details), new { id = created.FeatureRequestID }); } [HttpGet] public async Task Details(int id) { var request = await featureRequests.GetForUserAsync(id, RequireUserId()); if (request is null) { return NotFound(); } return View(new FeatureRequestDetailsViewModel { Request = request, Messages = await featureRequests.ListMessagesAsync(request.FeatureRequestID), Reply = new FeatureRequestReplyViewModel { FeatureRequestID = request.FeatureRequestID } }); } [HttpPost] [ValidateAntiForgeryToken] public async Task Reply([Bind(Prefix = "Reply")] FeatureRequestReplyViewModel model) { var userId = RequireUserId(); var request = await featureRequests.GetForUserAsync(model.FeatureRequestID, userId); if (request is null) { return NotFound(); } if (!ModelState.IsValid) { return View(nameof(Details), new FeatureRequestDetailsViewModel { Request = request, Messages = await featureRequests.ListMessagesAsync(request.FeatureRequestID), Reply = model }); } await featureRequests.AddUserReplyAsync(model.FeatureRequestID, userId, model.MessageBody); return RedirectToAction(nameof(Details), new { id = model.FeatureRequestID }); } private int RequireUserId() { return currentUser.UserId ?? throw new InvalidOperationException("Authenticated user id was not available."); } private static FeatureRequestCreateViewModel WithOptions(FeatureRequestCreateViewModel model) { model.AppAreas = PlotLine.Models.FeatureRequestOptions.AppAreas; model.ImportanceOptions = PlotLine.Models.FeatureRequestOptions.ImportanceOptions; return model; } }