diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d4219ea66..ef0389629 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -261,8 +261,11 @@ jobs: # constructor parameter does not break its hand-wired call sites at # compile time: the argument arrives as undefined and throws at # runtime, if anything reads it at all. This is the step that - # catches it. + # catches it. src and tests together are past 570,000 lines and need + # about 4.3 GB, over Node's default heap. run: cd server && npm run typecheck:tests + env: + NODE_OPTIONS: --max-old-space-size=8192 - name: Typecheck entity generator # tsconfig.scripts.json covers generate-entities.ts and migrate-encryption.ts; diff --git a/client/scripts/eslint-baseline.json b/client/scripts/eslint-baseline.json index ad5eb6d1f..6836a5f7e 100644 --- a/client/scripts/eslint-baseline.json +++ b/client/scripts/eslint-baseline.json @@ -8,7 +8,7 @@ "trek/no-swallowed-catch": 133, "max-params": 35, "trek/store-without-selector": 69, - "react-hooks/refs": 559, + "react-hooks/refs": 558, "react-hooks/set-state-in-effect": 197, "@typescript-eslint/no-floating-promises": 167, "react-hooks/exhaustive-deps": 121, diff --git a/client/src/api/tourSki.ts b/client/src/api/tourSki.ts index c3a485d2e..660a2f083 100644 --- a/client/src/api/tourSki.ts +++ b/client/src/api/tourSki.ts @@ -7,6 +7,5 @@ export const tourSkiApi = { tripId: number | string, placeId: number | string, body: TourSkiClassificationRequest - ): Promise => - apiClient.put(`/trips/${tripId}/tours/${placeId}/ski`, body).then((r) => r.data), + ): Promise => apiClient.put(`/trips/${tripId}/tours/${placeId}/ski`, body).then((r) => r.data), }; diff --git a/client/src/components/Atlas/tourActivity/AtlasTourActivityPane.test.tsx b/client/src/components/Atlas/tourActivity/AtlasTourActivityPane.test.tsx index 09ed42f71..29b8b26ac 100644 --- a/client/src/components/Atlas/tourActivity/AtlasTourActivityPane.test.tsx +++ b/client/src/components/Atlas/tourActivity/AtlasTourActivityPane.test.tsx @@ -5,8 +5,8 @@ import userEvent from '@testing-library/user-event'; import { summarizeTourActivities, type TourActivityStatsEntry, type TourActivityStatsResponse } from '@trek/shared'; import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { render, screen } from '../../../../tests/helpers/render'; import { buildSettings } from '../../../../tests/helpers/factories'; +import { render, screen } from '../../../../tests/helpers/render'; import { resetAllStores, seedStore } from '../../../../tests/helpers/store'; import { useSettingsStore } from '../../../store/settingsStore'; import { AtlasTourActivityPane } from './AtlasTourActivityPane'; diff --git a/client/src/components/Atlas/tourActivity/TourActivityStatsDialog.test.tsx b/client/src/components/Atlas/tourActivity/TourActivityStatsDialog.test.tsx index 91c365a0c..c669d4be9 100644 --- a/client/src/components/Atlas/tourActivity/TourActivityStatsDialog.test.tsx +++ b/client/src/components/Atlas/tourActivity/TourActivityStatsDialog.test.tsx @@ -5,9 +5,9 @@ import userEvent from '@testing-library/user-event'; import { summarizeTourActivities, type TourActivityStatsEntry, type TourActivityStatsResponse } from '@trek/shared'; import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { buildSettings } from '../../../../tests/helpers/factories'; import { render, screen, within } from '../../../../tests/helpers/render'; import { resetAllStores, seedStore } from '../../../../tests/helpers/store'; -import { buildSettings } from '../../../../tests/helpers/factories'; import { useSettingsStore } from '../../../store/settingsStore'; import { TourActivityStatsDialog } from './TourActivityStatsDialog'; import type { TourActivityStats } from './useTourActivityStats'; diff --git a/client/src/components/Tours/ReadStatusNotice.tsx b/client/src/components/Tours/ReadStatusNotice.tsx index 5d26ead77..ba5ef0d45 100644 --- a/client/src/components/Tours/ReadStatusNotice.tsx +++ b/client/src/components/Tours/ReadStatusNotice.tsx @@ -25,7 +25,8 @@ export function ReadStatusNotice({ {messages.loading} ); - if (status === 'offline') return }>{messages.offline}; + if (status === 'offline') + return }>{messages.offline}; if (status !== 'failed') return null; return ( }> diff --git a/client/src/components/Tours/TourDetailDialog.tsx b/client/src/components/Tours/TourDetailDialog.tsx index 4bf4da07d..c05e83490 100644 --- a/client/src/components/Tours/TourDetailDialog.tsx +++ b/client/src/components/Tours/TourDetailDialog.tsx @@ -52,8 +52,8 @@ import { TourGpxExportButton } from './TourGpxExportButton'; import TourActivitySection from './activity/TourActivitySection'; import type { PlanValues } from './activity/planComparison'; import { TourSaveToCollectionButton } from './collection/TourSaveToCollectionButton'; -import { PaddleCheckSection } from './paddle/PaddleCheckSection'; import { TourPackingSection } from './packing/TourPackingSection'; +import { PaddleCheckSection } from './paddle/PaddleCheckSection'; import { PaddleWindSection } from './paddle/PaddleWindCard'; import { TourProvenanceBlock } from './provenance/TourProvenanceSection'; import { RunHeadPills } from './run/RunHeadPills'; diff --git a/client/src/components/Tours/activity/TourActivityDialog.tsx b/client/src/components/Tours/activity/TourActivityDialog.tsx index 75f1fbcb3..c8e8a4edc 100644 --- a/client/src/components/Tours/activity/TourActivityDialog.tsx +++ b/client/src/components/Tours/activity/TourActivityDialog.tsx @@ -236,9 +236,7 @@ export default function TourActivityDialog({ variant="primary" data-testid="tour-activity-confirm" disabled={!assignment.ready || state.busy || importing} - icon={ - state.busy ? : - } + icon={state.busy ? : } onClick={confirm} > {t('tours.activity.confirm')} diff --git a/client/src/components/Tours/activity/TourActivitySection.test.tsx b/client/src/components/Tours/activity/TourActivitySection.test.tsx index bab399245..293a9ef5b 100644 --- a/client/src/components/Tours/activity/TourActivitySection.test.tsx +++ b/client/src/components/Tours/activity/TourActivitySection.test.tsx @@ -120,7 +120,17 @@ describe('TourActivitySection (ACT-01)', () => { expect(current.askRemove).toHaveBeenCalledWith(current.activities?.[0]); hook.state = state({ assigning: {}, removing: activity() }); - rerender(); + rerender( + + ); expect(screen.getByTestId('tour-activity-dialog')).toBeInTheDocument(); expect(screen.getByText('tours.activity.removeTitle')).toBeInTheDocument(); }); @@ -193,6 +203,9 @@ describe('TourActivitySection (ACT-01)', () => { expect(screen.queryByRole('button', { name: /tours.activity.compare.(show|hide)/ })).toBeNull(); act(() => useTourActivityCompareStore.getState().setMapAvailable(true)); - expect(screen.getByRole('button', { name: /tours.activity.compare.show/ })).toHaveAttribute('aria-pressed', 'false'); + expect(screen.getByRole('button', { name: /tours.activity.compare.show/ })).toHaveAttribute( + 'aria-pressed', + 'false' + ); }); }); diff --git a/client/src/components/Tours/activity/useActivityCompareMap.test.ts b/client/src/components/Tours/activity/useActivityCompareMap.test.ts index 7521dbd45..0628cd620 100644 --- a/client/src/components/Tours/activity/useActivityCompareMap.test.ts +++ b/client/src/components/Tours/activity/useActivityCompareMap.test.ts @@ -117,7 +117,9 @@ describe('useActivityCompareMap (ACT-02)', () => { }); it('FE-ACT-COMPARE-MAP-006: tells the store whether it can compare, and ends a comparison where it no longer can or is gone', () => { - const { rerender, unmount } = renderHook((props: typeof input) => useActivityCompareMap(props), { initialProps: input }); + const { rerender, unmount } = renderHook((props: typeof input) => useActivityCompareMap(props), { + initialProps: input, + }); expect(useTourActivityCompareStore.getState().mapAvailable).toBe(true); act(() => useTourActivityCompareStore.getState().show({ tourPlaceId: 7, trackPlaceId: 20 })); diff --git a/client/src/components/Tours/bike/routeWays.test.ts b/client/src/components/Tours/bike/routeWays.test.ts index 9b3436ff9..dfd86d007 100644 --- a/client/src/components/Tours/bike/routeWays.test.ts +++ b/client/src/components/Tours/bike/routeWays.test.ts @@ -183,7 +183,12 @@ describe('the paints and the highlight (BIK-01 to BIK-05)', () => { it('FE-TOUR-WAYS-014: lines of different paints each take their own, an unknown key the accent (MAP-03)', () => { const drawn = withRouteHighlight( - { id: 'sac', lines: [LINE.slice(0, 2), LINE.slice(1, 3), LINE.slice(2)], paint: 'gravel', paints: ['way', 'nope'] }, + { + id: 'sac', + lines: [LINE.slice(0, 2), LINE.slice(1, 3), LINE.slice(2)], + paint: 'gravel', + paints: ['way', 'nope'], + }, [LINE], null, null, diff --git a/client/src/components/Tours/bike/useRouteWays.test.tsx b/client/src/components/Tours/bike/useRouteWays.test.tsx index 12caacb8b..7e38f4f2c 100644 --- a/client/src/components/Tours/bike/useRouteWays.test.tsx +++ b/client/src/components/Tours/bike/useRouteWays.test.tsx @@ -1,5 +1,5 @@ -import { TOUR_TRAIL_GRADE_MAX_WAYS } from '@trek/shared'; import { act, renderHook } from '@testing-library/react'; +import { TOUR_TRAIL_GRADE_MAX_WAYS } from '@trek/shared'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { encodePolyline } from '../../../../tests/helpers/polyline'; import { OnlineOnlyError } from '../../../repo/onlineOnly'; diff --git a/client/src/components/Tours/gpxImportChoices.test.ts b/client/src/components/Tours/gpxImportChoices.test.ts index cad77195c..012750760 100644 --- a/client/src/components/Tours/gpxImportChoices.test.ts +++ b/client/src/components/Tours/gpxImportChoices.test.ts @@ -34,9 +34,11 @@ describe('GPX import choices', () => { tour_type: 'ski', ski_discipline: 'touring', }); - expect( - importFields({ ...base, type: 'ski', ski: { discipline: 'cross_country', technique: 'unknown' } }) - ).toEqual({ tour_type: 'ski', ski_discipline: 'cross_country', ski_technique: 'unknown' }); + expect(importFields({ ...base, type: 'ski', ski: { discipline: 'cross_country', technique: 'unknown' } })).toEqual({ + tour_type: 'ski', + ski_discipline: 'cross_country', + ski_technique: 'unknown', + }); }); it('FE-TOUR-GPX-CHOICES-002: holds the import back while a paddle tour or a ski track lacks what it must name', () => { diff --git a/client/src/components/Tours/hike/useHikeWays.test.tsx b/client/src/components/Tours/hike/useHikeWays.test.tsx index 9ceaecaed..2b9b7e7b6 100644 --- a/client/src/components/Tours/hike/useHikeWays.test.tsx +++ b/client/src/components/Tours/hike/useHikeWays.test.tsx @@ -1,5 +1,5 @@ -import type { TourTrailGrade } from '@trek/shared'; import { act, renderHook } from '@testing-library/react'; +import type { TourTrailGrade } from '@trek/shared'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { useTourRouteHighlightStore } from '../../../store/tourRouteHighlightStore'; import type { RouteWayEdge, RouteWays } from '../bike/routeWays'; diff --git a/client/src/components/Tours/hike/wayTagFacets.ts b/client/src/components/Tours/hike/wayTagFacets.ts index 5fcfd917e..83aac0280 100644 --- a/client/src/components/Tours/hike/wayTagFacets.ts +++ b/client/src/components/Tours/hike/wayTagFacets.ts @@ -13,16 +13,7 @@ import type { HikePaintKey } from './hikePaint'; */ type HikeSurfaceClass = - | 'paved' - | 'sett' - | 'compacted' - | 'gravel' - | 'ground' - | 'grass' - | 'rock' - | 'wood' - | 'unpaved' - | 'other'; + 'paved' | 'sett' | 'compacted' | 'gravel' | 'ground' | 'grass' | 'rock' | 'wood' | 'unpaved' | 'other'; type HikeWayClass = 'path' | 'footway' | 'steps' | 'track' | 'cycleway' | 'quietRoad' | 'road' | 'viaFerrata' | 'other'; diff --git a/client/src/components/Tours/horse/HorseLegRow.test.tsx b/client/src/components/Tours/horse/HorseLegRow.test.tsx index cee5e88c5..2666ae0f8 100644 --- a/client/src/components/Tours/horse/HorseLegRow.test.tsx +++ b/client/src/components/Tours/horse/HorseLegRow.test.tsx @@ -1,16 +1,16 @@ import { renderHook } from '@testing-library/react'; import { describe, expect, it, vi } from 'vitest'; import { render, screen, within } from '../../../../tests/helpers/render'; -import { TourDayRowIcon } from '../TourDayRowFacts'; -import { tourDayRowIcon } from '../tourDayRowIcon'; -import { movingTimeLabel } from '../tourFacts'; import type { TourPlannerWaypoint } from '../planner/tourPlannerWaypoints'; import { useShapingClick } from '../planner/useShapingClick'; import type { TourPlannerController } from '../planner/useTourPlanner'; import { WaypointLegRows } from '../planner/WaypointLegRows'; +import { TourDayRowIcon } from '../TourDayRowFacts'; +import { tourDayRowIcon } from '../tourDayRowIcon'; +import { movingTimeLabel } from '../tourFacts'; import { HorseLegRow } from './HorseLegRow'; -import { Horseshoe } from './HorseshoeIcon'; import type { HorseSectionLeg } from './horseSection'; +import { Horseshoe } from './HorseshoeIcon'; // FE-HORSE-LEG-001 to FE-HORSE-LEG-005 diff --git a/client/src/components/Tours/horse/HorseLegRow.tsx b/client/src/components/Tours/horse/HorseLegRow.tsx index c96a4166a..8d040c26f 100644 --- a/client/src/components/Tours/horse/HorseLegRow.tsx +++ b/client/src/components/Tours/horse/HorseLegRow.tsx @@ -6,8 +6,8 @@ import { fs } from '../../shared/DialogShell'; import { Tooltip } from '../../shared/Tooltip'; import { lineLengthM } from '../planner/tourFixedLegs'; import { ACCESS_TONE_DOT, accessText, accessToneOf } from './horseAccess'; -import { Horseshoe } from './HorseshoeIcon'; import type { HorseSectionLeg } from './horseSection'; +import { Horseshoe } from './HorseshoeIcon'; /** * HOR-01: a section of a horse route the ride follows, as a badge on its leg diff --git a/client/src/components/Tours/horse/horseModel.test.ts b/client/src/components/Tours/horse/horseModel.test.ts index 1474ef13d..d3a4a7ecc 100644 --- a/client/src/components/Tours/horse/horseModel.test.ts +++ b/client/src/components/Tours/horse/horseModel.test.ts @@ -132,9 +132,24 @@ describe('horse route sections on a ride (HOR-01)', () => { expect(accessToneOf(undefined)).toBeNull(); expect(accessToneOf([])).toBeNull(); expect(accessToneOf([{ value: 'yes', length_m: 10 }])).toBe('open'); - expect(accessToneOf([{ value: 'yes', length_m: 10 }, { value: 'unknown', length_m: 1 }])).toBe('unknown'); - expect(accessToneOf([{ value: 'unknown', length_m: 10 }, { value: 'destination', length_m: 1 }])).toBe('limited'); - expect(accessToneOf([{ value: 'designated', length_m: 10 }, { value: 'private', length_m: 1 }])).toBe('closed'); + expect( + accessToneOf([ + { value: 'yes', length_m: 10 }, + { value: 'unknown', length_m: 1 }, + ]) + ).toBe('unknown'); + expect( + accessToneOf([ + { value: 'unknown', length_m: 10 }, + { value: 'destination', length_m: 1 }, + ]) + ).toBe('limited'); + expect( + accessToneOf([ + { value: 'designated', length_m: 10 }, + { value: 'private', length_m: 1 }, + ]) + ).toBe('closed'); }); it('FE-HORSE-MODEL-009: spells the tags out with the metres each covers', () => { diff --git a/client/src/components/Tours/horse/horseRouting.test.ts b/client/src/components/Tours/horse/horseRouting.test.ts index 86568db7a..eb7b2e349 100644 --- a/client/src/components/Tours/horse/horseRouting.test.ts +++ b/client/src/components/Tours/horse/horseRouting.test.ts @@ -1,9 +1,9 @@ import type { TourFixedLeg } from '@trek/shared'; import { describe, expect, it } from 'vitest'; -import { tourMapLayersFor } from '../tourMapLayers'; import { normalizePlannerWaypoints, tourWaypointKey, type TourPlannerWaypoint } from '../planner/tourPlannerWaypoints'; import { toggleFreeLeg } from '../planner/tourRouteActions'; import { rideTour, routeWalkingTour } from '../planner/tourRouting'; +import { tourMapLayersFor } from '../tourMapLayers'; // FE-HORSE-ROUTE-001 to FE-HORSE-ROUTE-006 diff --git a/client/src/components/Tours/packing/tourPacking.test.tsx b/client/src/components/Tours/packing/tourPacking.test.tsx index d5cf95455..e213a596a 100644 --- a/client/src/components/Tours/packing/tourPacking.test.tsx +++ b/client/src/components/Tours/packing/tourPacking.test.tsx @@ -22,7 +22,16 @@ const GEAR: TourPackingLink = { category: 'Hiking gear', linked_at: '2026-10-20 let nextId = 1; function item(name: string, category: string | null, over: Partial = {}): PackingItem { - return { id: nextId++, trip_id: 5, name, category, checked: 0, sort_order: nextId, quantity: 1, ...over } as PackingItem; + return { + id: nextId++, + trip_id: 5, + name, + category, + checked: 0, + sort_order: nextId, + quantity: 1, + ...over, + } as PackingItem; } const ITEMS = [ diff --git a/client/src/components/Tours/planner/RoundHikeCard.tsx b/client/src/components/Tours/planner/RoundHikeCard.tsx index 98674364d..8872feb96 100644 --- a/client/src/components/Tours/planner/RoundHikeCard.tsx +++ b/client/src/components/Tours/planner/RoundHikeCard.tsx @@ -6,8 +6,8 @@ import type { DistanceUnit } from '../../../types'; import { formatDistance, getDistanceUnitLabel } from '../../../utils/units'; import { SoftPill } from '../../Planner/planParts'; import ConfirmDialog from '../../shared/ConfirmDialog'; -import { fs } from '../../shared/DialogShell'; import { INPUT, LABEL, PillSelect } from '../../shared/dialogParts'; +import { fs } from '../../shared/DialogShell'; import { Tooltip } from '../../shared/Tooltip'; import { TourNotice } from '../tourParts'; import { MapCard, MapCardActions, MapCornerOverlay, StopDisc, VariantFigures, WayChoice } from './mapCardParts'; diff --git a/client/src/components/Tours/planner/TourEditorFields.tsx b/client/src/components/Tours/planner/TourEditorFields.tsx index 36d2f53fb..97b056978 100644 --- a/client/src/components/Tours/planner/TourEditorFields.tsx +++ b/client/src/components/Tours/planner/TourEditorFields.tsx @@ -7,9 +7,9 @@ import { INPUT, LABEL } from '../../shared/dialogParts'; import { fs } from '../../shared/DialogShell'; import { FoldButton, InfoDot, TourNotice, TourSection } from '../tourParts'; import { HikingPreferencesField } from './HikingPreferencesField'; -import { WinterActivityField } from './WinterActivityField'; import { TOUR_DURATION_INPUT_MAX_LENGTH, formatTourDuration, parseTourDuration } from './tourDurationInput'; import type { TourPlannerController } from './useTourPlanner'; +import { WinterActivityField } from './WinterActivityField'; type Difficulty = 1 | 2 | 3 | 4 | 5 | 6; diff --git a/client/src/components/Tours/planner/WaypointLegRows.tsx b/client/src/components/Tours/planner/WaypointLegRows.tsx index 6b08a4616..e1cc0377c 100644 --- a/client/src/components/Tours/planner/WaypointLegRows.tsx +++ b/client/src/components/Tours/planner/WaypointLegRows.tsx @@ -5,9 +5,9 @@ import { useSettingsStore } from '../../../store/settingsStore'; import type { TourFerrataCrossing } from '../../../store/tourFerrataCrossingStore'; import { formatDistance } from '../../../utils/units'; import { FerrataGlyph } from '../../Ferratas/FerrataGlyph'; -import { HorseLegRow } from '../horse/HorseLegRow'; import { fs } from '../../shared/DialogShell'; import { Tooltip } from '../../shared/Tooltip'; +import { HorseLegRow } from '../horse/HorseLegRow'; import { PaddleLegFailureRow, PaddleLegNotes } from '../paddle/PaddleLegParts'; import { isRegionLoadPending, regionLoadFailure } from '../paddle/paddleRegionLoad'; import { PaddleRegionLoadRow } from '../paddle/PaddleRegionLoadRow'; diff --git a/client/src/components/Tours/planner/roundHikeGeometry.ts b/client/src/components/Tours/planner/roundHikeGeometry.ts index 88da72017..ec9bbe8b0 100644 --- a/client/src/components/Tours/planner/roundHikeGeometry.ts +++ b/client/src/components/Tours/planner/roundHikeGeometry.ts @@ -102,9 +102,9 @@ function hasNeighbour(grid: Map, sample: Sample, counts: (othe const cy = cellOf(sample.y); for (let dx = -1; dx <= 1; dx += 1) { for (let dy = -1; dy <= 1; dy += 1) { - const near = grid.get(`${cx + dx}:${cy + dy}`)?.some( - (other) => Math.hypot(other.x - sample.x, other.y - sample.y) <= SAME_GROUND_M && counts(other) - ); + const near = grid + .get(`${cx + dx}:${cy + dy}`) + ?.some((other) => Math.hypot(other.x - sample.x, other.y - sample.y) <= SAME_GROUND_M && counts(other)); if (near) return true; } } diff --git a/client/src/components/Tours/planner/roundHikeRouting.test.ts b/client/src/components/Tours/planner/roundHikeRouting.test.ts index 4289629be..ccbddfa4f 100644 --- a/client/src/components/Tours/planner/roundHikeRouting.test.ts +++ b/client/src/components/Tours/planner/roundHikeRouting.test.ts @@ -10,9 +10,9 @@ const { valhallaRun, enrichTourElevations } = vi.hoisted(() => ({ vi.mock('../../Map/valhallaRoute', () => ({ valhallaRun })); vi.mock('./tourRouting', () => ({ enrichTourElevations })); -import { fitsWish, type RoundRequest } from './roundHikes'; import { spotToward } from './roundHikeGeometry'; import { findRoundHikes, MAX_ROUND_ASKS, type RoundSearchReport } from './roundHikeRouting'; +import { fitsWish, type RoundRequest } from './roundHikes'; type Spot = { lat: number; lng: number }; diff --git a/client/src/components/Tours/planner/roundHikeRouting.ts b/client/src/components/Tours/planner/roundHikeRouting.ts index f552f672d..4cf407c29 100644 --- a/client/src/components/Tours/planner/roundHikeRouting.ts +++ b/client/src/components/Tours/planner/roundHikeRouting.ts @@ -3,8 +3,8 @@ import { valhallaRun } from '../../Map/valhallaRoute'; import { figuresOf } from './legVariants'; import { loopSpots, retracedShare, sharedShare, STRAIGHT_PER_RADIUS_M } from './roundHikeGeometry'; import { fitsWish, ROUND_KEYS, type RoundCandidate, type RoundRequest } from './roundHikes'; -import { enrichTourElevations } from './tourRouting'; import { MAX_TOUR_SNAP_M } from './tourRouteOutcome'; +import { enrichTourElevations } from './tourRouting'; type Spot = { lat: number; lng: number }; diff --git a/client/src/components/Tours/planner/roundHikes.ts b/client/src/components/Tours/planner/roundHikes.ts index ed38d9d0e..96e6526e4 100644 --- a/client/src/components/Tours/planner/roundHikes.ts +++ b/client/src/components/Tours/planner/roundHikes.ts @@ -4,8 +4,8 @@ import { convertDistance } from '../../../utils/units'; import type { CostingOptions } from '../../Map/valhallaRoute'; import { OTHER_WAY_KEYS, type LegVariant } from './legVariants'; import { spotToward } from './roundHikeGeometry'; -import { closeLoop } from './tourRouteActions'; import type { TourPlannerWaypoint } from './tourPlannerWaypoints'; +import { closeLoop } from './tourRouteActions'; /** * RTE-03: round hikes of about a wished length out of a start point, as a @@ -139,9 +139,13 @@ export function roundPlanOf( newId: () => string ): TourPlannerWaypoint[] { const { fixedLeg: _leg, lock: _lock, carryNext: _carry, auto: _auto, shaping: _shaping, ...own } = start; - const steering = via.map( - ({ lat, lng }): TourPlannerWaypoint => ({ id: newId(), lat, lng, role: 'via', shaping: true }) - ); + const steering = via.map(({ lat, lng }): TourPlannerWaypoint => ({ + id: newId(), + lat, + lng, + role: 'via', + shaping: true, + })); return closeLoop([{ ...own, role: 'start' }, ...steering], newId()); } diff --git a/client/src/components/Tours/planner/routeLegAt.ts b/client/src/components/Tours/planner/routeLegAt.ts index ea294e998..09cb54cc3 100644 --- a/client/src/components/Tours/planner/routeLegAt.ts +++ b/client/src/components/Tours/planner/routeLegAt.ts @@ -25,7 +25,8 @@ function alongLine( const t = length === 0 ? 0 : Math.max(0, Math.min(1, ((lng - aLng) * cos * dx + (lat - aLat) * dy) / (length * length))); const distance = Math.hypot(aLng * cos + dx * t - lng * cos, aLat + dy * t - lat); - if (distance < best.distance) best = { at: travelled + length * t, index: i, vertex: t < 0.5 ? i : i + 1, distance }; + if (distance < best.distance) + best = { at: travelled + length * t, index: i, vertex: t < 0.5 ? i : i + 1, distance }; } travelled += length; } diff --git a/client/src/components/Tours/planner/useTourPlanner.winter.test.tsx b/client/src/components/Tours/planner/useTourPlanner.winter.test.tsx index 12c9794c0..22d5bb64f 100644 --- a/client/src/components/Tours/planner/useTourPlanner.winter.test.tsx +++ b/client/src/components/Tours/planner/useTourPlanner.winter.test.tsx @@ -87,10 +87,7 @@ describe('useTourPlanner, the winter label of a hike (HIK-01)', () => { await act(async () => { await result.current.save(); }); - expect(createTour).toHaveBeenCalledWith( - 61, - expect.objectContaining({ tour_type: 'hike', winter_activity: null }) - ); + expect(createTour).toHaveBeenCalledWith(61, expect.objectContaining({ tour_type: 'hike', winter_activity: null })); }); it('FE-TOUR-WINTER-002: the label plans nothing again, is no step of the history and is kept in the draft', async () => { @@ -179,10 +176,7 @@ describe('useTourPlanner, the winter label of a hike (HIK-01)', () => { await act(async () => { await result.current.save(); }); - expect(createTour).toHaveBeenCalledWith( - 65, - expect.objectContaining({ tour_type: 'walk', winter_activity: null }) - ); + expect(createTour).toHaveBeenCalledWith(65, expect.objectContaining({ tour_type: 'walk', winter_activity: null })); }); it('FE-TOUR-WINTER-006: keeps the label the switch brings back with the tour, winter hiking for the next one', async () => { diff --git a/client/src/components/Tours/run/RunFields.tsx b/client/src/components/Tours/run/RunFields.tsx index 2f725acf4..5d7c938d3 100644 --- a/client/src/components/Tours/run/RunFields.tsx +++ b/client/src/components/Tours/run/RunFields.tsx @@ -1,9 +1,4 @@ -import { - MAX_RUN_PACE_SECONDS_PER_KM, - MIN_RUN_PACE_SECONDS_PER_KM, - RUN_PROFILES, - type RunProfile, -} from '@trek/shared'; +import { MAX_RUN_PACE_SECONDS_PER_KM, MIN_RUN_PACE_SECONDS_PER_KM, RUN_PROFILES, type RunProfile } from '@trek/shared'; import { Clock, Gauge, Info, Ruler } from 'lucide-react'; import { useState } from 'react'; import { useTranslation } from '../../../i18n'; diff --git a/client/src/components/Tours/ski/skiChoice.ts b/client/src/components/Tours/ski/skiChoice.ts index a2fb6db2f..f04d8820d 100644 --- a/client/src/components/Tours/ski/skiChoice.ts +++ b/client/src/components/Tours/ski/skiChoice.ts @@ -20,7 +20,7 @@ export function skiChoiceMissing(choice: SkiChoice): 'discipline' | 'technique' /** The fields a complete choice is sent as; null while something is missing. */ export function skiFieldsOf( - choice: SkiChoice, + choice: SkiChoice ): Pick | null { if (choice.discipline === null || skiChoiceMissing(choice)) return null; return choice.discipline === 'cross_country' diff --git a/client/src/components/Tours/ski/useSkiClassification.ts b/client/src/components/Tours/ski/useSkiClassification.ts index eccbbd949..32ce12108 100644 --- a/client/src/components/Tours/ski/useSkiClassification.ts +++ b/client/src/components/Tours/ski/useSkiClassification.ts @@ -29,8 +29,7 @@ export function useSkiClassification({ tripId, planner, tours, canEdit, onSaved const [draft, setDraft] = useState(null); const [saving, setSaving] = useState(false); const viewed = planner.mode.type === 'view-gpx' ? planner.mode.tour : null; - const tour = - viewed?.tour_type === 'ski' ? (tours.find((item) => item.place_id === viewed.place_id) ?? viewed) : null; + const tour = viewed?.tour_type === 'ski' ? (tours.find((item) => item.place_id === viewed.place_id) ?? viewed) : null; const saved = useMemo(() => (tour ? skiChoiceOf(tour) : NO_SKI_CHOICE), [tour]); const open = useCallback(() => { diff --git a/client/src/components/Tours/stages/StageDayPicker.tsx b/client/src/components/Tours/stages/StageDayPicker.tsx index 773a01def..51df26a55 100644 --- a/client/src/components/Tours/stages/StageDayPicker.tsx +++ b/client/src/components/Tours/stages/StageDayPicker.tsx @@ -18,7 +18,11 @@ interface StageDayPickerProps { } /** The days a stage can go on, the one it is on checked, and a way back to none. */ -function dayItems({ stageKey, days, stageDays }: StageDayPickerProps, label: (day: Day, index: number) => string, noDay: string) { +function dayItems( + { stageKey, days, stageDays }: StageDayPickerProps, + label: (day: Day, index: number) => string, + noDay: string +) { const current = stageDays.dayOf(stageKey); const items: MenuItems = days.map((day, index) => ({ label: label(day, index), @@ -27,7 +31,11 @@ function dayItems({ stageKey, days, stageDays }: StageDayPickerProps, label: (da onClick: () => void stageDays.setDay(stageKey, day.id), })); if (current === null) return items; - return [...items, { divider: true }, { label: noDay, icon: CalendarX2, onClick: () => void stageDays.setDay(stageKey, null) }]; + return [ + ...items, + { divider: true }, + { label: noDay, icon: CalendarX2, onClick: () => void stageDays.setDay(stageKey, null) }, + ]; } /** @@ -55,7 +63,11 @@ export function StageDayPicker(props: StageDayPickerProps) { menu.close(); return; } - menu.open(event, dayItems(props, (option, at) => dayMenuLabel(option, at, t, locale), t('tours.stages.noDay')), true); + menu.open( + event, + dayItems(props, (option, at) => dayMenuLabel(option, at, t, locale), t('tours.stages.noDay')), + true + ); }; const look = day @@ -86,7 +98,9 @@ export function StageDayPicker(props: StageDayPickerProps) { {day ? t('dayplan.dayN', { n: index + 1 }) : t('tours.stages.noDay')} - {interactive &&