diff --git a/routes/internal.py b/routes/internal.py index f83e941..9eacee5 100644 --- a/routes/internal.py +++ b/routes/internal.py @@ -226,7 +226,7 @@ def _sessions_by_weekday() -> dict: def _growth_data(weeks: int = 8) -> dict: now = datetime.now(timezone.utc) - labels, user_signups, session_counts, cash_in_weekly = [], [], [], [] + labels, user_signups, session_counts, league_counts = [], [], [], [] for i in range(weeks - 1, -1, -1): start = now - timedelta(weeks=i + 1) end = now - timedelta(weeks=i) @@ -240,22 +240,12 @@ def _growth_data(weeks: int = 8) -> dict: PokerSession.session_date < end_date, ).count() ) - cash = ( - db.session.query(db.func.coalesce(db.func.sum(LedgerEvent.amount_cents), 0)) - .filter( - LedgerEvent.event_type.in_(_CASH_IN_TYPES), - LedgerEvent.voided_at.is_(None), - LedgerEvent.created_at >= start, - LedgerEvent.created_at < end, - ) - .scalar() - ) - cash_in_weekly.append(round(int(cash or 0) / 100, 2)) + league_counts.append(League.query.filter(League.created_at >= start, League.created_at < end).count()) return { "labels": labels, "user_signups": user_signups, "session_counts": session_counts, - "cash_in_weekly": cash_in_weekly, + "league_counts": league_counts, } @@ -276,7 +266,7 @@ def _trend_cards(growth: dict) -> list[dict]: labels = growth["labels"] user_series = growth["user_signups"] session_series = growth["session_counts"] - cash_series = growth["cash_in_weekly"] + league_series = growth["league_counts"] current_start = datetime.now(timezone.utc) - timedelta(days=7) previous_start = current_start - timedelta(days=7) @@ -329,12 +319,12 @@ def _trend_cards(growth: dict) -> list[dict]: "series": [event_previous, event_current], }, { - "key": "volume", - "label": "Recorded volume", - "value": f"${cash_series[-1]:,.0f}" if cash_series else "$0", - "delta": _trend_delta(cash_series[-1] if cash_series else 0, cash_series[-2] if len(cash_series) > 1 else 0), + "key": "leagues", + "label": "New leagues", + "value": league_series[-1] if league_series else 0, + "delta": _trend_delta(league_series[-1] if league_series else 0, league_series[-2] if len(league_series) > 1 else 0), "labels": labels, - "series": cash_series, + "series": league_series, }, ] diff --git a/static/css/style.css b/static/css/style.css index 1af07e5..2aa6683 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -356,8 +356,27 @@ h1, h2, h3, h4 { margin: 0; } .int-breakdown-row__label { color: var(--muted); } .int-breakdown-row__val { font-weight: 600; color: var(--text-strong); font-variant-numeric: tabular-nums; } +.int-summary-grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 1px; + background: var(--border); + border-radius: 10px; + overflow: hidden; +} +.int-summary-item { + display: flex; + flex-direction: column; + gap: 4px; + padding: 16px 20px; + background: var(--surface); +} +.int-summary-item__val { font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--text-strong); line-height: 1; } +.int-summary-item__label { font-size: 12px; color: var(--muted); } + @media (max-width: 900px) { .int-hero-grid { grid-template-columns: repeat(2, 1fr); } + .int-summary-grid { grid-template-columns: repeat(2, 1fr); } .admin-searchbar { grid-template-columns: 1fr; } diff --git a/templates/internal_dashboard.html b/templates/internal_dashboard.html index 112be94..dacead0 100644 --- a/templates/internal_dashboard.html +++ b/templates/internal_dashboard.html @@ -40,7 +40,7 @@ {{ stats.active_leagues }} Active leagues - {{ stats.public_leagues }} public · {{ stats.archived_leagues }} archived · {{ '%.1f'|format(stats.avg_sessions_per_active_league) }} avg sessions + {{ stats.public_leagues }} public · {{ stats.archived_leagues }} archived
@@ -62,7 +62,7 @@
{{ stats.active_users_30d }} Active users · 30d - {{ stats.returning_users_30d }} returning · {{ stats.unverified_users }} unverified + {{ stats.users_in_leagues }} in leagues · {{ stats.orphan_users }} solo
@@ -110,15 +110,15 @@ - +
-

Recorded ledger volume

-

Buy-ins and collections · 8 weeks

+

Growth

+

New leagues per week · 8 weeks

- +
@@ -137,38 +137,25 @@

Activity breakdown

- 24h / 7d + 7d
-
New users (24h){{ stats.new_users_24h }}
New users (7d){{ stats.new_users_7d }}
-
Active users (24h){{ stats.active_users_24h }}
Active users (7d){{ stats.active_users_7d }}
Active users (30d){{ stats.active_users_30d }}
-
Returning users (7d){{ stats.returning_users_7d }}
-
Returning users (30d){{ stats.returning_users_30d }}
Users in leagues{{ stats.users_in_leagues }}
-
No-league signups{{ stats.orphan_users }}
-
Verified accounts{{ stats.verified_users }}
-
Unverified{{ stats.unverified_users }}
-
Disabled{{ stats.disabled_users }}
-
Site admins{{ stats.site_admins }}
+
Unverified accounts{{ stats.unverified_users }}
+
Disabled accounts{{ stats.disabled_users }}
-
Sessions (24h){{ stats.sessions_24h }}
Sessions (7d){{ stats.sessions_7d }}
Open sessions{{ stats.open_sessions }}
Leagues active (7d){{ stats.leagues_active_7d }}
-
Leagues with no sessions{{ stats.leagues_without_sessions }}
-
Sessions with no ledger records{{ stats.sessions_without_events }}
-
Avg players/session{{ '%.1f'|format(stats.avg_players_per_session) }}
-
Ledger events (24h){{ stats.ledger_events_24h }}
+
Avg players / session{{ '%.1f'|format(stats.avg_players_per_session) }}
Ledger events (7d){{ stats.ledger_events_7d }}
-
Total ledger events{{ stats.ledger_events }}
-
Voided ledger records{{ stats.voided_events }} · {{ '%.1f'|format(stats.void_rate) }}%
-
Avg sessions / league{{ stats.avg_sessions_per_active_league }}
+
Avg sessions / league{{ '%.1f'|format(stats.avg_sessions_per_active_league) }}
@@ -204,15 +191,19 @@
-

Recorded ledger volume

- Not platform revenue +

Totals at a glance

+ All time
-
-
Recorded buy-ins and collections${{ '%.2f'|format(stats.cash_in_cents / 100) }}
-
Recorded payouts${{ '%.2f'|format(stats.cash_out_cents / 100) }}
-
Average recorded volume / session${{ '%.2f'|format(stats.avg_cash_in_per_session_cents / 100) }}
-
Ledger records{{ stats.ledger_events }}
+
+
{{ stats.users }}Total users
+
{{ stats.leagues }}Total leagues
+
{{ stats.sessions }}Total sessions
+
{{ stats.ledger_events }}Ledger events
+
${{ '%.0f'|format(stats.cash_in_cents / 100) }}Recorded buy-ins
+
${{ '%.0f'|format(stats.cash_out_cents / 100) }}Recorded payouts
+
${{ '%.0f'|format(stats.avg_cash_in_per_session_cents / 100) }}Avg volume / session
+
{{ stats.verified_users }}Verified accounts
@@ -270,7 +261,7 @@ const labels = {{ growth.labels | tojson }}; const userSignups = {{ growth.user_signups | tojson }}; const sessionData = {{ growth.session_counts | tojson }}; - const cashData = {{ growth.cash_in_weekly | tojson }}; + const leagueData = {{ growth.league_counts | tojson }}; const wdLabels = {{ weekday_data.labels | tojson }}; const wdData = {{ weekday_data.data | tojson }}; const trendCards = {{ trend_cards | tojson }}; @@ -326,19 +317,13 @@ options: baseOpts, }); - new Chart(document.getElementById('chart-cash'), { + new Chart(document.getElementById('chart-leagues'), { type: 'bar', data: { labels, - datasets: [{ data: cashData, backgroundColor: 'rgba(120,180,240,.45)', borderColor: 'rgba(120,180,240,.9)', borderWidth: 1, borderRadius: 4 }] - }, - options: { - ...baseOpts, - scales: { - x: axisStyle, - y: { ...axisStyle, beginAtZero: true, ticks: { ...axisStyle.ticks, callback: v => '$' + v } }, - }, + datasets: [{ data: leagueData, backgroundColor: 'rgba(111,192,147,.45)', borderColor: 'rgba(111,192,147,.9)', borderWidth: 1, borderRadius: 4 }] }, + options: baseOpts, }); new Chart(document.getElementById('chart-weekday'), {