diff --git a/client/src/api/skiRoute.ts b/client/src/api/skiRoute.ts index 79b7ac770..d262f165d 100644 --- a/client/src/api/skiRoute.ts +++ b/client/src/api/skiRoute.ts @@ -4,7 +4,5 @@ import apiClient from './client'; /** The piste router: a ski tour's legs planned on the piste data the server keeps, held to the contract. */ export const skiRouteApi = { plan: (tripId: number | string, request: SkiRouteInput, signal?: AbortSignal): Promise => - apiClient - .post(`/trips/${tripId}/ski/route`, request, { signal }) - .then((r) => skiRouteResponseSchema.parse(r.data)), + apiClient.post(`/trips/${tripId}/ski/route`, request, { signal }).then((r) => skiRouteResponseSchema.parse(r.data)), }; diff --git a/client/src/components/Planner/PlaceFormModal.test.tsx b/client/src/components/Planner/PlaceFormModal.test.tsx index 47bfb6925..c7a7c73a6 100644 --- a/client/src/components/Planner/PlaceFormModal.test.tsx +++ b/client/src/components/Planner/PlaceFormModal.test.tsx @@ -11,7 +11,7 @@ import { usePermissionsStore } from '../../store/permissionsStore'; import { usePluginStore } from '../../store/pluginStore'; import { resetAllStores, seedStore } from '../../../tests/helpers/store'; import { buildUser, buildTrip, buildPlace, buildCategory, buildAssignment } from '../../../tests/helpers/factories'; -import { placeFormProps, seedPlaceFormStores } from '../../../tests/helpers/placeForm'; +import { placeFormProps, seedPlaceFormStores } from '../../../tests/helpers/placeFormSetup'; import PlaceFormModal from './PlaceFormModal'; // CustomTimePicker as a plain text input, see TimePickerStub. diff --git a/client/src/components/Planner/PlaceFormModal.tour.test.tsx b/client/src/components/Planner/PlaceFormModal.tour.test.tsx index 3b1fa0cd6..32a6a0c8b 100644 --- a/client/src/components/Planner/PlaceFormModal.tour.test.tsx +++ b/client/src/components/Planner/PlaceFormModal.tour.test.tsx @@ -2,7 +2,7 @@ import type { TourListItem } from '@trek/shared'; import { buildAssignment, buildPlace } from '../../../tests/helpers/factories'; -import { placeFormProps, seedPlaceFormStores } from '../../../tests/helpers/placeForm'; +import { placeFormProps, seedPlaceFormStores } from '../../../tests/helpers/placeFormSetup'; import { render, screen } from '../../../tests/helpers/render'; import { resetAllStores } from '../../../tests/helpers/store'; import PlaceFormModal from './PlaceFormModal'; diff --git a/client/src/components/Tours/planner/skiRouting.ts b/client/src/components/Tours/planner/skiRouting.ts index 00b0187e1..cceb04daa 100644 --- a/client/src/components/Tours/planner/skiRouting.ts +++ b/client/src/components/Tours/planner/skiRouting.ts @@ -2,8 +2,8 @@ import type { SkiColourScheme, SkiFailCode, SkiFailHint, SkiRouteLeg, SkiRoutePo import { skiRouteRepo, type SkiLegAnswer, type SkiPlanAnswer } from '../../../repo/skiRouteRepo'; import type { SkiChoice } from '../ski/skiChoice'; import { densifyLine, lineLengthM } from './tourFixedLegs'; -import { isTourRoute } from './tourRouteOutcome'; import { freeLegBetween } from './tourRouteActions'; +import { isTourRoute } from './tourRouteOutcome'; import { drawnTour, routeWalkingTour, type TourRoutePart, type TourRouteResult } from './tourRouting'; /** diff --git a/client/src/components/Tours/ski/SkiRouteOptions.tsx b/client/src/components/Tours/ski/SkiRouteOptions.tsx index 44970aa9c..44083aff1 100644 --- a/client/src/components/Tours/ski/SkiRouteOptions.tsx +++ b/client/src/components/Tours/ski/SkiRouteOptions.tsx @@ -6,11 +6,11 @@ import { SKI_ROUTE_PRIORITIES, skiOptionsReadBy, skiUsesLifts, + type SkiRouteOptions as Options, type SkiDifficulty, type SkiDiscipline, type SkiLiftClass, type SkiPace, - type SkiRouteOptions as Options, type SkiRouteOptionsInput, type SkiRoutePriority, } from '@trek/shared'; diff --git a/client/src/components/Tours/tourParts.tsx b/client/src/components/Tours/tourParts.tsx index c181d137b..3b831a9cc 100644 --- a/client/src/components/Tours/tourParts.tsx +++ b/client/src/components/Tours/tourParts.tsx @@ -140,48 +140,6 @@ export function TourActivityBadge({ tour }: { tour: Pick dayMenuLabel(day, index, t, locale) - const shown = tourDays.length > limit ? tourDays.slice(0, limit - 1) : tourDays - const folded = tourDays.slice(shown.length) - const foldedLabel = folded.map(fullLabel).join(', ') - return ( - <> - {shown.map((tourDay) => ( - - - }> - {t('dayplan.dayN', { n: tourDay.index + 1 })} - - - ))} - {folded.length > 0 && ( - - - +{folded.length} - - - - )} - - ) -} - /** * The days a tour is on, as the detail shows them: one box per day in the look * of the measures below, so the days and the numbers read as one block. The diff --git a/client/src/pages/tripPlanner/placeFormContext.ts b/client/src/pages/tripPlanner/placeFormContext.ts new file mode 100644 index 000000000..6a95c3474 --- /dev/null +++ b/client/src/pages/tripPlanner/placeFormContext.ts @@ -0,0 +1,18 @@ +import type { TourListItem } from '@trek/shared'; +import type { Assignment } from '../../types'; + +/** + * The place form's day context: while a place is edited, the whole day plan to check its times + * against and, TIME-02, the tour that place is, whose end the time fields work out from its start. + */ +export function placeFormContext( + editingPlace: { id: number } | null, + assignments: Record, + tours: readonly TourListItem[] +): { dayAssignments: Assignment[]; tour: TourListItem | null } { + if (!editingPlace) return { dayAssignments: [], tour: null }; + return { + dayAssignments: Object.values(assignments).flat(), + tour: tours.find((item) => item.place_id === editingPlace.id) ?? null, + }; +} diff --git a/client/src/pages/tripPlanner/useTripPlannerPage.ts b/client/src/pages/tripPlanner/useTripPlannerPage.ts index f85dc6268..91bb9c489 100644 --- a/client/src/pages/tripPlanner/useTripPlannerPage.ts +++ b/client/src/pages/tripPlanner/useTripPlannerPage.ts @@ -1,6 +1,4 @@ import { useCallback, useEffect, useMemo, useRef } from 'react' -import type { TourListItem } from '@trek/shared' -import type { Assignment } from '../../types' import { usePoiExplore, type Bbox } from '../../components/Map/usePoiExplore' import { placeActions } from '../../components/Planner/usePlaceActions' import { tourRouteStyle } from '../../components/Tours/planner/tourRouteStyle' @@ -17,22 +15,7 @@ import { usePlannerFocusPoints } from './usePlannerFocusPoints' import { useTripPlanner } from './useTripPlanner' import { useTourWorkspace } from './useTourWorkspace' import { mapFocusKeyOf, offeredWaysOf, paddleLineOf } from './tourMapFocus' - -/** - * The place form's day context: while a place is edited, the whole day plan to check its times - * against and, TIME-02, the tour that place is, whose end the time fields work out from its start. - */ -function placeFormContext( - editingPlace: { id: number } | null, - assignments: Record, - tours: readonly TourListItem[], -): { dayAssignments: Assignment[]; tour: TourListItem | null } { - if (!editingPlace) return { dayAssignments: [], tour: null } - return { - dayAssignments: Object.values(assignments).flat(), - tour: tours.find(item => item.place_id === editingPlace.id) ?? null, - } -} +import { placeFormContext } from './placeFormContext' export function useTripPlannerPage() { const planner = useTripPlanner() diff --git a/client/src/repo/skiRouteRepo.ts b/client/src/repo/skiRouteRepo.ts index 33f7c240e..be1db3937 100644 --- a/client/src/repo/skiRouteRepo.ts +++ b/client/src/repo/skiRouteRepo.ts @@ -3,8 +3,8 @@ import { type SkiColourScheme, type SkiDiscipline, type SkiRouteLeg, - type SkiRoutePoint, type SkiRouteOptionsInput, + type SkiRoutePoint, type SkiRouteResponse, type SkiTechnique, } from '@trek/shared'; diff --git a/client/tests/helpers/placeForm.tsx b/client/tests/helpers/placeForm.tsx index d7b99e0b3..5816204a8 100644 --- a/client/tests/helpers/placeForm.tsx +++ b/client/tests/helpers/placeForm.tsx @@ -1,10 +1,3 @@ -import { vi } from 'vitest'; - -import { useAuthStore } from '../../src/store/authStore'; -import { useTripStore } from '../../src/store/tripStore'; -import { buildTrip, buildUser } from './factories'; -import { seedStore } from './store'; - /** * Stands in for CustomTimePicker in the place form's tests: a plain text input * instead of the portal-heavy picker. The aria props land on the input, as the @@ -34,23 +27,3 @@ export function TimePickerStub({ /> ); } - -/** The props an open place form gets when a test sets none: a new place in trip 1. */ -export const placeFormProps = { - isOpen: true, - onClose: vi.fn(), - onSave: vi.fn(), - place: null, - prefillCoords: null, - tripId: 1, - categories: [], - onCategoryCreated: vi.fn(), - assignmentId: null, - dayAssignments: [], -}; - -/** A signed-in user without a maps key, in trip 1: what the form reads before it renders. */ -export function seedPlaceFormStores() { - seedStore(useAuthStore, { user: buildUser(), isAuthenticated: true, hasMapsKey: false }); - seedStore(useTripStore, { trip: buildTrip({ id: 1 }) }); -} diff --git a/client/tests/helpers/placeFormSetup.ts b/client/tests/helpers/placeFormSetup.ts new file mode 100644 index 000000000..31c2e8f08 --- /dev/null +++ b/client/tests/helpers/placeFormSetup.ts @@ -0,0 +1,26 @@ +import { vi } from 'vitest'; + +import { useAuthStore } from '../../src/store/authStore'; +import { useTripStore } from '../../src/store/tripStore'; +import { buildTrip, buildUser } from './factories'; +import { seedStore } from './store'; + +/** The props an open place form gets when a test sets none: a new place in trip 1. */ +export const placeFormProps = { + isOpen: true, + onClose: vi.fn(), + onSave: vi.fn(), + place: null, + prefillCoords: null, + tripId: 1, + categories: [], + onCategoryCreated: vi.fn(), + assignmentId: null, + dayAssignments: [], +}; + +/** A signed-in user without a maps key, in trip 1: what the form reads before it renders. */ +export function seedPlaceFormStores() { + seedStore(useAuthStore, { user: buildUser(), isAuthenticated: true, hasMapsKey: false }); + seedStore(useTripStore, { trip: buildTrip({ id: 1 }) }); +} diff --git a/server/src/nest/maps/trek-places.client.ts b/server/src/nest/maps/trek-places.client.ts index aba56699d..6930fb8a7 100644 --- a/server/src/nest/maps/trek-places.client.ts +++ b/server/src/nest/maps/trek-places.client.ts @@ -750,7 +750,7 @@ const trekWayTagsSchema = z.object({ tags: osmTagsSchema.default({}), }); /** One way of the ways layer, as `way(id:...);out tags;` answers it: only the keys the layer keeps. */ -export type TrekWayTags = z.infer; +type TrekWayTags = z.infer; const pointSchema = z.object({ lat: z.number().min(-90).max(90), lon: z.number().min(-180).max(180) }); const memberSchema = z.object({ type: z.enum(['node', 'way', 'relation']), ref: osmIdSchema, role: z.string() });