fix: Replace unsafe .toFixed() calls with safeFixed() in analytics views

- AnalyticsView: avg_players, uptime_percentage
- WipeAnalyticsView: success_rate, population curve, durations, CSV export
- PlayerRetentionView: retention percentages, session duration, tooltip
- MapAnalyticsView: rotation effectiveness, performance metrics, table

All analytics views now use safe formatter utilities with optional chaining
to prevent null/undefined runtime errors when displaying numeric data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Vantz Stockwell
2026-02-15 21:56:04 -05:00
parent daa9c3035f
commit 26e717ac96
18 changed files with 111 additions and 53 deletions

View File

@@ -3,6 +3,7 @@ import { ref, onMounted } from 'vue'
import { useApi } from '@/composables/useApi'
import { useRouter } from 'vue-router'
import { Key, KeyRound, Users, DollarSign, Server, UserPlus, ArrowRight, ScrollText, CreditCard, MonitorCog } from 'lucide-vue-next'
import { safeCurrency, safeLocaleString } from '@/utils/formatters'
const api = useApi()
const router = useRouter()
@@ -36,11 +37,10 @@ const quickLinks = [
]
function formatValue(value: number | undefined, format: string): string {
if (value == null) return '\u2014'
if (format === 'currency') {
return `$${value.toFixed(2)}`
return safeCurrency(value, '$', '\u2014')
}
return value.toLocaleString()
return safeLocaleString(value, '\u2014')
}
async function fetchStats() {

View File

@@ -2,6 +2,7 @@
import { ref, computed, onMounted } from 'vue'
import { useApi } from '@/composables/useApi'
import { CreditCard, Package, DollarSign, Users } from 'lucide-vue-next'
import { safeCurrency, safeLocaleString } from '@/utils/formatters'
const api = useApi()
@@ -78,7 +79,7 @@ onMounted(() => {
<p class="text-sm text-neutral-400">Total Subscribers</p>
</div>
<div v-if="isLoading" class="h-8 w-16 bg-neutral-800 rounded animate-pulse" />
<p v-else class="text-3xl font-bold text-neutral-100">{{ totalSubscribers.toLocaleString() }}</p>
<p v-else class="text-3xl font-bold text-neutral-100">{{ safeLocaleString(totalSubscribers) }}</p>
</div>
<!-- Total MRR -->
@@ -90,7 +91,7 @@ onMounted(() => {
<p class="text-sm text-neutral-400">Total MRR</p>
</div>
<div v-if="isLoading" class="h-8 w-24 bg-neutral-800 rounded animate-pulse" />
<p v-else class="text-3xl font-bold text-neutral-100">${{ totalMrr.toFixed(2) }}</p>
<p v-else class="text-3xl font-bold text-neutral-100">{{ safeCurrency(totalMrr, '$') }}</p>
</div>
<!-- Per-Module Cards -->