mirror of
https://github.com/pupperpowell/bibdle.git
synced 2026-10-22 05:54:10 -04:00
first pass analytics redo
This commit is contained in:
1 parent
b656fd04c0
commit
45ffa39f2a
69 files changed
+6400
-1138
No files matched your search
@@ -0,0 +1,83 @@
|
||||
<script lang="ts">
|
||||
import Container from '$lib/components/Container.svelte';
|
||||
import CohortHeatmap from '$lib/components/charts/CohortHeatmap.svelte';
|
||||
import MiniLineChart from '$lib/components/charts/MiniLineChart.svelte';
|
||||
import BarList from '$lib/components/charts/BarList.svelte';
|
||||
import type { SnapshotPayload, StatsSettings } from '$lib/types/stats';
|
||||
import { pctOrDash, numOrDash } from '$lib/utils/stats-format';
|
||||
|
||||
interface Props {
|
||||
payload: SnapshotPayload;
|
||||
settings: StatsSettings;
|
||||
}
|
||||
let { payload, settings }: Props = $props();
|
||||
|
||||
const mix = $derived(payload.retention.segmentMix);
|
||||
const colors = ['#60a5fa', '#34d399', '#a78bfa', '#f59e0b', '#fb7185'];
|
||||
</script>
|
||||
|
||||
<section class="flex flex-col gap-3">
|
||||
<h2 class="text-lg font-bold text-gray-100">3 · Retention Lab</h2>
|
||||
|
||||
<div class="grid gap-3 md:grid-cols-2">
|
||||
<Container class="p-4 w-full items-start text-left">
|
||||
<p class="text-[11px] font-semibold uppercase tracking-wider text-gray-400">
|
||||
Overall return rate
|
||||
</p>
|
||||
<p class="text-2xl font-bold text-gray-100">
|
||||
{pctOrDash(payload.kpis.overallReturnRate)}
|
||||
</p>
|
||||
<p class="text-xs text-gray-400">
|
||||
Share of all players who ever played more than once. Target:
|
||||
{settings.return7_target}%+ within 7 days.
|
||||
</p>
|
||||
</Container>
|
||||
<Container class="p-4 w-full items-start text-left">
|
||||
<p class="text-[11px] font-semibold uppercase tracking-wider text-gray-400">
|
||||
Time to second play
|
||||
</p>
|
||||
<BarList items={payload.retention.timeToSecondPlay.map((b) => ({ label: b.label, value: b.value }))} />
|
||||
</Container>
|
||||
</div>
|
||||
|
||||
<Container class="p-4 w-full items-stretch text-left gap-2">
|
||||
<p class="font-semibold text-gray-100">Cohort retention triangle</p>
|
||||
<p class="text-xs text-gray-400">
|
||||
Each row is a starting week; each column is weeks later. Darker = more came back.
|
||||
Only resolved weeks are filled.
|
||||
</p>
|
||||
<CohortHeatmap cohorts={payload.retention.cohorts} weeks={8} />
|
||||
</Container>
|
||||
|
||||
<Container class="p-4 w-full items-stretch text-left gap-2">
|
||||
<p class="font-semibold text-gray-100">Retention curves</p>
|
||||
<p class="text-xs text-gray-400">
|
||||
D1 / D7 / D30 return over time. Latest resolvable cohorts only.
|
||||
</p>
|
||||
<MiniLineChart
|
||||
series={[
|
||||
{ name: 'D1', color: '#34d399', points: payload.retention.curves.d1 },
|
||||
{ name: 'D7', color: '#60a5fa', points: payload.retention.curves.d7 },
|
||||
{ name: 'D30', color: '#a78bfa', points: payload.retention.curves.d30 }
|
||||
]}
|
||||
ySuffix="%"
|
||||
/>
|
||||
</Container>
|
||||
|
||||
<Container class="p-4 w-full items-stretch text-left gap-2">
|
||||
<p class="font-semibold text-gray-100">Segment mix over time</p>
|
||||
<p class="text-xs text-gray-400">
|
||||
Active players split into new, core, returning, at-risk and churned. Total tracked:
|
||||
{numOrDash(payload.activity.mau)} recently active.
|
||||
</p>
|
||||
<MiniLineChart
|
||||
series={[
|
||||
{ name: 'New', color: colors[0], points: mix.map((m) => ({ date: m.date, value: m.new })) },
|
||||
{ name: 'Core', color: colors[1], points: mix.map((m) => ({ date: m.date, value: m.core })) },
|
||||
{ name: 'Returning', color: colors[2], points: mix.map((m) => ({ date: m.date, value: m.returning })) },
|
||||
{ name: 'At risk', color: colors[3], points: mix.map((m) => ({ date: m.date, value: m.atRisk })) },
|
||||
{ name: 'Churned', color: colors[4], points: mix.map((m) => ({ date: m.date, value: m.churned })) }
|
||||
]}
|
||||
/>
|
||||
</Container>
|
||||
</section>
|
||||
Reference in new issue
Block a user