@model ManageSubscriptionViewModel @{ ViewData["Title"] = "Subscription"; var subscription = Model.CurrentSubscription; var usage = Model.Usage; }

Account

Subscription

@Model.User.Email

Back to account
@if (TempData["SubscriptionMessage"] is string subscriptionMessage) {
@subscriptionMessage
}

Current subscription

@if (subscription is null) {

No active subscription is assigned.

} else {

Plan

@subscription.DisplayName

Description

@(string.IsNullOrWhiteSpace(subscription.Description) ? "No description available." : subscription.Description)

Status

@(string.IsNullOrWhiteSpace(subscription.StripeStatus) ? (subscription.IsActive ? "Active" : "Inactive") : subscription.StripeStatus)

Billing interval

@(string.IsNullOrWhiteSpace(subscription.BillingInterval) ? "Not set" : subscription.BillingInterval)

Trial

@(subscription.IsTrial ? "Trial" : "No")

Trial expiry

@FormatDate(subscription.TrialExpiryDateUTC)

Started

@FormatDate(subscription.StartDateUTC)

Ends

@FormatDate(subscription.EndDateUTC)

@if (subscription.CancelAtPeriodEnd) {
This subscription is scheduled to cancel at the end of the current billing period.
} @if (subscription.LastPaymentFailureDateUTC.HasValue) {
Stripe has reported a payment issue for this subscription.
}
@if (!string.IsNullOrWhiteSpace(subscription.StripeCustomerId)) {
} @if (!string.IsNullOrWhiteSpace(subscription.StripeSubscriptionId) && !subscription.CancelAtPeriodEnd) {
}
}

Usage

@if (subscription is null || usage is null) {

Usage is available after a subscription is assigned.

} else {
Limit Usage
Books @FormatUsage(usage.BooksUsed, subscription.MaxBooks, "books")
Storage @FormatStorageUsage(usage.StorageUsedBytes, usage.StorageMaximumBytes)
Collaborators @FormatUsage(usage.CollaboratorsUsed, subscription.MaxCollaborators, "collaborators")
Highest chapters in a book @FormatUsage(usage.HighestChaptersInBook, subscription.MaxChaptersPerBook, "chapters")
Highest scenes in a book @FormatUsage(usage.HighestScenesInBook, subscription.MaxScenesPerBook, "scenes")
Highest characters in a project @FormatUsage(usage.HighestCharactersInProject, subscription.MaxCharactersPerProject, "characters")
}

Available plans

@if (!Model.AvailableLevels.Any()) {

No active subscription levels are available.

} else {
@foreach (var level in Model.AvailableLevels) { var isCurrent = subscription is not null && level.SubscriptionLevelID == subscription.SubscriptionLevelID;

@level.DisplayName

@(isCurrent ? "Current plan" : "Available plan")

@(string.IsNullOrWhiteSpace(level.Description) ? "No description available." : level.Description)

@if (!level.RequiresStripeSubscription) {

Free / trial / application managed

} else {
@if (level.MonthlyPricePence.HasValue) {

Monthly

@FormatMoney(level.MonthlyPricePence.Value, level.CurrencyCode)

} @if (level.AnnualPricePence.HasValue) {

Annual

@FormatMoney(level.AnnualPricePence.Value, level.CurrencyCode)

}
}
Books
@FormatLimit(level.MaxBooks)
Chapters / book
@FormatLimit(level.MaxChaptersPerBook)
Scenes / book
@FormatLimit(level.MaxScenesPerBook)
Characters / project
@FormatLimit(level.MaxCharactersPerProject)
Storage
@FormatStorageAllowance(level.MaxStorageMB)
Collaborators
@FormatLimit(level.MaxCollaborators)
@if (!level.RequiresStripeSubscription) {

Draft Desk is managed inside PlotDirector.

} else {
@if (!string.IsNullOrWhiteSpace(level.StripeMonthlyPriceId)) {
} @if (!string.IsNullOrWhiteSpace(level.StripeAnnualPriceId)) {
}
}
}
}
@functions { private const int PracticalUnlimited = 999999; private static string FormatDate(DateTime? value) => value.HasValue ? value.Value.ToLocalTime().ToString("yyyy-MM-dd") : "Not set"; private static string FormatLimit(int value) => value >= PracticalUnlimited ? "Unlimited" : value.ToString("N0"); private static string FormatUsage(int used, int maximum, string label) => maximum >= PracticalUnlimited ? $"{used:N0} / Unlimited {label}" : $"{used:N0} / {maximum:N0} {label}"; private static string FormatStorageAllowance(int megabytes) => megabytes >= PracticalUnlimited ? "Unlimited" : StorageUsage.FormatBytes(megabytes * 1024L * 1024L); private static string FormatStorageUsage(long usedBytes, long maximumBytes) => maximumBytes >= PracticalUnlimited * 1024L * 1024L ? $"{StorageUsage.FormatBytes(usedBytes)} / Unlimited storage" : $"{StorageUsage.FormatBytes(usedBytes)} / {StorageUsage.FormatBytes(maximumBytes)} storage"; private static string FormatMoney(int pence, string? currencyCode) => string.Equals(currencyCode, "GBP", StringComparison.OrdinalIgnoreCase) ? $"£{pence / 100m:0.00}" : $"{pence / 100m:0.00} {(string.IsNullOrWhiteSpace(currencyCode) ? "GBP" : currencyCode.ToUpperInvariant())}"; }