feat: align frontend with rusty-telemetry v0.5.0 API changes
- Update ShiftPointAnalysis types: gear_ranges → gear_curves (with acceleration data points), shift_events → crossover_points, add runs_analyzed field - Add UseCaseInfo type for GET /api/use-cases (now returns objects with id, name, guidance instead of plain strings) - Add guidance and recording_id fields to UseCaseSession - Rewrite ShiftPointsView: scatter chart for gear acceleration curves, dual y-axis bar chart for crossover RPM/speed, 4-column summary - Update SessionDetailView: show session guidance, crossover points and runs analyzed in analysis stats - Extract shared type guard functions into src/utils/analysis.ts - Type getAnalysis/reAnalyze as AnalysisResult instead of Record<string, unknown> - Type getGames return as string[] to match backend
This commit is contained in:
parent
aa6293d346
commit
87e5bcae5b
6 changed files with 156 additions and 114 deletions
|
|
@ -3,6 +3,7 @@ import { ref, onMounted, computed } from 'vue'
|
|||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useSessionsStore } from '@/stores/sessions'
|
||||
import type { ShiftPointAnalysis, TrackMapAnalysis } from '@/types'
|
||||
import { isShiftPointAnalysis, isTrackMapAnalysis } from '@/utils/analysis'
|
||||
|
||||
const props = defineProps<{
|
||||
id: string
|
||||
|
|
@ -34,19 +35,16 @@ const analysisData = computed(() => {
|
|||
|
||||
const shiftAnalysis = computed((): ShiftPointAnalysis | null => {
|
||||
if (!analysisData.value) return null
|
||||
// The analysis field is the full analysis object
|
||||
const data = analysisData.value
|
||||
if (data && typeof data === 'object' && 'gear_ranges' in data) {
|
||||
return data as unknown as ShiftPointAnalysis
|
||||
if (isShiftPointAnalysis(analysisData.value)) {
|
||||
return analysisData.value
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
const trackAnalysis = computed((): TrackMapAnalysis | null => {
|
||||
if (!analysisData.value) return null
|
||||
const data = analysisData.value
|
||||
if (data && typeof data === 'object' && 'boundaries' in data) {
|
||||
return data as unknown as TrackMapAnalysis
|
||||
if (isTrackMapAnalysis(analysisData.value)) {
|
||||
return analysisData.value
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
|
@ -147,6 +145,10 @@ async function handleDelete() {
|
|||
<span class="info-label">Completed</span>
|
||||
<span>{{ formatTime(session.completed_at) }}</span>
|
||||
</div>
|
||||
<div v-if="session.guidance" class="info-item" style="grid-column: 1 / -1">
|
||||
<span class="info-label">Guidance</span>
|
||||
<span class="text-secondary" style="font-size: 0.85rem">{{ session.guidance }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
|
@ -243,14 +245,18 @@ async function handleDelete() {
|
|||
</div>
|
||||
|
||||
<!-- Quick stats for shift points -->
|
||||
<div v-if="shiftAnalysis" class="analysis-stats grid grid-2 mb-2">
|
||||
<div v-if="shiftAnalysis" class="analysis-stats grid grid-3 mb-2">
|
||||
<div class="stat-card">
|
||||
<span class="stat-label">Recommended Shift RPM</span>
|
||||
<span class="stat-value mono">{{ Math.round(shiftAnalysis.recommended_shift_rpm ?? 0) }}</span>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span class="stat-label">Shift Events Detected</span>
|
||||
<span class="stat-value mono">{{ shiftAnalysis.shift_events.length }}</span>
|
||||
<span class="stat-label">Crossover Points</span>
|
||||
<span class="stat-value mono">{{ shiftAnalysis.crossover_points.length }}</span>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span class="stat-label">Runs Analyzed</span>
|
||||
<span class="stat-value mono">{{ shiftAnalysis.runs_analyzed }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue