defmodule PlausibleWeb.Live.SubscriptionSettings do
@moduledoc """
LiveView for the subscription settings page.
"""
use PlausibleWeb, :live_view
use Plausible
require Plausible.Billing
import PlausibleWeb.Components.Billing.Helpers
alias Plausible.Teams
alias PlausibleWeb.Router.Helpers, as: Routes
def mount(_params, _session, socket) do
team = socket.assigns.current_team
if Teams.setup?(team) &&
socket.assigns.current_team_role not in Plausible.Billing.allowed_roles() do
{:ok, redirect(socket, to: Routes.site_path(socket, :index))}
else
subscription = Teams.Billing.get_subscription(team)
invoices = Plausible.Billing.paddle_api().get_invoices(subscription)
pageview_usage = Teams.Billing.monthly_pageview_usage(team)
site_usage = Teams.Billing.site_usage(team)
team_member_usage = Teams.Billing.team_member_usage(team)
usage = %{
monthly_pageviews: pageview_usage,
sites: site_usage,
team_members: team_member_usage
}
notification_type = Plausible.Billing.Quota.usage_notification_type(team, usage)
total_pageview_usage_domain =
if site_usage == 1 do
[site] = Plausible.Teams.owned_sites(team)
site.domain
else
on_ee(do: team && consolidated_view_domain(team), else: nil)
end
socket =
socket
|> assign(:subscription, subscription)
|> assign(:invoices, invoices)
|> assign(:pageview_limit, Teams.Billing.monthly_pageview_limit(subscription))
|> assign(:pageview_usage, pageview_usage)
|> assign(:site_usage, site_usage)
|> assign(:site_limit, Teams.Billing.site_limit(team))
|> assign(:team_member_limit, Teams.Billing.team_member_limit(team))
|> assign(:team_member_usage, team_member_usage)
|> assign(:notification_type, notification_type)
|> assign(:total_pageview_usage_domain, total_pageview_usage_domain)
{:ok, socket}
end
end
def render(assigns) do
~H"""
<.settings_tiles>
<%= if is_nil(@current_team) || Plausible.Teams.on_trial?(@current_team) do %>
<.tile docs="trial-to-paid">
<:title>Current plan
Free trial
<.pill :if={@current_team} color={:yellow}>
{Plausible.Teams.trial_days_left(@current_team)} days left
Your 30-day trial will start when you add your first site
<.button_link
href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)}
mt?={false}
id="upgrade-or-change-plan-link"
>
{trial_button_label(@current_team)}
<% else %>
<.tile docs="billing">
<:title>Current plan
<%= if @subscription do %>
{present_plan_name(Plausible.Billing.Plans.get_subscription_plan(@subscription))}
<.pill color={subscription_pill_color(@subscription.status)}>
{present_subscription_status(@subscription.status)}
Up to {PlausibleWeb.AuthView.subscription_quota(@subscription)} monthly pageviews
<%= if @subscription.next_bill_amount && @subscription.next_bill_date do %>
{PlausibleWeb.BillingView.present_currency(@subscription.currency_code)}{@subscription.next_bill_amount} / {present_subscription_interval(
@subscription
)} • Renews on {Calendar.strftime(@subscription.next_bill_date, "%b %-d, %Y")}
<% end %>
<.button_link
:if={
Plausible.Billing.Subscriptions.resumable?(@subscription) &&
@subscription.update_url
}
theme="secondary"
href={@subscription.update_url}
mt?={false}
id="billing-details-link"
>
Billing details
<.button_link
:if={
not (Plausible.Teams.Billing.enterprise_configured?(@current_team) &&
Plausible.Billing.Subscriptions.halted?(@subscription))
}
href={Routes.billing_path(PlausibleWeb.Endpoint, :choose_plan)}
mt?={false}
id="upgrade-or-change-plan-link"
>
{change_plan_button_label(@subscription)}
<% else %>
<% end %>
<% end %>
<.tile docs="subscription-plans">
<:title>
Monthly usage
<.tile docs="subscription-plans">
<:title>Site and team usage
Owned sites
{PlausibleWeb.TextHelpers.number_format(@site_usage)}
{if is_number(@site_limit),
do: "/ #{PlausibleWeb.TextHelpers.number_format(@site_limit)}"}
{if @site_limit == :unlimited, do: "/ Unlimited"}
Team members
{PlausibleWeb.TextHelpers.number_format(@team_member_usage)}
{if is_number(@team_member_limit),
do: "/ #{PlausibleWeb.TextHelpers.number_format(@team_member_limit)}"}
{if @team_member_limit == :unlimited, do: "/ Unlimited"}
<.tile :if={@subscription} docs="download-invoices">
<:title>
Invoices
<%= case @invoices do %>
<% {:error, :no_invoices} -> %>
You don't have any invoices yet.
<% {:error, :request_failed} -> %>
<.notice theme={:gray} title="We couldn't retrieve your invoices">
Please refresh the page or try again later
<% {:ok, invoice_list} when is_list(invoice_list) -> %>
<.table
rows={Enum.with_index(format_invoices(invoice_list))}
row_attrs={
fn {_invoice, idx} ->
%{
"x-show" => "showAll || #{idx} < 3"
}
end
}
>
<:tbody :let={{invoice, _idx}}>
<.td>{invoice.date}
<.td>{invoice.currency <> invoice.amount}
<.td class="flex justify-end">
<.styled_link href={invoice.url} new_tab={true}>
3}>
|
<.button
theme="secondary"
x-on:click="showAll = true"
x-show="!showAll"
>
Show more
|
<% end %>
<%= if Plausible.Billing.Subscriptions.resumable?(@subscription) && @subscription.cancel_url do %>
<.button_link theme="danger" href={@subscription.cancel_url} mt?={false}>
Cancel plan
<%= if Application.get_env(:plausible, :environment) == "dev" do %>
<.button_link
href={@subscription.update_url}
theme="secondary"
class="text-yellow-600 dark:text-yellow-400"
mt?={false}
>
[DEV ONLY] Change status
<% end %>
<% end %>
"""
end
on_ee do
defp consolidated_view_domain(team) do
view = Plausible.ConsolidatedView.get(team)
if not is_nil(view) and Plausible.ConsolidatedView.ok_to_display?(team) do
view.domain
end
end
end
end