Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .vitepress/theme/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import DefaultTheme from 'vitepress/theme';
import { h } from 'vue';
import CsvTable from '@/components/CsvTable.vue';
import NavCards from '@/components/NavCards.vue';
import ReferralRewardsTable from '@/components/ReferralRewardsTable.vue';
import './style.css';

export default {
Expand All @@ -16,6 +17,7 @@ export default {
enhanceAppWithTabs(app);
app.component('CsvTable', CsvTable);
app.component('NavCards', NavCards);
app.component('ReferralRewardsTable', ReferralRewardsTable);
app.component('CopyOrDownloadAsMarkdownButtons', CopyOrDownloadAsMarkdownButtons);
},
} satisfies Theme;
159 changes: 159 additions & 0 deletions components/ReferralRewardsTable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';

interface Plan {
price: string;
}

interface Tier {
name: string;
referrer_reward_percentage: number;
monthly_plan: Plan;
yearly_plan: Plan;
}

interface ReferralProgram {
referee_discount_percentage: string;
tiers: Tier[];
}

const { endpoint = 'https://rotki.com/webapi/2/referral/program' } = defineProps<{
endpoint?: string;
}>();

const data = ref<ReferralProgram>();
const loading = ref(true);
const error = ref(false);

const tiers = computed(() => {
if (!data.value)
return [];

return [...data.value.tiers].sort(
(a, b) => Number(a.monthly_plan.price) - Number(b.monthly_plan.price),
);
});

const hasTiers = computed(() => tiers.value.length > 0);

const refereeDiscount = computed(() => {
if (!data.value)
return '';

return formatPercentage(data.value.referee_discount_percentage);
});

function formatPercentage(value: string | number): string {
return `${Number(value)}%`;
}

function formatPrice(value: string): string {
return `$${Number(value).toFixed(2)}`;
}

onMounted(async () => {
try {
const response = await fetch(endpoint);
if (!response.ok)
throw new Error(`Request failed with status ${response.status}`);

data.value = await response.json();
}
catch {
error.value = true;
}
finally {
loading.value = false;
}
});
</script>

<template>
<div class="referral-table">
<p
v-if="loading"
class="referral-table__status"
>
Loading current rates&hellip;
</p>

<div
v-else-if="error || !hasTiers"
class="referral-table__empty"
>
<p class="referral-table__empty-title">
Current rates couldn't be loaded
</p>
<p class="referral-table__empty-body">
The live rates aren't available right now. You can always see the exact
discount and reward on your
<a href="https://rotki.com/home/subscription">subscription page</a>,
where they're shown at the point they apply.
</p>
</div>

<template v-else>
<p class="referral-table__caption">
People who use your code get <strong>{{ refereeDiscount }}</strong> off
their first subscription payment. You earn account credit based on the
plan they pick:
</p>
<table>
<thead>
<tr>
<th>Plan</th>
<th>Monthly</th>
<th>Yearly</th>
<th>Your reward</th>
</tr>
</thead>
<tbody>
<tr
v-for="tier in tiers"
:key="tier.name"
>
<td>{{ tier.name }}</td>
<td>{{ formatPrice(tier.monthly_plan.price) }}</td>
<td>{{ formatPrice(tier.yearly_plan.price) }}</td>
<td>{{ formatPercentage(tier.referrer_reward_percentage) }}</td>
</tr>
</tbody>
</table>
<p class="referral-table__note">
Rates are pulled live from rotki and may change. The reward is a
percentage of what the referred person pays.
</p>
</template>
</div>
</template>

<style scoped>
.referral-table__status,
.referral-table__caption {
margin-top: 1rem;
}

.referral-table__note {
font-size: 0.85em;
opacity: 0.75;
}

.referral-table__empty {
margin-top: 1rem;
padding: 1rem 1.25rem;
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background-color: var(--vp-c-bg-soft);
}

.referral-table__empty-title {
margin: 0 0 0.25rem;
font-weight: 600;
}

.referral-table__empty-body {
margin: 0;
font-size: 0.9em;
color: var(--vp-c-text-2);
}
</style>
2 changes: 2 additions & 0 deletions premium/referrals.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ A referral discount applies only to the first payment of a new subscription. Ren

When someone you referred makes their first qualifying purchase, you receive account credit based on what they paid.

<ReferralRewardsTable />

- Your balance and a full history of credit earned and used appear in the Account Credit section of your [subscription page](https://rotki.com/home/subscription).
- Credit is applied automatically to your subscription purchases, renewals, and upgrades. You do not need to enter anything.
- Credit is granted once per referred user, on their first non-upgrade purchase.
Expand Down