jcloud/dashboard/src/views/marketplace/MarketplaceAppAnalytics.vue

254 lines
6.0 KiB
Vue

<template>
<div
v-if="$resources.analytics.data"
class="grid grid-cols-1 gap-5 sm:grid-cols-2"
>
<Card :title="$t('Earnings')">
<template #actions>
<a
class="text-base text-gray-700 hover:text-gray-800"
href="/support/tickets"
target="_blank"
>
{{ $t('Contact Support') }} →
</a>
</template>
<ListItem
:title="$t('Total Earnings')"
:subtitle="$t('Total earnings for {app}', { app: app.title })"
>
<template #actions>
<span class="text-base font-semibold text-green-500">{{
'$' +
paymentAnalytics.total_payout.usd +
' + ' +
'¥' +
paymentAnalytics.total_payout.cny
}}</span>
</template>
</ListItem>
<ListItem
:title="$t('Pending Payout')"
:subtitle="$t('Payout you are yet to receive from Jingrow')"
>
<template #actions>
<span class="text-base font-semibold">{{
'$' +
paymentAnalytics.pending_payout.usd +
' + ' +
'¥' +
paymentAnalytics.pending_payout.cny
}}</span>
</template>
</ListItem>
<ListItem
:title="$t('Commission')"
:subtitle="$t('Payouts start once you have passed $500 threshold')"
>
<template #actions>
<span class="text-base font-semibold">{{
'$' +
paymentAnalytics.commission.usd +
' + ' +
'¥' +
paymentAnalytics.commission.cny
}}</span>
</template>
</ListItem>
</Card>
<Card :title="$t('Installs')">
<div class="divide-y" v-if="analytics">
<ListItem
v-for="stat in analytics"
:key="stat.title"
:title="stat.title"
:description="stat.value"
>
</ListItem>
</div>
<div class="py-10 text-center" v-if="$resources.analytics.loading">
<Button :loading="true">{{ $t('Loading') }}</Button>
</div>
</Card>
<LineChart
:title="$t('Pageviews')"
type="time"
:key="pageViewsData"
:data="pageViewsData"
unit="views"
:chartTheme="[$theme.colors.purple[500]]"
:loading="$resources.plausible_analytics.loading"
:error="$resources.plausible_analytics.error"
>
<template #actions>
<a
v-if="app"
class="text-base text-gray-700 hover:text-gray-800"
:href="`/marketplace/apps/${app.app}`"
target="_blank"
>
{{ $t('View Marketplace Page') }}
</a>
</template>
</LineChart>
<LineChart
:title="$t('Unique Visitors')"
type="time"
:key="visitorsData"
:data="visitorsData"
unit="visitors"
:chartTheme="[$theme.colors.green[500]]"
:loading="$resources.plausible_analytics.loading"
:error="$resources.plausible_analytics.error"
/>
</div>
</template>
<script>
import { DateTime } from 'luxon';
import LineChart from '@/components/charts/LineChart.vue';
export default {
name: 'MarketplaceAppAnalytics',
props: {
app: Object
},
components: {
LineChart
},
methods: {
formatDate(data) {
return data.map(d => d.date);
},
getChartOptions(yFormatter) {
return {
axisOptions: {
xIsSeries: true,
shortenYAxisNumbers: 1
},
lineOptions: {
hideDots: true,
regionFill: true
},
tooltipOptions: {
formatTooltipX: d => {
return DateTime.fromISO(d).toLocaleString(DateTime.DATE_MED);
},
formatTooltipY: yFormatter
}
};
}
},
resources: {
analytics() {
return {
url: 'jcloud.api.marketplace.analytics',
auto: true,
params: {
name: this.app?.app
}
};
},
plausible_analytics() {
return {
url: 'jcloud.api.analytics.plausible_analytics',
auto: true,
params: {
name: this.app?.app
}
};
}
},
computed: {
analytics() {
if (
!this.$resources.analytics.loading &&
this.$resources.analytics.data
) {
const analyticsData = this.$resources.analytics.data;
const {
total_installs,
num_installs_active_sites,
num_installs_active_benches
} = analyticsData;
return [
{
title: this.$t('Total Installs'),
value:
total_installs.toString() +
' ' +
(total_installs == 1 ? this.$t('Site') : this.$t('Sites'))
},
{
title: this.$t('Active Sites with this App'),
value:
num_installs_active_sites.toString() +
' ' +
(num_installs_active_sites == 1 ? this.$t('Site') : this.$t('Sites'))
},
{
title: this.$t('Active Benches with this App'),
value:
num_installs_active_benches.toString() +
' ' +
(num_installs_active_benches == 1 ? this.$t('Bench') : this.$t('Benches'))
}
];
}
},
pageViewsData() {
let pageViews = this.$resources.plausible_analytics.data?.pageviews;
if (!pageViews) return;
return {
datasets: [pageViews.map(d => [+new Date(d.date), d.value])]
};
},
visitorsData() {
let visitorsData = this.$resources.plausible_analytics.data?.visitors;
if (!visitorsData) return;
return {
datasets: [visitorsData.map(d => [+new Date(d.date), d.value])]
};
},
paymentAnalytics() {
if (
!this.$resources.analytics.loading &&
this.$resources.analytics.data
) {
let data = this.$resources.analytics.data;
return {
total_payout: {
usd: data.total_payout.usd_amount
? data.total_payout.usd_amount.toFixed(2)
: 0.0,
cny: data.total_payout.cny_amount
? data.total_payout.cny_amount.toFixed(2)
: 0.0
},
pending_payout: {
usd: data.pending_payout.usd_amount
? data.pending_payout.usd_amount.toFixed(2)
: 0.0,
cny: data.pending_payout.cny_amount
? data.pending_payout.cny_amount.toFixed(2)
: 0.0
},
commission: {
usd: data.commission.usd_amount
? data.commission.usd_amount.toFixed(2)
: 0.0,
cny: data.commission.cny_amount
? data.commission.cny_amount.toFixed(2)
: 0.0
}
};
}
}
}
};
</script>