Add subscription management page and currency widget

This commit is contained in:
2021-11-16 21:11:59 +01:00
parent 312b6e8a89
commit 772bb40030
7 changed files with 238 additions and 67 deletions

View File

@@ -303,10 +303,6 @@ p, .indent {
margin: 10px;
}
li {
margin-bottom: 0.3em;
}
hr{
height: 1px;
border: none;

View File

@@ -4,6 +4,7 @@ import { formatDataVolume, formatThousands } from "../util/Formatting.svelte";
import Chart from "../util/Chart.svelte";
import StorageProgressBar from "./StorageProgressBar.svelte";
import HotlinkProgressBar from "./HotlinkProgressBar.svelte";
import Euro from "../util/Euro.svelte"
let graph_view = null
let graph_download = null
@@ -128,11 +129,11 @@ onDestroy(() => {
Max file size: {formatDataVolume(window.user.subscription.file_size_limit, 3)}
</li>
<li>
Advertisements when viewing files:
Advertisements when you view files:
{#if window.user.subscription.disable_ad_display}No{:else}Yes{/if}
</li>
<li>
Advertisements on your uploaded files:
Advertisements when others view your files:
{#if window.user.subscription.disable_ads_on_files}No{:else}Yes{/if}
</li>
{#if window.user.subscription.file_expiry_days > 0}
@@ -142,6 +143,11 @@ onDestroy(() => {
{/if}
</ul>
</li>
{#if window.user.balance_micro_eur !== 0}
<li>
Current account balance: <Euro amount={window.user.balance_micro_eur}></Euro>
</li>
{/if}
</ul>
{#if window.user.subscription.storage_space === -1}
@@ -150,7 +156,7 @@ onDestroy(() => {
<StorageProgressBar used={storage_space_used} total={window.user.subscription.storage_space}></StorageProgressBar>
{/if}
{#if window.user.subscription.storage_space === -1}
{#if window.user.subscription.direct_linking_bandwidth === -1}
Hotlink bandwidth used in the last 30 days: {formatDataVolume(direct_link_bandwidth_used, 3)}<br/>
{:else}
<HotlinkProgressBar used={direct_link_bandwidth_used} total={window.user.subscription.direct_linking_bandwidth}></HotlinkProgressBar>

View File

@@ -4,6 +4,7 @@ import Home from "./Home.svelte";
import AccountSettings from "./AccountSettings.svelte";
import APIKeys from "./APIKeys.svelte";
import Transactions from "./Transactions.svelte";
import Subscription from "./Subscription.svelte";
let page = ""
@@ -62,6 +63,13 @@ onMount(() => {
<i class="icon">receipt_long</i>
Transactions
</a>
<a class="button"
href="/user/subscription"
class:button_highlight={page === "subscription"}
on:click|preventDefault={() => {navigate("subscription", "Subscription")}}>
<i class="icon">shopping_cart</i>
Subscription
</a>
{/if}
</div>
@@ -73,5 +81,7 @@ onMount(() => {
<APIKeys></APIKeys>
{:else if page === "transactions"}
<Transactions></Transactions>
{:else if page === "subscription"}
<Subscription></Subscription>
{/if}
</div>

View File

@@ -0,0 +1,186 @@
<script>
import Spinner from "../util/Spinner.svelte";
import Euro from "../util/Euro.svelte"
let loading = false
let result = ""
let result_success = false
const update_subscription = async name => {
loading = true
const form = new FormData()
form.append("subscription", name)
try {
const resp = await fetch(
window.api_endpoint+"/user/subscription",
{ method: "PUT", body: form },
)
if(resp.status >= 400) {
let json = await resp.json()
throw json.message
}
result_success = true
result = "Subscription updated"
setTimeout(() => {location.reload()}, 1000)
} catch (err) {
result_success = false
result = "Failed to update subscription: "+err
loading = false
}
}
</script>
<div>
{#if loading}
<div class="spinner_container">
<Spinner />
</div>
{/if}
<div class="limit_width">
<h2>Manage subscription</h2>
<p>
Current account balance: <Euro amount={window.user.balance_micro_eur}></Euro>
</p>
<p>
When your prepaid subscription is active you will be charged daily
based on usage. Hotlink bandwidth is charged per TB based on the
usage of the previous day. The amount charged for storage each day
is your storage usage at the end of the day multiplied by the
storage price (€4 / TB) and divided by the average number of days in
a month (30.4375). So if you have exactly 1 TB on your account you
will be charged €0.131416838 per day.
</p>
<p>
The prepaid subscription will stay active for as long as you have
credit on your account. When you reach negative balance the
subscription will automatically end. You will need a positive
balance to activate the subscription again.
</p>
{#if result !== ""}
<div class:highlight_green={result_success} class:highlight_red={!result_success}>
{result}
</div>
{/if}
<div class="feat_table">
<div>
<div class="feat_label" class:feat_highlight={window.user.subscription.id === "prepaid"}>
Prepaid<br/>
{#if window.user.subscription.id === "prepaid"}
Currently active
{:else}
<button on:click={() => {update_subscription("prepaid")}}>
<i class="icon">attach_money</i>
Activate
</button>
{/if}
</div>
<div class="feat_normal round_tr">
<ul>
<li>Base price of €2 per month</li>
<li>€4 per TB per month for storage</li>
<li>€2 per TB for hotlink bandwidth</li>
<li>No bandwidth limit, your files will download at the highest speed possible</li>
</ul>
</div>
</div>
<div>
<div class="feat_label" class:feat_highlight={window.user.subscription.id === "prepaid_storage"}>
Prepaid (just storage)<br/>
{#if window.user.subscription.id === "prepaid_storage"}
Currently active
{:else}
<button on:click={() => {update_subscription("prepaid_storage")}}>
<i class="icon">attach_money</i>
Activate
</button>
{/if}
</div>
<div class="feat_normal">
<ul>
<li>Base price of €0.10 per month</li>
<li>€4 per TB per month for storage</li>
<li>No hotlink bandwidth (rate limiting will be enabled when a file uses too much bandwidth)</li>
<li>You don't see ads, but people downloading your files do see ads</li>
</ul>
</div>
</div>
<div>
<div class="feat_label" class:feat_highlight={window.user.subscription.id === ""}>
Free<br/>
{#if window.user.subscription.id === ""}
Currently active
{:else}
<button on:click={() => {update_subscription("none")}}>
<i class="icon">money_off</i>
Activate
</button>
{/if}
</div>
<div class="feat_normal round_br">
<ul>
<li>Standard free plan, files expire after 30 days.</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<style>
.spinner_container {
position: absolute;
top: 10px;
left: 10px;
height: 100px;
width: 100px;
z-index: 1000;
}
.feat_table {
display: flex;
flex-direction: column;
}
.feat_table > div {
display: flex;
flex-direction: row;
}
.feat_table > div > div:first-child {
flex: 0 0 25%;
max-width: 25%;
}
.feat_table > div > div {
flex: 1 1 0;
margin: 0.25em;
padding: 0.5em;
word-wrap: break-word;
hyphens: auto;
}
.feat_table > div > .feat_label {
border-top-left-radius: 0.5em;
border-bottom-left-radius: 0.5em;
background-color: var(--layer_1_color);
font-size: 1.1em;
color: #ffffff;
text-shadow: 0 0 3px #000000;
}
.feat_table > div > .feat_normal {
background-color: var(--layer_3_color);
box-shadow: 1px 1px 3px -1px var(--shadow_color);
text-shadow: 1px 1px 3px var(--shadow_color);
}
.feat_table > div > .feat_highlight {
border: 1px solid var(--highlight_color)
}
.feat_table > div > div.round_tl { border-top-left-radius: 0.5em; }
.feat_table > div > div.round_tr { border-top-right-radius: 0.5em; }
.feat_table > div > div.round_br { border-bottom-right-radius: 0.5em; }
.feat_table > div > div.round_bl { border-bottom-left-radius: 0.5em; }
</style>

View File

@@ -1,7 +1,8 @@
<script>
import { onMount } from "svelte";
import { formatDataVolume, formatDate, formatEuros } from "../util/Formatting.svelte";
import { formatDataVolume, formatDate } from "../util/Formatting.svelte";
import Spinner from "../util/Spinner.svelte";
import Euro from "../util/Euro.svelte"
let loading = false
let months = []
@@ -102,55 +103,6 @@ onMount(() => {
</div>
{/if}
<div class="limit_width">
<h2>Manage subscription</h2>
<p>
Current account balance: {formatEuros(window.user.balance_micro_eur, 4)}
</p>
{#if result !== ""}
<div class:highlight_green={result_success} class:highlight_red={!result_success}>
{result}
</div>
{/if}
<div class="highlight_dark">
{#if window.user.subscription.id !== "prepaid"}
Prepaid subscription is not active.<br/>
<button on:click={() => {update_subscription("prepaid")}}>
<i class="icon">attach_money</i>
Enable prepaid subscription
</button>
{:else}
Prepaid subscription is active.<br/>
Deactivating your subscription may cause your files to expire
sooner than expected!<br/>
<button on:click={() => {update_subscription("none")}}>
<i class="icon">money_off</i>
Disable prepaid subscription
</button>
{/if}
</div>
<p>
When your prepaid subscription is active you will be charged:
</p>
<ul>
<li>
€4 per TB per month for storage. The amount is charged per day
and divided by the average number of days in a month (30.4375).
So if you have exactly 1 TB on your account you will be charged
€0.131416838 per day.
</li>
<li>
€2 per TB of bandwidth, charged every day based on the usage of
the previous day
</li>
<li>
€2 per month for the subscription itself, because prepaid has
the same perks as the Pro subscription (No advertisements, no
bandwidth limit, video player, etc)
</li>
</ul>
<h2>Transaction log</h2>
<p>
Here is a log of all transactions on your account balance.
@@ -159,11 +111,11 @@ onMount(() => {
{#each months as month}
<h3>{month.month}</h3>
<ul>
<li>Subscription charge: {formatEuros(month.total_subscription_charge, 4)}</li>
<li>Storage charge: {formatEuros(month.total_storage_charge, 4)}</li>
<li>Bandwidth charge: {formatEuros(month.total_bandwidth_charge, 4)}</li>
<li>Total charge: {formatEuros(month.total_deducted, 4)}</li>
<li>Deposited: {formatEuros(month.total_deposited, 4)}</li>
<li>Subscription charge: <Euro amount={month.total_subscription_charge}></Euro></li>
<li>Storage charge: <Euro amount={month.total_storage_charge}></Euro></li>
<li>Bandwidth charge: <Euro amount={month.total_bandwidth_charge}></Euro></li>
<li>Total charge: <Euro amount={month.total_deducted}></Euro></li>
<li>Deposited: <Euro amount={month.total_deposited}></Euro></li>
</ul>
<div class="table_scroll">
@@ -192,13 +144,13 @@ onMount(() => {
{#each month.rows as row}
<tr>
<td>{formatDate(row.time, true, true, false)}</td>
<td>{formatEuros(row.new_balance, 4)}</td>
<td>{formatEuros(row.subscription_charge, 4)}</td>
<td>{formatEuros(row.storage_charge, 4)}</td>
<td><Euro amount={row.new_balance}></Euro></td>
<td><Euro amount={row.subscription_charge} precision="4"></Euro></td>
<td><Euro amount={row.storage_charge} precision="4"></Euro></td>
<td>{formatDataVolume(row.storage_used, 3)}</td>
<td>{formatEuros(row.bandwidth_charge, 4)}</td>
<td><Euro amount={row.bandwidth_charge} precision="4"></Euro></td>
<td>{formatDataVolume(row.bandwidth_used, 3)}</td>
<td>{formatEuros(row.deposit_amount, 4)}</td>
<td><Euro amount={row.deposit_amount}></Euro></td>
</tr>
{/each}
</tbody>

View File

@@ -0,0 +1,20 @@
<script>
export let amount = 0
export let precision = 2
</script>
<span>
<span class:red={amount < 0} class:green={amount > 0}>
{(amount / 1000000).toFixed(precision)}
</span>
</span>
<style>
.red {
color: var(--danger_color);
}
.green {
color: var(--highlight_color);
}
</style>

View File

@@ -179,6 +179,7 @@ func New(
{GET, "user/settings" /* */, wc.serveTemplate("user_home", handlerOpts{Auth: true})},
{GET, "user/api_keys" /* */, wc.serveTemplate("user_home", handlerOpts{Auth: true})},
{GET, "user/transactions" /* */, wc.serveTemplate("user_home", handlerOpts{Auth: true})},
{GET, "user/subscription" /* */, wc.serveTemplate("user_home", handlerOpts{Auth: true})},
{GET, "user/confirm_email" /* */, wc.serveEmailConfirm},
{GET, "user/password_reset_confirm" /**/, wc.serveForm(wc.passwordResetConfirmForm, handlerOpts{NoEmbed: true})},
{PST, "user/password_reset_confirm" /**/, wc.serveForm(wc.passwordResetConfirmForm, handlerOpts{NoEmbed: true})},