From 9ed944c1e65182f18e47adee9f23be38e8063d95 Mon Sep 17 00:00:00 2001 From: Maurice Date: Mon, 19 Oct 2026 21:35:50 +0000 Subject: [PATCH] fix(tours): city walk gates: entity collection, formatting, a walk's name hint and the tests' visits repository The day assignments entity carries the station visits that hang off it, as the generator writes it. A city walk gets its own placeholder for an untitled name, the tour service tests hand in the visits repository the service now takes, and the files the walk touched are formatted. The theme icons of the place search overlap by their start margin, so they stack the same way in both reading directions. --- .../src/components/Planner/DayPlanPlaceSubline.tsx | 11 +++++++++-- .../components/Tours/planner/TourEditorFields.tsx | 1 + .../components/Tours/planner/TourWaypointList.tsx | 6 +++--- .../components/Tours/planner/tourPlannerWaypoints.ts | 9 ++++++++- .../src/components/Tours/poi/TourPoiSearchCard.tsx | 6 +++--- server/src/db/entities/DayAssignments.entity.ts | 3 +++ .../db/repositories/TourStationVisits.repository.ts | 7 ++----- server/src/nest/tours/tour-visits.controller.ts | 12 +++++++++++- server/src/nest/tours/tour-visits.service.ts | 5 ++++- server/src/nest/tours/tours.module.ts | 12 ++++++++++-- server/src/nest/tours/tours.service.ts | 7 ++++--- server/tests/helpers/tours-repos.ts | 6 ++++++ server/tests/unit/nest/tours.gpx.atomic.test.ts | 8 +++++++- .../tours.permissions.boundaries.mock-only.test.ts | 2 ++ .../unit/nest/tours.service.permissions.test.ts | 2 ++ server/tests/unit/nest/tours.service.test.ts | 2 ++ shared/src/i18n/ar/tours.ts | 1 + shared/src/i18n/az/tours.ts | 1 + shared/src/i18n/br/tours.ts | 1 + shared/src/i18n/ca/tours.ts | 1 + shared/src/i18n/cs/tours.ts | 1 + shared/src/i18n/de/tours.ts | 1 + shared/src/i18n/en/tours.ts | 1 + shared/src/i18n/es/tours.ts | 1 + shared/src/i18n/et/tours.ts | 1 + shared/src/i18n/fr/tours.ts | 1 + shared/src/i18n/gr/tours.ts | 1 + shared/src/i18n/hu/tours.ts | 1 + shared/src/i18n/id/tours.ts | 1 + shared/src/i18n/it/tours.ts | 1 + shared/src/i18n/ja/tours.ts | 1 + shared/src/i18n/ko/tours.ts | 1 + shared/src/i18n/nl/tours.ts | 1 + shared/src/i18n/pl/tours.ts | 1 + shared/src/i18n/ru/tours.ts | 1 + shared/src/i18n/sk/tours.ts | 1 + shared/src/i18n/sv/tours.ts | 1 + shared/src/i18n/th/tours.ts | 1 + shared/src/i18n/tours-locales.spec.ts | 2 +- shared/src/i18n/tr/tours.ts | 1 + shared/src/i18n/uk/tours.ts | 1 + shared/src/i18n/vi/tours.ts | 1 + shared/src/i18n/zh-TW/tours.ts | 1 + shared/src/i18n/zh/tours.ts | 1 + shared/src/tours/tour-walk.schema.ts | 8 ++++---- 45 files changed, 109 insertions(+), 27 deletions(-) diff --git a/client/src/components/Planner/DayPlanPlaceSubline.tsx b/client/src/components/Planner/DayPlanPlaceSubline.tsx index 8d40d4cb1..3db2833d8 100644 --- a/client/src/components/Planner/DayPlanPlaceSubline.tsx +++ b/client/src/components/Planner/DayPlanPlaceSubline.tsx @@ -7,9 +7,9 @@ import type { Category, Place } from '../../types'; import { formatTime } from '../../utils/formatters'; import { fs } from '../shared/DialogShell'; import { TourDayRowPills } from '../Tours/TourDayRowFacts'; -import { WalkProgressPill } from '../Tours/walk/WalkStations'; import { movingTimeLabel } from '../Tours/tourFacts'; import { formatPlannedTourDuration, type TourPlannedTimes } from '../Tours/tourPresentation'; +import { WalkProgressPill } from '../Tours/walk/WalkStations'; import { TimePill } from './planParts'; type DayRowTourTimes = TourPlannedTimes & { tour?: TourListItem }; @@ -93,7 +93,14 @@ function SublineDescription({ text, isTourPlace }: { text: string; isTourPlace: // Second line of a place row in the day plan: time, tour facts or planned // tour durations, then the clamped description. -export function DayPlanPlaceSubline({ place, cat, tourTimes, isTourPlace, timeFormat, assignmentId }: DayPlanPlaceSublineProps) { +export function DayPlanPlaceSubline({ + place, + cat, + tourTimes, + isTourPlace, + timeFormat, + assignmentId, +}: DayPlanPlaceSublineProps) { const { locale } = useTranslation(); const dayRowTour = tourTimes?.tour; const description = place.description || place.address || cat?.name; diff --git a/client/src/components/Tours/planner/TourEditorFields.tsx b/client/src/components/Tours/planner/TourEditorFields.tsx index b34c7e122..54b3f65a9 100644 --- a/client/src/components/Tours/planner/TourEditorFields.tsx +++ b/client/src/components/Tours/planner/TourEditorFields.tsx @@ -79,6 +79,7 @@ export function TourNameField({ planner, locked }: TourFieldProps) { hike: t('tours.planner.namePlaceholder'), bike: t('tours.planner.namePlaceholder.bike'), kayak: t('tours.planner.namePlaceholder.kayak'), + walk: t('tours.planner.namePlaceholder.walk'), }[planner.tourType] } className={INPUT} diff --git a/client/src/components/Tours/planner/TourWaypointList.tsx b/client/src/components/Tours/planner/TourWaypointList.tsx index 10112b543..3310d2e6d 100644 --- a/client/src/components/Tours/planner/TourWaypointList.tsx +++ b/client/src/components/Tours/planner/TourWaypointList.tsx @@ -17,8 +17,8 @@ import { Navigation, RefreshCw, Repeat, - SquarePen, Spline, + SquarePen, Trash2, Unlink, Waves, @@ -47,10 +47,10 @@ import { usePaddleRegionLoad } from '../paddle/usePaddleRegionLoad'; import { usePaddleWaypointActions } from '../paddle/usePaddleWaypointActions'; import { usePortageRouting, usePortageWay } from '../paddle/usePortageRouting'; import { RailCard } from '../tourParts'; -import { StationDialog } from './StationDialog'; -import { StationPills } from './stationParts'; import { paddlePlanPoints, paddleRolesById } from './paddlePlanOf'; import type { PaddleLegFailure } from './paddleRouting'; +import { StationDialog } from './StationDialog'; +import { StationPills } from './stationParts'; import { lineLengthM } from './tourFixedLegs'; import { TripPlacePicker } from './TripPlacePicker'; import type { TourPlannerController } from './useTourPlanner'; diff --git a/client/src/components/Tours/planner/tourPlannerWaypoints.ts b/client/src/components/Tours/planner/tourPlannerWaypoints.ts index 96fa61a86..68021dc15 100644 --- a/client/src/components/Tours/planner/tourPlannerWaypoints.ts +++ b/client/src/components/Tours/planner/tourPlannerWaypoints.ts @@ -1,4 +1,11 @@ -import type { PaddleLock, PlannableTourType, StationImportance, TourFixedLeg, TourWaypoint, TourWaypointRole } from '@trek/shared'; +import type { + PaddleLock, + PlannableTourType, + StationImportance, + TourFixedLeg, + TourWaypoint, + TourWaypointRole, +} from '@trek/shared'; import type { AutoBase } from './paddleRouting'; import { keepJoinedFixedLegs } from './tourFixedLegs'; import { alignFreeLegs } from './tourRouteActions'; diff --git a/client/src/components/Tours/poi/TourPoiSearchCard.tsx b/client/src/components/Tours/poi/TourPoiSearchCard.tsx index 92807f0a8..68f7795d6 100644 --- a/client/src/components/Tours/poi/TourPoiSearchCard.tsx +++ b/client/src/components/Tours/poi/TourPoiSearchCard.tsx @@ -70,13 +70,13 @@ function CategoryPicker({ search }: { search: TourPoiSearch }) { className="flex w-full min-w-0 items-center gap-2 rounded-[10px] border border-edge bg-surface-input px-2.5 py-1.5 text-start hover:border-content-faint" > {t('tours.poi.categories')}: -