PlotDirector/PlotLine/Controllers/BooksController.cs

118 lines
4.1 KiB
C#

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using PlotLine.Models;
using PlotLine.Services;
using PlotLine.ViewModels;
namespace PlotLine.Controllers;
[Authorize]
public sealed class BooksController(IBookService books, IOnboardingService onboarding) : Controller
{
public async Task<IActionResult> Details(int id)
{
var model = await books.GetDetailAsync(id);
return model is null ? NotFound() : View(model);
}
public async Task<IActionResult> Create(int projectId)
{
var model = await books.GetCreateAsync(projectId);
return model is null ? NotFound() : View("Edit", model);
}
public async Task<IActionResult> Edit(int id)
{
var model = await books.GetEditAsync(id);
return model is null ? NotFound() : View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Save(BookEditViewModel model)
{
if (model.BeginMode is not (BookBeginModes.Manual or BookBeginModes.Import))
{
model.BeginMode = BookBeginModes.Manual;
}
if (!BookStatuses.IsValid(model.Status))
{
ModelState.AddModelError(nameof(model.Status), "Select a valid book status.");
}
if (!ModelState.IsValid)
{
await books.PopulateEditContextAsync(model);
return View("Edit", model);
}
BookSaveResult result;
try
{
result = await books.SaveAsync(model);
}
catch (SubscriptionLimitException ex) when (model.BookID == 0)
{
ModelState.AddModelError(string.Empty, ex.Message);
var createModel = await books.GetCreateAsync(model.ProjectID);
if (createModel is null)
{
return NotFound();
}
createModel.BookTitle = model.BookTitle;
createModel.Subtitle = model.Subtitle;
createModel.Tagline = model.Tagline;
createModel.ShortDescription = model.ShortDescription;
createModel.Status = model.Status;
createModel.BookNumber = model.BookNumber;
createModel.Description = model.Description;
createModel.TargetWordCount = model.TargetWordCount;
createModel.WritingStartDate = model.WritingStartDate;
createModel.TargetCompletionDate = model.TargetCompletionDate;
createModel.PublicationDate = model.PublicationDate;
createModel.UsesExplicitScenes = model.UsesExplicitScenes;
createModel.BeginMode = model.BeginMode;
await books.PopulateEditContextAsync(createModel);
return View("Edit", createModel);
}
if (!result.Succeeded)
{
model.BookID = result.BookID;
ModelState.AddModelError(nameof(model.CoverUpload), result.ErrorMessage ?? "Cover image could not be uploaded.");
await books.PopulateEditContextAsync(model);
return View("Edit", model);
}
if (model.BookID == 0 && string.Equals(model.BeginMode, BookBeginModes.Import, StringComparison.Ordinal))
{
await onboarding.BeginManuscriptImportForBookAsync(model.ProjectID, result.BookID);
return RedirectToAction("Index", "Onboarding");
}
return RedirectToAction(nameof(Details), new { id = result.BookID });
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Archive(int id, int projectId)
{
await books.ArchiveAsync(id);
TempData["ArchiveMessage"] = "Book archived. You can restore it from Archived Items.";
return RedirectToAction("Details", "Projects", new { id = projectId });
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> UnlinkManuscript(int id)
{
var result = await books.UnlinkManuscriptAsync(id);
TempData["ManuscriptMessage"] = result is null
? "Unable to unlink manuscript. It may already be unlinked, or you may not have access."
: result.Message;
return RedirectToAction(nameof(Details), new { id });
}
}