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:
@@ -4,6 +4,7 @@ import { Users, TrendingUp, Clock, Download, BarChart3 } from 'lucide-vue-next'
|
||||
import * as echarts from 'echarts'
|
||||
import type { ECharts } from 'echarts'
|
||||
import { useApi } from '@/composables/useApi'
|
||||
import { safeFixed } from '@/utils/formatters'
|
||||
|
||||
const api = useApi()
|
||||
|
||||
@@ -88,7 +89,7 @@ const renderCharts = () => {
|
||||
formatter: (params: any) => {
|
||||
let tooltip = `<strong>${params[0].axisValue}</strong><br/>`
|
||||
params.forEach((param: any) => {
|
||||
tooltip += `${param.marker} ${param.seriesName}: ${param.value.toFixed(1)}%<br/>`
|
||||
tooltip += `${param.marker} ${param.seriesName}: ${safeFixed(param.value, 1)}%<br/>`
|
||||
})
|
||||
return tooltip
|
||||
}
|
||||
@@ -236,7 +237,7 @@ onMounted(() => {
|
||||
<p class="text-sm text-neutral-400">Avg Session</p>
|
||||
</div>
|
||||
<p class="text-2xl font-bold text-neutral-100">
|
||||
{{ retentionData.summary.avg_session_duration_minutes.toFixed(0) }}m
|
||||
{{ safeFixed(retentionData?.summary?.avg_session_duration_minutes, 0) }}m
|
||||
</p>
|
||||
<p class="text-xs text-neutral-600 mt-1">Duration</p>
|
||||
</div>
|
||||
@@ -308,15 +309,15 @@ onMounted(() => {
|
||||
</td>
|
||||
<td class="py-3 px-3 text-right">
|
||||
<span class="text-neutral-100 font-medium">{{ wipe.returned_24h }}</span>
|
||||
<span class="text-neutral-500 text-xs ml-1">({{ wipe.retention_24h_percent.toFixed(1) }}%)</span>
|
||||
<span class="text-neutral-500 text-xs ml-1">({{ safeFixed(wipe.retention_24h_percent, 1) }}%)</span>
|
||||
</td>
|
||||
<td class="py-3 px-3 text-right">
|
||||
<span class="text-neutral-100 font-medium">{{ wipe.returned_48h }}</span>
|
||||
<span class="text-neutral-500 text-xs ml-1">({{ wipe.retention_48h_percent.toFixed(1) }}%)</span>
|
||||
<span class="text-neutral-500 text-xs ml-1">({{ safeFixed(wipe.retention_48h_percent, 1) }}%)</span>
|
||||
</td>
|
||||
<td class="py-3 px-3 text-right">
|
||||
<span class="text-neutral-100 font-medium">{{ wipe.returned_72h }}</span>
|
||||
<span class="text-neutral-500 text-xs ml-1">({{ wipe.retention_72h_percent.toFixed(1) }}%)</span>
|
||||
<span class="text-neutral-500 text-xs ml-1">({{ safeFixed(wipe.retention_72h_percent, 1) }}%)</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
Reference in New Issue
Block a user