diff --git a/client/src/components/Roadtrip/RoadtripCorridorPanel.tsx b/client/src/components/Roadtrip/RoadtripCorridorPanel.tsx
index ef6236c50..4761fb68f 100644
--- a/client/src/components/Roadtrip/RoadtripCorridorPanel.tsx
+++ b/client/src/components/Roadtrip/RoadtripCorridorPanel.tsx
@@ -1,7 +1,6 @@
import React from 'react'
import {
- Fuel, Zap, ParkingSquare, Tent, Utensils, Camera, Search, Plus, RotateCw,
- AlertTriangle, MapPin, X, type LucideIcon,
+ Search, Plus, RotateCw, AlertTriangle, X, BedDouble, MapPin,
} from 'lucide-react'
import { useTranslation } from '../../i18n/TranslationContext'
import { Tooltip } from '../shared/Tooltip'
@@ -90,18 +89,26 @@ function ResultRow({ poi, onAdd }: { poi: CorridorPoi; onAdd?: () => void }): Re
{/* Always there, quiet until the row is under the pointer: a button that only
exists on hover is one a keyboard user has to find by faith. */}
- {onAdd ? (
-
-
-
- ) : null}
+ {onAdd ? (() => {
+ // One button, two meanings. Somewhere to sleep ends the day rather than
+ // interrupting the drive, so the icon and the label say that before the dialog
+ // opens instead of after.
+ const night = poi.category === 'hotel'
+ const label = night ? t('roadtrip.stay.nightAction') : t('roadtrip.poi.add')
+ const Icon = night ? BedDouble : Plus
+ return (
+
+
+
+ )
+ })() : null}
)
}
diff --git a/client/src/components/Roadtrip/RoadtripSidebar.tsx b/client/src/components/Roadtrip/RoadtripSidebar.tsx
index 8610c8659..84adc3f51 100644
--- a/client/src/components/Roadtrip/RoadtripSidebar.tsx
+++ b/client/src/components/Roadtrip/RoadtripSidebar.tsx
@@ -576,7 +576,7 @@ function Arrival({ entry }: { entry: ScheduleEntry }): React.ReactElement {
)
}
-function Stop({ stop, number, entry, late, driveFindings, selected, continues, onSelect, onMove, canMove, onEditStay }: {
+function Stop({ stop, number, entry, late, driveFindings, selected, continues, starts, onSelect, onMove, canMove, onEditStay }: {
stop: RoadtripStop
/** Position within the day — the same count the map badges its markers with. */
number: number
@@ -587,6 +587,8 @@ function Stop({ stop, number, entry, late, driveFindings, selected, continues, o
selected: boolean
/** Whether the chain goes on below, so the marker keeps hold of the line. */
continues: boolean
+ /** First row of the day: no line above it, because the chain starts here. */
+ starts?: boolean
onSelect?: () => void
/** Moves this stop by one place. Absent means the chain is read-only. */
onMove?: (delta: number) => void
@@ -614,16 +616,20 @@ function Stop({ stop, number, entry, late, driveFindings, selected, continues, o
className="group grid w-full rounded-lg text-start focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-accent"
style={RAIL_GRID}
>
- {/* The marker and the line below it share one column, so the chain runs unbroken
- from stop to stop rather than restarting under whatever the row happens to hold. */}
+ {/* The marker sits level with the middle of the row rather than at its top, the
+ way the corridor list already places its own badges: a number pinned to the
+ first line drifts away from the row as soon as a stop carries a stay and a walk
+ under its name. The line grows above and below it, so the chain still runs
+ unbroken from stop to stop. */}
+ {starts ? null : }
{number}
- {continues ? : null}
+ {continues ? : null}
{/* The fill stops at the rail: the number is part of the chain, not part of the row
@@ -810,6 +816,7 @@ function DaySection({ day, selectedAssignmentId, onSelectStop, onReorderStop, on
driveFindings={day.driveWarnings.filter(w => w.index === i)}
selected={selectedAssignmentId === stop.assignmentId}
continues={i < last}
+ starts={i === 0}
onSelect={onSelectStop ? () => onSelectStop(stop.placeId, stop.assignmentId) : undefined}
onMove={onReorderStop ? delta => onReorderStop(day.dayId, stop.assignmentId, i + delta) : undefined}
canMove={{ up: i > 0, down: i < last }}
diff --git a/client/src/components/Roadtrip/roadtripModel.test.ts b/client/src/components/Roadtrip/roadtripModel.test.ts
index 1e8ad75dc..3f33ff957 100644
--- a/client/src/components/Roadtrip/roadtripModel.test.ts
+++ b/client/src/components/Roadtrip/roadtripModel.test.ts
@@ -289,14 +289,28 @@ describe('deriveDriveWarnings', () => {
{ legMinutes: null, dayMinutes: null, rangeKm: 100 },
0,
)
- // 21.5 + 103.4 on arrival at HEM, then 244.7 on arrival at Berlin, because the budget
- // starts over after each finding.
+ // 21.5 + 103.4 on arrival at HEM, and then it keeps counting, because nothing on this
+ // trip fills up.
expect(out.warnings).toEqual([
{ index: 2, code: 'range', sinceKm: 125 },
- { index: 3, code: 'range', sinceKm: 245 },
+ { index: 3, code: 'range', sinceKm: 370 },
])
})
+ it('FE-ROADTRIP-MODEL-070: arriving at a petrol station is the plan, not a warning', () => {
+ // Same trip, but HEM is marked as fuel. Reaching it with an empty tank is exactly
+ // what it is there for, so nothing is flagged on it; the budget still starts over,
+ // and the next stretch is measured from there.
+ const out = deriveDriveWarnings(
+ [leg(20, 21.5), leg(62, 103.4), leg(155, 244.7)],
+ [false, false, true, false],
+ { legMinutes: null, dayMinutes: null, rangeKm: 100 },
+ 0,
+ )
+ expect(out.warnings).toEqual([{ index: 3, code: 'range', sinceKm: 245 }])
+ // 245 and not 370: HEM filled the tank, so Berlin counts from there.
+ })
+
const noLimits = { legMinutes: null, dayMinutes: null, rangeKm: null }
const leg = (minutes: number, km: number) => ({ duration: minutes * 60, distance: km * 1000 })
@@ -329,20 +343,34 @@ describe('deriveDriveWarnings', () => {
expect(out.day).toEqual({ code: 'dayDriving', minutes: 400, limitMinutes: 360 })
})
- it('FE-ROADTRIP-MODEL-063: the range runs out once and then starts over', () => {
- // Without the reset, a 1800 km trip on a 600 km range flags every leg after the first
- // overrun, which is a column of red nobody reads. With it the marks stand one range
- // apart and each means "fill up around here".
+ it('FE-ROADTRIP-MODEL-063: the figure keeps counting until something actually refuels', () => {
+ // A warning is not a fill-up. Zeroing the budget at one made every figure after the
+ // first wrong: the second stop would claim a fresh tank while the same one is still
+ // in the car.
const out = deriveDriveWarnings(
[leg(60, 300), leg(60, 400), leg(60, 300), leg(60, 400)],
[false, false, false, false, false],
{ ...noLimits, rangeKm: 600 },
0,
)
- expect(out.warnings.map(w => w.code)).toEqual(['range', 'range'])
- // 300 + 400 on arrival at stop 2, which is exactly what adding up the two drive bands
- // above it gives.
- expect(out.warnings[0]).toEqual({ index: 2, code: 'range', sinceKm: 700 })
+ expect(out.warnings).toEqual([
+ { index: 2, code: 'range', sinceKm: 700 },
+ { index: 3, code: 'range', sinceKm: 1000 },
+ { index: 4, code: 'range', sinceKm: 1400 },
+ ])
+ })
+
+ it('FE-ROADTRIP-MODEL-071: adding a fuel stop is what stops the run of warnings', () => {
+ // The same drive with a charger at stop 2. Nothing is flagged there, because reaching
+ // it on an empty tank is what it is for; everything after counts from zero again, so
+ // the three-warning run above collapses to one.
+ const out = deriveDriveWarnings(
+ [leg(60, 300), leg(60, 400), leg(60, 300), leg(60, 400)],
+ [false, false, true, false, false],
+ { ...noLimits, rangeKm: 600 },
+ 0,
+ )
+ expect(out.warnings).toEqual([{ index: 4, code: 'range', sinceKm: 700 }])
})
it('FE-ROADTRIP-MODEL-064: filling up starts the budget over, resting does not', () => {
diff --git a/client/src/components/Roadtrip/roadtripModel.ts b/client/src/components/Roadtrip/roadtripModel.ts
index 49dd79c5a..9b8ec45e8 100644
--- a/client/src/components/Roadtrip/roadtripModel.ts
+++ b/client/src/components/Roadtrip/roadtripModel.ts
@@ -304,10 +304,13 @@ export function sumLegSeconds(legSeconds: (number | undefined)[]): number {
* an hour of the day would simply never fire. All three limits are therefore durations and
* kilometres, which exist as soon as a leg has routed.
*
- * The range budget carries across midnight, because a tank does not empty overnight, and
- * resets to zero after a finding: without that reset, one trip of 1800 km on a 600 km
- * range flags every leg after the first overrun, which is a column of red nobody reads.
- * With it, the marks stand one range apart and each one means "fill up around here".
+ * The range budget resets at a fuel or charging stop and NOWHERE ELSE. It carries across
+ * midnight, because a tank does not empty overnight, and it keeps counting past a finding,
+ * because a warning is not a fill-up. Zeroing it there made the second figure wrong and
+ * every one after it: a day reading 245 km at one stop and 121 at the next claims the 121
+ * is a fresh tank, when it is 366 on the same one. A run of warnings down a stretch with
+ * no fuel on it is not noise; it is the answer, and it stops the moment a fuel or
+ * charging stop is put in.
*
* An unrouted leg gives the budget up entirely rather than guessing, the same way the
* schedule abandons its cursor: a distance we do not have cannot be added to one we do.
@@ -341,9 +344,12 @@ export function deriveDriveWarnings(
budget = null
} else if (budget !== null) {
budget += metres / 1000
- if (limits.rangeKm && budget > limits.rangeKm) {
+ // Not on a stop that fills up: arriving at a petrol station with an empty tank is
+ // the plan working, not a problem, and a warning there would sit on the one stop
+ // that answers it. No reset either — a warning is not a fill-up, and the figure has
+ // to keep counting until a fuel or charging stop actually puts one in.
+ if (limits.rangeKm && budget > limits.rangeKm && !refuelsAt[at]) {
warnings.push({ index: at, code: 'range', sinceKm: Math.round(budget) })
- budget = 0
}
}
}
diff --git a/shared/src/i18n/ar/roadtrip.ts b/shared/src/i18n/ar/roadtrip.ts
index cbd7e92ed..0b4535992 100644
--- a/shared/src/i18n/ar/roadtrip.ts
+++ b/shared/src/i18n/ar/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'غير محددة',
'roadtrip.stop.none': 'وجهة',
'roadtrip.stop.kindHelp': 'التوقف في الطريق يُرسم على المسار ولا يُحتسب ضمن عدد التوقفات.',
+ 'roadtrip.stay.mode.pause': 'استراحة',
+ 'roadtrip.stay.mode.night': 'مبيت',
+ 'roadtrip.stay.checkOutDay': 'المغادرة في',
+ 'roadtrip.stay.dayNumber': 'اليوم {number}',
+ 'roadtrip.stay.nightAdded': 'أُضيف كمبيت',
+ 'roadtrip.stay.nightAction': 'إضافة كمبيت',
'roadtrip.poi.rest': 'استراحة',
'roadtrip.poi.campsite': 'مخيم',
'roadtrip.poi.food': 'طعام',
diff --git a/shared/src/i18n/br/roadtrip.ts b/shared/src/i18n/br/roadtrip.ts
index b2cb362d8..f9048e136 100644
--- a/shared/src/i18n/br/roadtrip.ts
+++ b/shared/src/i18n/br/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'Nenhum definido',
'roadtrip.stop.none': 'Um destino',
'roadtrip.stop.kindHelp': 'Uma parada no caminho é desenhada no trajeto e não é contada.',
+ 'roadtrip.stay.mode.pause': 'Pausa',
+ 'roadtrip.stay.mode.night': 'Pernoite',
+ 'roadtrip.stay.checkOutDay': 'Saída em',
+ 'roadtrip.stay.dayNumber': 'Dia {number}',
+ 'roadtrip.stay.nightAdded': 'Adicionado como pernoite',
+ 'roadtrip.stay.nightAction': 'Adicionar como pernoite',
'roadtrip.poi.rest': 'Área de descanso',
'roadtrip.poi.campsite': 'Camping',
'roadtrip.poi.food': 'Comida',
diff --git a/shared/src/i18n/ca/roadtrip.ts b/shared/src/i18n/ca/roadtrip.ts
index 7fca4f9f7..0cb15311a 100644
--- a/shared/src/i18n/ca/roadtrip.ts
+++ b/shared/src/i18n/ca/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'Cap definit',
'roadtrip.stop.none': 'Una destinació',
'roadtrip.stop.kindHelp': 'Una parada al camí es dibuixa sobre el trajecte i no es compta.',
+ 'roadtrip.stay.mode.pause': 'Parada',
+ 'roadtrip.stay.mode.night': 'Pernoctar',
+ 'roadtrip.stay.checkOutDay': 'Sortida el',
+ 'roadtrip.stay.dayNumber': 'Dia {number}',
+ 'roadtrip.stay.nightAdded': 'Afegit com a pernoctació',
+ 'roadtrip.stay.nightAction': 'Afegeix com a pernoctació',
'roadtrip.poi.rest': 'Àrea de descans',
'roadtrip.poi.campsite': 'Càmping',
'roadtrip.poi.food': 'Menjar',
diff --git a/shared/src/i18n/cs/roadtrip.ts b/shared/src/i18n/cs/roadtrip.ts
index 9dd5acfc8..5d65b343e 100644
--- a/shared/src/i18n/cs/roadtrip.ts
+++ b/shared/src/i18n/cs/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'Nenastaveno',
'roadtrip.stop.none': 'Cíl cesty',
'roadtrip.stop.kindHelp': 'Zastávka po cestě se kreslí na trase a nepočítá se.',
+ 'roadtrip.stay.mode.pause': 'Pauza',
+ 'roadtrip.stay.mode.night': 'Nocleh',
+ 'roadtrip.stay.checkOutDay': 'Odjezd',
+ 'roadtrip.stay.dayNumber': 'Den {number}',
+ 'roadtrip.stay.nightAdded': 'Přidáno jako nocleh',
+ 'roadtrip.stay.nightAction': 'Přidat jako nocleh',
'roadtrip.poi.rest': 'Odpočívadlo',
'roadtrip.poi.campsite': 'Kemp',
'roadtrip.poi.food': 'Jídlo',
diff --git a/shared/src/i18n/de/roadtrip.ts b/shared/src/i18n/de/roadtrip.ts
index 7f57b1981..eaa85f6f7 100644
--- a/shared/src/i18n/de/roadtrip.ts
+++ b/shared/src/i18n/de/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'Keine gesetzt',
'roadtrip.stop.none': 'Ein Ziel',
'roadtrip.stop.kindHelp': 'Ein Halt unterwegs wird auf der Fahrt gezeichnet und nicht mitgezählt.',
+ 'roadtrip.stay.mode.pause': 'Pause',
+ 'roadtrip.stay.mode.night': 'Übernachten',
+ 'roadtrip.stay.checkOutDay': 'Abreise am',
+ 'roadtrip.stay.dayNumber': 'Tag {number}',
+ 'roadtrip.stay.nightAdded': 'Als Übernachtung hinzugefügt',
+ 'roadtrip.stay.nightAction': 'Als Übernachtung hinzufügen',
'roadtrip.poi.rest': 'Rastplatz',
'roadtrip.poi.campsite': 'Campingplatz',
'roadtrip.poi.food': 'Essen',
diff --git a/shared/src/i18n/en/roadtrip.ts b/shared/src/i18n/en/roadtrip.ts
index 0d7c40a2d..4e4c18ffb 100644
--- a/shared/src/i18n/en/roadtrip.ts
+++ b/shared/src/i18n/en/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'None set',
'roadtrip.stop.none': 'A destination',
'roadtrip.stop.kindHelp': 'A pause on the way is drawn on the drive and left out of the stop count.',
+ 'roadtrip.stay.mode.pause': 'Pause',
+ 'roadtrip.stay.mode.night': 'Overnight',
+ 'roadtrip.stay.checkOutDay': 'Check out on',
+ 'roadtrip.stay.dayNumber': 'Day {number}',
+ 'roadtrip.stay.nightAdded': 'Added as an overnight stay',
+ 'roadtrip.stay.nightAction': 'Add as an overnight stay',
'roadtrip.poi.rest': 'Rest area',
'roadtrip.poi.campsite': 'Campsite',
'roadtrip.poi.food': 'Food',
diff --git a/shared/src/i18n/es/roadtrip.ts b/shared/src/i18n/es/roadtrip.ts
index e83107ce9..3d767f934 100644
--- a/shared/src/i18n/es/roadtrip.ts
+++ b/shared/src/i18n/es/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'Ninguno definido',
'roadtrip.stop.none': 'Un destino',
'roadtrip.stop.kindHelp': 'Una parada en el camino se dibuja sobre el trayecto y no se cuenta.',
+ 'roadtrip.stay.mode.pause': 'Parada',
+ 'roadtrip.stay.mode.night': 'Pernoctar',
+ 'roadtrip.stay.checkOutDay': 'Salida el',
+ 'roadtrip.stay.dayNumber': 'Día {number}',
+ 'roadtrip.stay.nightAdded': 'Añadido como pernoctación',
+ 'roadtrip.stay.nightAction': 'Añadir como pernoctación',
'roadtrip.poi.rest': 'Área de descanso',
'roadtrip.poi.campsite': 'Camping',
'roadtrip.poi.food': 'Comida',
diff --git a/shared/src/i18n/fr/roadtrip.ts b/shared/src/i18n/fr/roadtrip.ts
index aeebbfff9..a76d8eacc 100644
--- a/shared/src/i18n/fr/roadtrip.ts
+++ b/shared/src/i18n/fr/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'Aucune définie',
'roadtrip.stop.none': 'Une destination',
'roadtrip.stop.kindHelp': 'Un arrêt en chemin est dessiné sur le trajet et n’est pas compté.',
+ 'roadtrip.stay.mode.pause': 'Pause',
+ 'roadtrip.stay.mode.night': 'Nuitée',
+ 'roadtrip.stay.checkOutDay': 'Départ le',
+ 'roadtrip.stay.dayNumber': 'Jour {number}',
+ 'roadtrip.stay.nightAdded': 'Ajouté comme nuitée',
+ 'roadtrip.stay.nightAction': 'Ajouter comme nuitée',
'roadtrip.poi.rest': 'Aire de repos',
'roadtrip.poi.campsite': 'Camping',
'roadtrip.poi.food': 'Restauration',
diff --git a/shared/src/i18n/gr/roadtrip.ts b/shared/src/i18n/gr/roadtrip.ts
index 1c452e27e..b3338f053 100644
--- a/shared/src/i18n/gr/roadtrip.ts
+++ b/shared/src/i18n/gr/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'Δεν έχουν οριστεί',
'roadtrip.stop.none': 'Προορισμός',
'roadtrip.stop.kindHelp': 'Μια στάση στον δρόμο σχεδιάζεται πάνω στη διαδρομή και δεν προσμετράται.',
+ 'roadtrip.stay.mode.pause': 'Στάση',
+ 'roadtrip.stay.mode.night': 'Διανυκτέρευση',
+ 'roadtrip.stay.checkOutDay': 'Αναχώρηση',
+ 'roadtrip.stay.dayNumber': 'Ημέρα {number}',
+ 'roadtrip.stay.nightAdded': 'Προστέθηκε ως διανυκτέρευση',
+ 'roadtrip.stay.nightAction': 'Προσθήκη ως διανυκτέρευση',
'roadtrip.poi.rest': 'Χώρος ανάπαυσης',
'roadtrip.poi.campsite': 'Κάμπινγκ',
'roadtrip.poi.food': 'Φαγητό',
diff --git a/shared/src/i18n/hu/roadtrip.ts b/shared/src/i18n/hu/roadtrip.ts
index e3666f45b..6594941d6 100644
--- a/shared/src/i18n/hu/roadtrip.ts
+++ b/shared/src/i18n/hu/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'Nincs beállítva',
'roadtrip.stop.none': 'Úti cél',
'roadtrip.stop.kindHelp': 'Az útközbeni megálló az útvonalra kerül, és nem számít bele.',
+ 'roadtrip.stay.mode.pause': 'Szünet',
+ 'roadtrip.stay.mode.night': 'Éjszakázás',
+ 'roadtrip.stay.checkOutDay': 'Kijelentkezés',
+ 'roadtrip.stay.dayNumber': '{number}. nap',
+ 'roadtrip.stay.nightAdded': 'Hozzáadva éjszakázásként',
+ 'roadtrip.stay.nightAction': 'Hozzáadás éjszakázásként',
'roadtrip.poi.rest': 'Pihenőhely',
'roadtrip.poi.campsite': 'Kemping',
'roadtrip.poi.food': 'Étkezés',
diff --git a/shared/src/i18n/id/roadtrip.ts b/shared/src/i18n/id/roadtrip.ts
index c87edc901..c76908285 100644
--- a/shared/src/i18n/id/roadtrip.ts
+++ b/shared/src/i18n/id/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'Belum diatur',
'roadtrip.stop.none': 'Sebuah tujuan',
'roadtrip.stop.kindHelp': 'Perhentian di jalan digambar pada rute dan tidak dihitung.',
+ 'roadtrip.stay.mode.pause': 'Istirahat',
+ 'roadtrip.stay.mode.night': 'Menginap',
+ 'roadtrip.stay.checkOutDay': 'Check out',
+ 'roadtrip.stay.dayNumber': 'Hari {number}',
+ 'roadtrip.stay.nightAdded': 'Ditambahkan sebagai menginap',
+ 'roadtrip.stay.nightAction': 'Tambahkan sebagai menginap',
'roadtrip.poi.rest': 'Tempat istirahat',
'roadtrip.poi.campsite': 'Perkemahan',
'roadtrip.poi.food': 'Makanan',
diff --git a/shared/src/i18n/it/roadtrip.ts b/shared/src/i18n/it/roadtrip.ts
index bd42c75ee..5c6ebbbda 100644
--- a/shared/src/i18n/it/roadtrip.ts
+++ b/shared/src/i18n/it/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'Nessuno impostato',
'roadtrip.stop.none': 'Una destinazione',
'roadtrip.stop.kindHelp': 'Una sosta lungo il percorso viene disegnata sulla tratta e non viene contata.',
+ 'roadtrip.stay.mode.pause': 'Sosta',
+ 'roadtrip.stay.mode.night': 'Pernottamento',
+ 'roadtrip.stay.checkOutDay': 'Partenza il',
+ 'roadtrip.stay.dayNumber': 'Giorno {number}',
+ 'roadtrip.stay.nightAdded': 'Aggiunto come pernottamento',
+ 'roadtrip.stay.nightAction': 'Aggiungi come pernottamento',
'roadtrip.poi.rest': 'Area di sosta',
'roadtrip.poi.campsite': 'Campeggio',
'roadtrip.poi.food': 'Ristoro',
diff --git a/shared/src/i18n/ja/roadtrip.ts b/shared/src/i18n/ja/roadtrip.ts
index bcc230370..21ecbce17 100644
--- a/shared/src/i18n/ja/roadtrip.ts
+++ b/shared/src/i18n/ja/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': '未設定',
'roadtrip.stop.none': '目的地',
'roadtrip.stop.kindHelp': '途中の立ち寄りは走行線上に描かれ、停車数には数えません。',
+ 'roadtrip.stay.mode.pause': '休憩',
+ 'roadtrip.stay.mode.night': '宿泊',
+ 'roadtrip.stay.checkOutDay': 'チェックアウト日',
+ 'roadtrip.stay.dayNumber': '{number}日目',
+ 'roadtrip.stay.nightAdded': '宿泊として追加しました',
+ 'roadtrip.stay.nightAction': '宿泊として追加',
'roadtrip.poi.rest': 'サービスエリア',
'roadtrip.poi.campsite': 'キャンプ場',
'roadtrip.poi.food': '食事',
diff --git a/shared/src/i18n/ko/roadtrip.ts b/shared/src/i18n/ko/roadtrip.ts
index 92fc9573e..6625efc92 100644
--- a/shared/src/i18n/ko/roadtrip.ts
+++ b/shared/src/i18n/ko/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': '설정 안 됨',
'roadtrip.stop.none': '목적지',
'roadtrip.stop.kindHelp': '경유 정차는 주행 경로에 표시되며 정차 수에 포함되지 않습니다.',
+ 'roadtrip.stay.mode.pause': '휴식',
+ 'roadtrip.stay.mode.night': '숙박',
+ 'roadtrip.stay.checkOutDay': '체크아웃 날짜',
+ 'roadtrip.stay.dayNumber': '{number}일차',
+ 'roadtrip.stay.nightAdded': '숙박으로 추가했습니다',
+ 'roadtrip.stay.nightAction': '숙박으로 추가',
'roadtrip.poi.rest': '휴게소',
'roadtrip.poi.campsite': '캠핑장',
'roadtrip.poi.food': '식사',
diff --git a/shared/src/i18n/nl/roadtrip.ts b/shared/src/i18n/nl/roadtrip.ts
index 4cd4277a0..caa162ce4 100644
--- a/shared/src/i18n/nl/roadtrip.ts
+++ b/shared/src/i18n/nl/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'Geen ingesteld',
'roadtrip.stop.none': 'Een bestemming',
'roadtrip.stop.kindHelp': 'Een stop onderweg wordt op de rit getekend en telt niet mee.',
+ 'roadtrip.stay.mode.pause': 'Pauze',
+ 'roadtrip.stay.mode.night': 'Overnachten',
+ 'roadtrip.stay.checkOutDay': 'Uitchecken op',
+ 'roadtrip.stay.dayNumber': 'Dag {number}',
+ 'roadtrip.stay.nightAdded': 'Toegevoegd als overnachting',
+ 'roadtrip.stay.nightAction': 'Toevoegen als overnachting',
'roadtrip.poi.rest': 'Rustplaats',
'roadtrip.poi.campsite': 'Camping',
'roadtrip.poi.food': 'Eten',
diff --git a/shared/src/i18n/pl/roadtrip.ts b/shared/src/i18n/pl/roadtrip.ts
index cadd4f4be..17249cd7c 100644
--- a/shared/src/i18n/pl/roadtrip.ts
+++ b/shared/src/i18n/pl/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'Brak ustawionych',
'roadtrip.stop.none': 'Cel podróży',
'roadtrip.stop.kindHelp': 'Postój po drodze rysowany jest na trasie i nie jest liczony.',
+ 'roadtrip.stay.mode.pause': 'Postój',
+ 'roadtrip.stay.mode.night': 'Nocleg',
+ 'roadtrip.stay.checkOutDay': 'Wymeldowanie',
+ 'roadtrip.stay.dayNumber': 'Dzień {number}',
+ 'roadtrip.stay.nightAdded': 'Dodano jako nocleg',
+ 'roadtrip.stay.nightAction': 'Dodaj jako nocleg',
'roadtrip.poi.rest': 'Miejsce odpoczynku',
'roadtrip.poi.campsite': 'Kemping',
'roadtrip.poi.food': 'Jedzenie',
diff --git a/shared/src/i18n/ru/roadtrip.ts b/shared/src/i18n/ru/roadtrip.ts
index b4b807a99..e2c309045 100644
--- a/shared/src/i18n/ru/roadtrip.ts
+++ b/shared/src/i18n/ru/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'Не заданы',
'roadtrip.stop.none': 'Пункт назначения',
'roadtrip.stop.kindHelp': 'Остановка в пути рисуется на маршруте и не учитывается в счёте.',
+ 'roadtrip.stay.mode.pause': 'Остановка',
+ 'roadtrip.stay.mode.night': 'Ночёвка',
+ 'roadtrip.stay.checkOutDay': 'Выезд',
+ 'roadtrip.stay.dayNumber': 'День {number}',
+ 'roadtrip.stay.nightAdded': 'Добавлено как ночёвка',
+ 'roadtrip.stay.nightAction': 'Добавить как ночёвку',
'roadtrip.poi.rest': 'Зона отдыха',
'roadtrip.poi.campsite': 'Кемпинг',
'roadtrip.poi.food': 'Еда',
diff --git a/shared/src/i18n/sv/roadtrip.ts b/shared/src/i18n/sv/roadtrip.ts
index 2efc87400..5c490df95 100644
--- a/shared/src/i18n/sv/roadtrip.ts
+++ b/shared/src/i18n/sv/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'Inga angivna',
'roadtrip.stop.none': 'Ett resmål',
'roadtrip.stop.kindHelp': 'Ett stopp på vägen ritas på körningen och räknas inte.',
+ 'roadtrip.stay.mode.pause': 'Paus',
+ 'roadtrip.stay.mode.night': 'Övernattning',
+ 'roadtrip.stay.checkOutDay': 'Utcheckning',
+ 'roadtrip.stay.dayNumber': 'Dag {number}',
+ 'roadtrip.stay.nightAdded': 'Tillagd som övernattning',
+ 'roadtrip.stay.nightAction': 'Lägg till som övernattning',
'roadtrip.poi.rest': 'Rastplats',
'roadtrip.poi.campsite': 'Campingplats',
'roadtrip.poi.food': 'Mat',
diff --git a/shared/src/i18n/tr/roadtrip.ts b/shared/src/i18n/tr/roadtrip.ts
index 6881f2c30..0550743f8 100644
--- a/shared/src/i18n/tr/roadtrip.ts
+++ b/shared/src/i18n/tr/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'Ayarlanmadı',
'roadtrip.stop.none': 'Bir varış noktası',
'roadtrip.stop.kindHelp': 'Yol üzerindeki mola sürüşe çizilir ve sayıma girmez.',
+ 'roadtrip.stay.mode.pause': 'Mola',
+ 'roadtrip.stay.mode.night': 'Konaklama',
+ 'roadtrip.stay.checkOutDay': 'Çıkış günü',
+ 'roadtrip.stay.dayNumber': '{number}. gün',
+ 'roadtrip.stay.nightAdded': 'Konaklama olarak eklendi',
+ 'roadtrip.stay.nightAction': 'Konaklama olarak ekle',
'roadtrip.poi.rest': 'Dinlenme alanı',
'roadtrip.poi.campsite': 'Kamp alanı',
'roadtrip.poi.food': 'Yemek',
diff --git a/shared/src/i18n/uk/roadtrip.ts b/shared/src/i18n/uk/roadtrip.ts
index fd92332bd..4c4f90543 100644
--- a/shared/src/i18n/uk/roadtrip.ts
+++ b/shared/src/i18n/uk/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'Не задано',
'roadtrip.stop.none': 'Пункт призначення',
'roadtrip.stop.kindHelp': 'Зупинка в дорозі малюється на маршруті й не рахується.',
+ 'roadtrip.stay.mode.pause': 'Зупинка',
+ 'roadtrip.stay.mode.night': 'Ночівля',
+ 'roadtrip.stay.checkOutDay': 'Виїзд',
+ 'roadtrip.stay.dayNumber': 'День {number}',
+ 'roadtrip.stay.nightAdded': 'Додано як ночівлю',
+ 'roadtrip.stay.nightAction': 'Додати як ночівлю',
'roadtrip.poi.rest': 'Зона відпочинку',
'roadtrip.poi.campsite': 'Кемпінг',
'roadtrip.poi.food': 'Їжа',
diff --git a/shared/src/i18n/vi/roadtrip.ts b/shared/src/i18n/vi/roadtrip.ts
index c249535cd..2f00b4aa5 100644
--- a/shared/src/i18n/vi/roadtrip.ts
+++ b/shared/src/i18n/vi/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': 'Chưa đặt',
'roadtrip.stop.none': 'Một điểm đến',
'roadtrip.stop.kindHelp': 'Điểm dừng dọc đường được vẽ trên chặng và không tính vào số điểm dừng.',
+ 'roadtrip.stay.mode.pause': 'Nghỉ',
+ 'roadtrip.stay.mode.night': 'Qua đêm',
+ 'roadtrip.stay.checkOutDay': 'Trả phòng ngày',
+ 'roadtrip.stay.dayNumber': 'Ngày {number}',
+ 'roadtrip.stay.nightAdded': 'Đã thêm làm nơi nghỉ đêm',
+ 'roadtrip.stay.nightAction': 'Thêm làm nơi nghỉ đêm',
'roadtrip.poi.rest': 'Trạm dừng nghỉ',
'roadtrip.poi.campsite': 'Khu cắm trại',
'roadtrip.poi.food': 'Đồ ăn',
diff --git a/shared/src/i18n/zh-TW/roadtrip.ts b/shared/src/i18n/zh-TW/roadtrip.ts
index 0a9ffefad..a08c257fb 100644
--- a/shared/src/i18n/zh-TW/roadtrip.ts
+++ b/shared/src/i18n/zh-TW/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': '未設定',
'roadtrip.stop.none': '目的地',
'roadtrip.stop.kindHelp': '途中停靠會畫在行程線上,且不計入停靠數。',
+ 'roadtrip.stay.mode.pause': '停留',
+ 'roadtrip.stay.mode.night': '過夜',
+ 'roadtrip.stay.checkOutDay': '退房日',
+ 'roadtrip.stay.dayNumber': '第 {number} 天',
+ 'roadtrip.stay.nightAdded': '已新增為過夜住宿',
+ 'roadtrip.stay.nightAction': '新增為過夜住宿',
'roadtrip.poi.rest': '休息站',
'roadtrip.poi.campsite': '露營地',
'roadtrip.poi.food': '餐飲',
diff --git a/shared/src/i18n/zh/roadtrip.ts b/shared/src/i18n/zh/roadtrip.ts
index 555c4b3a8..c1dd71b28 100644
--- a/shared/src/i18n/zh/roadtrip.ts
+++ b/shared/src/i18n/zh/roadtrip.ts
@@ -32,6 +32,12 @@ const roadtrip: TranslationStrings = {
'roadtrip.limit.none': '未设置',
'roadtrip.stop.none': '目的地',
'roadtrip.stop.kindHelp': '途中停靠会画在行程线上,且不计入停靠数。',
+ 'roadtrip.stay.mode.pause': '停留',
+ 'roadtrip.stay.mode.night': '过夜',
+ 'roadtrip.stay.checkOutDay': '退房日',
+ 'roadtrip.stay.dayNumber': '第 {number} 天',
+ 'roadtrip.stay.nightAdded': '已添加为过夜住宿',
+ 'roadtrip.stay.nightAction': '添加为过夜住宿',
'roadtrip.poi.rest': '服务区',
'roadtrip.poi.campsite': '露营地',
'roadtrip.poi.food': '餐饮',