PlotDirector/PlotLine/Controllers/PricingController.cs

91 lines
3.5 KiB
C#

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using PlotLine.Data;
using PlotLine.Models;
using PlotLine.Services;
using PlotLine.ViewModels;
namespace PlotLine.Controllers;
[AllowAnonymous]
public sealed class PricingController(
ICurrentUserService currentUser,
IUserRepository users,
ISubscriptionService subscriptions,
IStripeBillingService stripeBilling,
IConfiguration configuration) : Controller
{
[HttpGet("pricing", Name = PublicRouteNames.Pricing)]
public async Task<IActionResult> Index()
{
const string description = "Compare PlotDirector plans and choose the right subscription for organising your novel, series, characters, plot threads, timelines, and story details.";
ViewData["SeoTitle"] = "Pricing | PlotDirector";
ViewData["SeoDescription"] = description;
ViewData["SeoKeywords"] = "novel planning software, writing software, story planning app, author tools, plot tracking, character tracking, story timeline, novel organisation, fiction writing software, series writing software, continuity tracking, plot threads, story bible";
ViewData["CanonicalUrl"] = PublicSeo.AbsoluteUrl(configuration, "/pricing");
ViewData["StructuredData"] = new[]
{
PublicSeo.WebPageJsonLd(configuration, "WebPage", "Pricing", "/pricing", description)
};
UserSubscriptionDetail? currentSubscription = null;
if (currentUser.UserId is int userId)
{
currentSubscription = await subscriptions.GetCurrentSubscriptionAsync(userId);
}
return View(new PricingViewModel
{
Plans = await subscriptions.GetActiveSubscriptionLevelsAsync(),
CurrentSubscriptionLevelID = currentSubscription?.SubscriptionLevelID,
IsSignedIn = currentUser.UserId.HasValue
});
}
[HttpGet]
public IActionResult StartTrial()
{
if (!currentUser.UserId.HasValue)
{
return RedirectToAction("Register", "Account");
}
return RedirectToAction("Subscription", "ManageAccount");
}
[HttpGet]
public async Task<IActionResult> Checkout(int id, string billingInterval = "Monthly")
{
if (!currentUser.UserId.HasValue)
{
var returnUrl = Url.Action(nameof(Checkout), "Pricing", new { id, billingInterval }) ?? "/pricing";
return RedirectToAction("Login", "Account", new { returnUrl });
}
var user = await users.GetByIdAsync(currentUser.UserId.Value);
if (user is null)
{
return RedirectToAction("Login", "Account");
}
var request = new StripeCheckoutRequest
{
SubscriptionLevelID = id,
BillingInterval = string.Equals(billingInterval, "Annual", StringComparison.OrdinalIgnoreCase)
? "Annual"
: "Monthly"
};
var successUrl = Url.Action("SubscriptionSuccess", "ManageAccount", null, Request.Scheme) ?? string.Empty;
var cancelUrl = Url.Action(nameof(Index), "Pricing", null, Request.Scheme) ?? string.Empty;
var result = await stripeBilling.StartCheckoutOrChangePlanAsync(user, request, successUrl, cancelUrl);
if (result.Succeeded && !string.IsNullOrWhiteSpace(result.RedirectUrl))
{
return Redirect(result.RedirectUrl);
}
TempData["PricingMessage"] = result.Message;
return RedirectToAction(nameof(Index));
}
}