Compare commits
5 Commits
feat/issue
...
v0.02
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc4337be88 | ||
|
|
addfd6d24d | ||
|
|
b5d070e116 | ||
|
|
233eefaf12 | ||
|
|
51b0238b09 |
BIN
docs/phase-1/screenshots/command-center-hero-between.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
docs/phase-1/screenshots/live-event-tyre-radio-mocked.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
docs/phase-1/screenshots/race-hub-compare-telemetry-delta.png
Normal file
|
After Width: | Height: | Size: 93 KiB |
BIN
docs/phase-1/screenshots/race-hub-strategy-timeline.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
@@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useMemo, useState } from 'react'
|
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||||
import { useQuery } from '@tanstack/react-query'
|
import { useQuery } from '@tanstack/react-query'
|
||||||
import { fetchLapsComparison, fetchTelemetry } from '../api'
|
import { fetchLapsComparison, fetchTelemetry } from '../api'
|
||||||
import {
|
import {
|
||||||
@@ -57,16 +57,23 @@ export function CompareView({ sessionKey, results, drivers }: Props) {
|
|||||||
[results, drivers],
|
[results, drivers],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const previousSessionKey = useRef(sessionKey)
|
||||||
const [driverA, setDriverA] = useState<number | null>(initialPair?.[0] ?? null)
|
const [driverA, setDriverA] = useState<number | null>(initialPair?.[0] ?? null)
|
||||||
const [driverB, setDriverB] = useState<number | null>(initialPair?.[1] ?? null)
|
const [driverB, setDriverB] = useState<number | null>(initialPair?.[1] ?? null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (previousSessionKey.current !== sessionKey) {
|
||||||
|
previousSessionKey.current = sessionKey
|
||||||
|
setDriverA(initialPair?.[0] ?? null)
|
||||||
|
setDriverB(initialPair?.[1] ?? null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (driverA != null && driverB != null) return
|
if (driverA != null && driverB != null) return
|
||||||
const pair = defaultCompareDriverNumbers(results, drivers)
|
if (!initialPair) return
|
||||||
if (!pair) return
|
setDriverA(initialPair[0])
|
||||||
setDriverA(pair[0])
|
setDriverB(initialPair[1])
|
||||||
setDriverB(pair[1])
|
}, [sessionKey, initialPair, driverA, driverB])
|
||||||
}, [results, drivers, driverA, driverB])
|
|
||||||
|
|
||||||
const pair = useMemo((): [number, number] | null => {
|
const pair = useMemo((): [number, number] | null => {
|
||||||
if (driverA == null || driverB == null || driverA === driverB) return null
|
if (driverA == null || driverB == null || driverA === driverB) return null
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
||||||
import { render, screen, waitFor } from '@testing-library/react'
|
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||||
import { CompareView } from '../components/CompareView'
|
import { CompareView } from '../components/CompareView'
|
||||||
import type { Driver, EnrichedResult, LapsComparisonResponse } from '../types'
|
import type { Driver, EnrichedResult, LapsComparisonResponse } from '../types'
|
||||||
@@ -158,13 +158,89 @@ const comparison: LapsComparisonResponse = {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderCompareView() {
|
const nextSessionResults: EnrichedResult[] = [
|
||||||
|
{
|
||||||
|
driver_number: 16,
|
||||||
|
position: 1,
|
||||||
|
name_acronym: 'LEC',
|
||||||
|
full_name: 'Charles Leclerc',
|
||||||
|
team_name: 'Ferrari',
|
||||||
|
team_colour: 'E8002D',
|
||||||
|
dnf: false,
|
||||||
|
dns: false,
|
||||||
|
dsq: false,
|
||||||
|
duration: null,
|
||||||
|
gap_to_leader: null,
|
||||||
|
number_of_laps: 57,
|
||||||
|
points: 25,
|
||||||
|
session_key: 9550,
|
||||||
|
meeting_key: 1234,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver_number: 55,
|
||||||
|
position: 2,
|
||||||
|
name_acronym: 'SAI',
|
||||||
|
full_name: 'Carlos Sainz',
|
||||||
|
team_name: 'Williams',
|
||||||
|
team_colour: '64C4FF',
|
||||||
|
dnf: false,
|
||||||
|
dns: false,
|
||||||
|
dsq: false,
|
||||||
|
duration: null,
|
||||||
|
gap_to_leader: 3.2,
|
||||||
|
number_of_laps: 57,
|
||||||
|
points: 18,
|
||||||
|
session_key: 9550,
|
||||||
|
meeting_key: 1234,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const nextSessionDrivers: Driver[] = [
|
||||||
|
{
|
||||||
|
driver_number: 16,
|
||||||
|
name_acronym: 'LEC',
|
||||||
|
full_name: 'Charles Leclerc',
|
||||||
|
first_name: 'Charles',
|
||||||
|
last_name: 'Leclerc',
|
||||||
|
team_name: 'Ferrari',
|
||||||
|
team_colour: 'E8002D',
|
||||||
|
headshot_url: '',
|
||||||
|
broadcast_name: 'C LECLERC',
|
||||||
|
session_key: 9550,
|
||||||
|
meeting_key: 1234,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
driver_number: 55,
|
||||||
|
name_acronym: 'SAI',
|
||||||
|
full_name: 'Carlos Sainz',
|
||||||
|
first_name: 'Carlos',
|
||||||
|
last_name: 'Sainz',
|
||||||
|
team_name: 'Williams',
|
||||||
|
team_colour: '64C4FF',
|
||||||
|
headshot_url: '',
|
||||||
|
broadcast_name: 'C SAINZ',
|
||||||
|
session_key: 9550,
|
||||||
|
meeting_key: 1234,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
function renderCompareView(
|
||||||
|
props: {
|
||||||
|
sessionKey?: number
|
||||||
|
results?: EnrichedResult[]
|
||||||
|
drivers?: Driver[]
|
||||||
|
} = {},
|
||||||
|
) {
|
||||||
const client = new QueryClient({
|
const client = new QueryClient({
|
||||||
defaultOptions: { queries: { retry: false } },
|
defaultOptions: { queries: { retry: false } },
|
||||||
})
|
})
|
||||||
return render(
|
return render(
|
||||||
<QueryClientProvider client={client}>
|
<QueryClientProvider client={client}>
|
||||||
<CompareView sessionKey={9472} results={results} drivers={drivers} />
|
<CompareView
|
||||||
|
sessionKey={props.sessionKey ?? 9472}
|
||||||
|
results={props.results ?? results}
|
||||||
|
drivers={props.drivers ?? drivers}
|
||||||
|
/>
|
||||||
</QueryClientProvider>,
|
</QueryClientProvider>,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -305,6 +381,28 @@ describe('CompareView', () => {
|
|||||||
expect(screen.getAllByText('HAM').length).toBeGreaterThan(0)
|
expect(screen.getAllByText('HAM').length).toBeGreaterThan(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('resets the selected pair when the mounted session changes', async () => {
|
||||||
|
const { rerender } = renderCompareView()
|
||||||
|
|
||||||
|
fireEvent.change(screen.getByTestId('compare-picker-a'), { target: { value: '44' } })
|
||||||
|
expect(screen.getByTestId('compare-picker-a')).toHaveValue('44')
|
||||||
|
|
||||||
|
rerender(
|
||||||
|
<QueryClientProvider client={new QueryClient({ defaultOptions: { queries: { retry: false } } })}>
|
||||||
|
<CompareView
|
||||||
|
sessionKey={9550}
|
||||||
|
results={nextSessionResults}
|
||||||
|
drivers={nextSessionDrivers}
|
||||||
|
/>
|
||||||
|
</QueryClientProvider>,
|
||||||
|
)
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByTestId('compare-picker-a')).toHaveValue('16')
|
||||||
|
expect(screen.getByTestId('compare-picker-b')).toHaveValue('55')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
it('renders telemetry and pace sections with mocked queries', async () => {
|
it('renders telemetry and pace sections with mocked queries', async () => {
|
||||||
renderCompareView()
|
renderCompareView()
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 97 KiB |
|
Before Width: | Height: | Size: 169 KiB After Width: | Height: | Size: 129 KiB |