fix(places): let the pool follow the open day, and say that it does

The map has narrowed to the selected day on the Planned filter since #2024. The pool
beside it did not, so a trip with 55 planned places read 55 in the tab and drew five
pins on the map, with nothing anywhere to say the two were answering different
questions. Reported twice in the same thread as the map being broken: you pick a day,
open Places, tap Planned, see everything you ever planned, and the map shows a handful
of it.

The list and the tab count now use the same set the map does. Unplanned deliberately
stays trip-wide: a place assigned to some other day is planned, whichever day happens
to be open.

A note under the tabs says so and closes the day when dismissed. It sits there rather
than over the map because a chip on the canvas is out of reach on a phone, which is
where this was reported from.
This commit is contained in:
Maurice
2026-09-09 15:21:20 +02:00
committed by Maurice
parent d30b916f9c
commit 756e0fb908
27 changed files with 230 additions and 9 deletions
@@ -288,6 +288,113 @@ describe('Filter tabs', () => {
expect(screen.getByText('Planned Place')).toBeInTheDocument();
expect(screen.queryByText('Unplanned Place')).not.toBeInTheDocument();
});
// ── The open day narrows the pool, and says so ──────────────────────────────
//
// The map has followed the selected day on this filter since #2024 while the list
// did not, so a trip with everything planned read "55" in the pool beside five pins
// on the map. Reported twice in the same Discord thread as the map being broken.
it('FE-PLANNER-SIDEBAR-052: with a day open, "Planned" shows that day, not the whole trip', () => {
const today = buildPlace({ id: 91, name: 'On This Day' });
const otherDay = buildPlace({ id: 92, name: 'On Another Day' });
const assignments = {
'1': [buildAssignment({ place: today, day_id: 1 })],
'2': [buildAssignment({ place: otherDay, day_id: 2 })],
};
seedStore(useTripStore, { placesFilter: 'planned' });
render(
<PlacesSidebar
{...defaultProps}
places={[today, otherDay]}
assignments={assignments}
days={[{ id: 1 }, { id: 2 }] as never}
selectedDayId={1}
/>,
);
expect(screen.getByText('On This Day')).toBeInTheDocument();
expect(screen.queryByText('On Another Day')).not.toBeInTheDocument();
});
it('FE-PLANNER-SIDEBAR-053: without a day open it is the whole trip again', () => {
const dayOne = buildPlace({ id: 91, name: 'On This Day' });
const dayTwo = buildPlace({ id: 92, name: 'On Another Day' });
const assignments = {
'1': [buildAssignment({ place: dayOne, day_id: 1 })],
'2': [buildAssignment({ place: dayTwo, day_id: 2 })],
};
seedStore(useTripStore, { placesFilter: 'planned' });
render(
<PlacesSidebar
{...defaultProps}
places={[dayOne, dayTwo]}
assignments={assignments}
days={[{ id: 1 }, { id: 2 }] as never}
selectedDayId={null}
/>,
);
expect(screen.getByText('On This Day')).toBeInTheDocument();
expect(screen.getByText('On Another Day')).toBeInTheDocument();
});
it('FE-PLANNER-SIDEBAR-054: the note only appears while the day is actually narrowing', () => {
const today = buildPlace({ id: 91, name: 'On This Day' });
const assignments = { '1': [buildAssignment({ place: today, day_id: 1 })] };
const onClearSelectedDay = vi.fn();
seedStore(useTripStore, { placesFilter: 'planned' });
const { rerender } = render(
<PlacesSidebar
{...defaultProps}
places={[today]}
assignments={assignments}
days={[{ id: 1 }] as never}
selectedDayId={1}
onClearSelectedDay={onClearSelectedDay}
/>,
);
expect(screen.getByText('Showing the open day only')).toBeInTheDocument();
// Dismissing it asks for the day to be closed rather than changing the filter.
fireEvent.click(screen.getByLabelText('Show the whole trip'));
expect(onClearSelectedDay).toHaveBeenCalledTimes(1);
// No day open, nothing narrowed, no note.
rerender(
<PlacesSidebar
{...defaultProps}
places={[today]}
assignments={assignments}
days={[{ id: 1 }] as never}
selectedDayId={null}
onClearSelectedDay={onClearSelectedDay}
/>,
);
expect(screen.queryByText('Showing the open day only')).not.toBeInTheDocument();
});
it('FE-PLANNER-SIDEBAR-055: "Unplanned" stays trip-wide while a day is open', () => {
// A place assigned to some other day is planned, whichever day happens to be open,
// so it must not reappear in the unplanned pool.
const otherDay = buildPlace({ id: 92, name: 'On Another Day' });
const loose = buildPlace({ id: 93, name: 'Not Planned At All' });
const assignments = { '2': [buildAssignment({ place: otherDay, day_id: 2 })] };
seedStore(useTripStore, { placesFilter: 'unplanned' });
render(
<PlacesSidebar
{...defaultProps}
places={[otherDay, loose]}
assignments={assignments}
days={[{ id: 1 }, { id: 2 }] as never}
selectedDayId={1}
/>,
);
expect(screen.getByText('Not Planned At All')).toBeInTheDocument();
expect(screen.queryByText('On Another Day')).not.toBeInTheDocument();
expect(screen.queryByText('Showing the open day only')).not.toBeInTheDocument();
});
});
// ── Search ────────────────────────────────────────────────────────────────────
@@ -1,4 +1,4 @@
import { Search, Plus, X, Upload, FileDown, ChevronDown, Check, MapPin, Star, CalendarPlus } from 'lucide-react'
import { Search, Plus, X, Upload, FileDown, ChevronDown, Check, MapPin, Star, CalendarPlus, CalendarDays } from 'lucide-react'
import { getCategoryIcon } from '../shared/categoryIcons'
import Tooltip from '../shared/Tooltip'
import { useElementSize } from '../../hooks/useElementSize'
@@ -32,7 +32,7 @@ export function PlacesDropOverlay({ t }: SidebarState) {
export function PlacesHeader(S: SidebarState) {
const {
canEditPlaces, onAddPlace, onAddPlaceToSelectedDay, selectedDayId, t, setFileImportOpen, setListImportOpen, hasMultipleListImportProviders,
places, categories, categoryFilters, search, setSearch, plannedIds, hasTracks,
places, categories, categoryFilters, search, setSearch, plannedIds, plannedFilterIds, dayScoped, onClearSelectedDay, hasTracks,
filter, setFilter, setSelectedIds, selectMode, setSelectMode,
catDropOpen, setCatDropOpen, toggleCategoryFilter, setCategoryFilters,
ratingFilter, setRatingFilter,
@@ -163,7 +163,11 @@ export function PlacesHeader(S: SidebarState) {
const counts = {
all: baseFiltered.length,
unplanned: baseFiltered.filter(p => !plannedIds.has(p.id)).length,
planned: baseFiltered.filter(p => plannedIds.has(p.id)).length,
// While a day is open this counts that day's plan, the same set the list and
// the map show. Counting the whole trip here is what made the tab read 55
// beside five pins, with nothing to say the two were answering different
// questions.
planned: baseFiltered.filter(p => plannedFilterIds.has(p.id)).length,
tracks: baseFiltered.filter(p => p.route_geometry).length,
}
const tabs = ([
@@ -211,6 +215,42 @@ export function PlacesHeader(S: SidebarState) {
)
})()}
{/* Says out loud what the count above already narrowed to.
The map has followed the open day on this filter since #2024, and until now
nothing anywhere said so: the pool read 55, the map drew five, and the honest
conclusion was that the map was broken. It sits under the tabs rather than on
the map because a chip over the canvas is unreachable on a phone, which is
where this was reported from. */}
{dayScoped && (
<div
className="border border-edge-faint bg-surface-tertiary text-content-secondary"
style={{
display: 'flex', alignItems: 'center', gap: 6,
padding: '4px 6px 4px 9px', borderRadius: 8, marginBottom: 8,
fontSize: 'calc(11px * var(--fs-scale-caption, 1))',
}}
>
<CalendarDays size={11} strokeWidth={2} style={{ flexShrink: 0 }} />
<span style={{ minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
{t('places.dayScoped')}
</span>
{onClearSelectedDay && (
<button type="button"
onClick={onClearSelectedDay}
aria-label={t('places.dayScopedClear')}
title={t('places.dayScopedClear')}
className="text-content-faint hover:text-content"
style={{
marginInlineStart: 'auto', display: 'flex', alignItems: 'center',
background: 'none', border: 'none', padding: 3, cursor: 'pointer', flexShrink: 0,
}}
>
<X size={12} strokeWidth={2.2} />
</button>
)}
</div>
)}
{/* Suchfeld */}
<div style={{ position: 'relative' }}>
<Search size={13} strokeWidth={1.8} color="var(--text-faint)" style={{ position: 'absolute', left: 10, top: '50%', transform: 'translateY(-50%)', pointerEvents: 'none' }} />
@@ -15,7 +15,7 @@ import { placeToSaveTarget } from '../Collections/saveTarget'
import type { Place, Category, Day, AssignmentsMap } from '../../types'
import { getGoogleMapsUrlForPlace } from './placeGoogleMaps'
import { safeHttpUrl } from '../../utils/safeUrl'
import { plannedPlaceIds, type PlannedAccommodation } from '../../utils/plannedPlaces'
import { plannedPlaceIds, plannedPlaceIdsForDay, type PlannedAccommodation } from '../../utils/plannedPlaces'
/** Stable identity — a fresh [] default would invalidate the planned memo on every render. */
const NO_ACCOMMODATIONS: PlannedAccommodation[] = []
@@ -40,6 +40,12 @@ export interface PlacesSidebarProps {
* through the day picker.
*/
onAddPlaceToSelectedDay?: () => void
/**
* Close the open day, from the note that says the pool is showing only that day.
* Absent leaves the note without its dismiss, which is what the mobile day picker
* wants: there the day is closed by the picker itself.
*/
onClearSelectedDay?: () => void
onAssignToDay: (placeId: number, dayId: number) => void
onEditPlace: (place: Place) => void
onDeletePlace: (placeId: number) => void
@@ -60,7 +66,7 @@ export interface PlacesSidebarProps {
*/
export function usePlacesSidebar(props: PlacesSidebarProps) {
const {
tripId, places, assignments, selectedDayId, accommodations = NO_ACCOMMODATIONS,
tripId, places, assignments, selectedDayId, days, accommodations = NO_ACCOMMODATIONS,
pushUndo, initialScrollTop, onScrollTopChange,
} = props
const { t } = useTranslation()
@@ -238,10 +244,30 @@ export function usePlacesSidebar(props: PlacesSidebarProps) {
[assignments, accommodations, reservations],
)
/**
* What "planned" means while a day is open: that day's plan, not the whole trip's.
*
* The map has narrowed to the selected day since #2024, and the list did not, which is
* how a trip with 55 planned places showed 55 in the pool and five pins on the map with
* nothing to explain the gap — read, reasonably, as the map being broken. The list now
* follows the map, and `dayScoped` tells the header to say so.
*
* Only "planned" narrows. "Unplanned" stays trip-wide on purpose: a place assigned to
* some other day is planned, whichever day happens to be open.
*/
const plannedInDayIds = useMemo(
() => (selectedDayId
? plannedPlaceIdsForDay(selectedDayId, days, { assignments, accommodations, reservations })
: null),
[selectedDayId, days, assignments, accommodations, reservations],
)
const plannedFilterIds = plannedInDayIds ?? plannedIds
const dayScoped = filter === 'planned' && plannedInDayIds !== null
const filtered = useMemo(() => {
const list = places.filter(p => {
if (filter === 'unplanned' && plannedIds.has(p.id)) return false
if (filter === 'planned' && !plannedIds.has(p.id)) return false
if (filter === 'planned' && !plannedFilterIds.has(p.id)) return false
if (filter === 'tracks' && !p.route_geometry) return false
if (categoryFilters.size > 0) {
if (p.category_id == null) {
@@ -254,7 +280,7 @@ export function usePlacesSidebar(props: PlacesSidebarProps) {
return true
})
return list
}, [places, filter, categoryFilters, search, plannedIds, ratingFilter])
}, [places, filter, categoryFilters, search, plannedIds, plannedFilterIds, ratingFilter])
const registerPlaceRow = useCallback((placeId: number, element: HTMLDivElement | null) => {
if (element) {
@@ -322,7 +348,7 @@ export function usePlacesSidebar(props: PlacesSidebarProps) {
markSelectionVisited, markVisitedBusy,
exitSelectMode, toggleSelected, toggleCategoryFilter, dayPickerPlace, setDayPickerPlace,
catDropOpen, setCatDropOpen, mobileShowDays, setMobileShowDays,
hasTracks, plannedIds, filtered, registerPlaceRow, isAssignedToSelectedDay, inDaySet, openContextMenu,
hasTracks, plannedIds, plannedFilterIds, dayScoped, filtered, registerPlaceRow, isAssignedToSelectedDay, inDaySet, openContextMenu,
}
}
+2 -1
View File
@@ -685,6 +685,7 @@ function TripPlannerPageDesktop(): React.ReactElement | null {
assignments={assignments}
accommodations={tripAccommodations}
selectedDayId={selectedDayId}
onClearSelectedDay={() => handleSelectDay(null)}
selectedPlaceId={selectedPlaceId}
onPlaceClick={handlePlaceClick}
onAddPlace={() => { setEditingPlace(null); setPlaceFormDayId(null); setShowPlaceForm(true) }}
@@ -852,7 +853,7 @@ function TripPlannerPageDesktop(): React.ReactElement | null {
<div style={{ flex: 1, overflow: 'auto', paddingBottom: 'env(safe-area-inset-bottom, 0px)' }}>
{mobileSidebarOpen === 'left'
? <DayPlanSidebar tripId={tripId} trip={trip} days={days} places={places} categories={categories} assignments={assignments} selectedDayId={selectedDayId} selectedPlaceId={selectedPlaceId} selectedAssignmentId={selectedAssignmentId} onSelectDay={(id) => { handleSelectDay(id); setMobileSidebarOpen(null) }} onPlaceClick={(placeId, assignmentId) => { handlePlaceClick(placeId, assignmentId) }} onReorder={handleReorder} onReorderDays={handleReorderDays} onAddDay={handleAddDay} onUpdateDayTitle={handleUpdateDayTitle} onAssignToDay={handleAssignToDay} onRouteCalculated={(r) => { if (r) { setRoute([r.coordinates]); setRouteInfo(r) } else { setRoute(null); setRouteInfo(null) } }} reservations={reservations} visibleConnectionIds={visibleConnections} onToggleConnection={toggleConnection} allConnectionsShown={allConnectionsShown} onToggleAllConnections={toggleAllConnections} onAddReservation={(dayId) => { setEditingReservation(null); tripActions.setSelectedDay(dayId); setShowReservationModal(true); setMobileSidebarOpen(null) }} onAddTransport={can('day_edit', trip) ? (dayId) => { setTransportModalDayId(dayId); setEditingTransport(null); setTransitPrefill(null); setTransportModalAutomated(false); setShowTransportModal(true); setMobileSidebarOpen(null) } : undefined} onOpenTransit={(r) => { setTransitJourney(r); setMobileSidebarOpen(null) }} onPlanTransit={can('day_edit', trip) && tripHasDates ? (dayId) => { setTransportModalDayId(dayId); setEditingTransport(null); setTransitPrefill(null); setTransportModalAutomated(true); setShowTransportModal(true); setMobileSidebarOpen(null) } : undefined} onPlanTransitLeg={can('day_edit', trip) && tripHasDates ? ({ dayId, from, to, time }) => { setTransportModalDayId(dayId); setEditingTransport(null); setTransitPrefill({ from, to, time }); setTransportModalAutomated(true); setShowTransportModal(true); setMobileSidebarOpen(null) } : undefined} onAddPlace={() => { setEditingPlace(null); setPlaceFormDayId(null); setShowPlaceForm(true); setMobileSidebarOpen(null) }} onCreatePlaceForDay={can('place_edit', trip) ? (dayId) => { setEditingPlace(null); setPlaceFormDayId(dayId); setShowPlaceForm(true); setMobileSidebarOpen(null) } : undefined} onDayDetail={(day) => { setShowDayDetail(day); setSelectedPlaceId(null); selectAssignment(null) }} onRemoveAssignment={handleRemoveAssignment} onEditPlace={(place, assignmentId) => { setEditingPlace(place); setEditingAssignmentId(assignmentId || null); setPlaceFormDayId(null); setShowPlaceForm(true); setMobileSidebarOpen(null) }} onDeletePlace={(placeId) => handleDeletePlace(placeId)} accommodations={tripAccommodations} routeShown={routeShown} routeProfile={routeProfile} onToggleRoute={() => setRouteShown(v => !v)} onSetRouteProfile={setRouteProfile} onNavigateToFiles={() => { setMobileSidebarOpen(null); handleTabChange('dateien') }} onExpandedDaysChange={setExpandedDayIds} pushUndo={pushUndo} canUndo={canUndo} lastActionLabel={lastActionLabel} onUndo={handleUndo} onEditTransport={can('day_edit', trip) ? (reservation) => { setEditingTransport(reservation); setTransportModalDayId(reservation.day_id ?? null); setShowTransportModal(true); setMobileSidebarOpen(null) } : undefined} onEditReservation={can('reservation_edit', trip) ? (r) => { setEditingReservation(r); setShowReservationModal(true); setMobileSidebarOpen(null) } : undefined} initialScrollTop={mobilePlanScrollTopRef.current} onScrollTopChange={(top) => { mobilePlanScrollTopRef.current = top }} showRouteToolsWhenExpanded isMobile />
: <PlacesSidebar tripId={tripId} places={places} categories={categories} assignments={assignments} accommodations={tripAccommodations} selectedDayId={selectedDayId} selectedPlaceId={selectedPlaceId} onPlaceClick={(placeId) => { handlePlaceClick(placeId); setMobileSidebarOpen(null) }} onAddPlace={() => { setEditingPlace(null); setPlaceFormDayId(null); setShowPlaceForm(true); setMobileSidebarOpen(null) }} onAssignToDay={handleAssignToDay} onEditPlace={(place) => { openPlaceEditor(place); setMobileSidebarOpen(null) }} onDeletePlace={(placeId) => handleDeletePlace(placeId)} onBulkDeletePlaces={(ids) => setDeletePlaceIds(ids)} onBulkDeleteConfirm={(ids) => confirmDeletePlaces(ids)} onBulkChangeCategory={(ids, catId) => confirmChangeCategory(ids, catId)} days={days} isMobile pushUndo={pushUndo} initialScrollTop={mobilePlacesScrollTopRef.current} onScrollTopChange={(top) => { mobilePlacesScrollTopRef.current = top }} />
: <PlacesSidebar tripId={tripId} places={places} categories={categories} assignments={assignments} accommodations={tripAccommodations} selectedDayId={selectedDayId} onClearSelectedDay={() => handleSelectDay(null)} selectedPlaceId={selectedPlaceId} onPlaceClick={(placeId) => { handlePlaceClick(placeId); setMobileSidebarOpen(null) }} onAddPlace={() => { setEditingPlace(null); setPlaceFormDayId(null); setShowPlaceForm(true); setMobileSidebarOpen(null) }} onAssignToDay={handleAssignToDay} onEditPlace={(place) => { openPlaceEditor(place); setMobileSidebarOpen(null) }} onDeletePlace={(placeId) => handleDeletePlace(placeId)} onBulkDeletePlaces={(ids) => setDeletePlaceIds(ids)} onBulkDeleteConfirm={(ids) => confirmDeletePlaces(ids)} onBulkChangeCategory={(ids, catId) => confirmChangeCategory(ids, catId)} days={days} isMobile pushUndo={pushUndo} initialScrollTop={mobilePlacesScrollTopRef.current} onScrollTopChange={(top) => { mobilePlacesScrollTopRef.current = top }} />
}
</div>
</div>
+2
View File
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
'places.all': 'الكل',
'places.unplanned': 'غير مخطط',
'places.planned': 'مخطط لها',
'places.dayScoped': 'يظهر اليوم المفتوح فقط',
'places.dayScopedClear': 'عرض الرحلة كاملة',
'places.filterTracks': 'المسارات',
'places.filterByRating': 'تصفية حسب التقييم',
'places.yourRating': 'تقييمك',
+2
View File
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
'places.all': 'Todos',
'places.unplanned': 'Não planejados',
'places.planned': 'Planejados',
'places.dayScoped': 'Mostrando apenas o dia aberto',
'places.dayScopedClear': 'Mostrar a viagem inteira',
'places.filterTracks': 'Trilhas',
'places.filterByRating': 'Filtrar por avaliação',
'places.yourRating': 'Sua avaliação',
+2
View File
@@ -46,6 +46,8 @@ const places: TranslationStrings = {
'places.all': 'Tot',
'places.unplanned': 'Sense planificar',
'places.planned': 'Planificats',
'places.dayScoped': 'Es mostra només el dia obert',
'places.dayScopedClear': 'Mostra tot el viatge',
'places.filterTracks': 'Rutes',
'places.filterByRating': 'Filtra per valoració',
'places.yourRating': 'La teva valoració',
+2
View File
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
'places.all': 'Vše',
'places.unplanned': 'Nezařazené',
'places.planned': 'Naplánované',
'places.dayScoped': 'Zobrazuje se jen otevřený den',
'places.dayScopedClear': 'Zobrazit celou cestu',
'places.filterTracks': 'Trasy',
'places.filterByRating': 'Filtrovat podle hodnocení',
'places.yourRating': 'Tvé hodnocení',
+2
View File
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
'places.all': 'Alle',
'places.unplanned': 'Ungeplant',
'places.planned': 'Geplant',
'places.dayScoped': 'Nur der geöffnete Tag wird angezeigt',
'places.dayScopedClear': 'Ganze Reise anzeigen',
'places.filterTracks': 'Tracks',
'places.filterByRating': 'Nach Bewertung filtern',
'places.yourRating': 'Deine Bewertung',
+3
View File
@@ -48,6 +48,9 @@ const places: TranslationStrings = {
'places.all': 'All',
'places.unplanned': 'Unplanned',
'places.planned': 'Planned',
/** Shown under the filter tabs while an open day narrows both the list and the map. */
'places.dayScoped': 'Showing the open day only',
'places.dayScopedClear': 'Show the whole trip',
'places.filterTracks': 'Tracks',
'places.filterByRating': 'Filter by rating',
'places.yourRating': 'Your rating',
+2
View File
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
'places.all': 'Todo',
'places.unplanned': 'Sin planificar',
'places.planned': 'Planificados',
'places.dayScoped': 'Se muestra solo el día abierto',
'places.dayScopedClear': 'Mostrar todo el viaje',
'places.filterTracks': 'Rutas',
'places.filterByRating': 'Filtrar por valoración',
'places.yourRating': 'Tu valoración',
+2
View File
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
'places.all': 'Tous',
'places.unplanned': 'Non planifiés',
'places.planned': 'Planifiés',
'places.dayScoped': 'Seul le jour ouvert est affiché',
'places.dayScopedClear': 'Afficher tout le voyage',
'places.filterTracks': 'Traces',
'places.filterByRating': 'Filtrer par note',
'places.yourRating': 'Ta note',
+2
View File
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
'places.all': 'Όλα',
'places.unplanned': 'Μη προγραμματισμένα',
'places.planned': 'Προγραμματισμένα',
'places.dayScoped': 'Εμφανίζεται μόνο η ανοιχτή ημέρα',
'places.dayScopedClear': 'Εμφάνιση όλου του ταξιδιού',
'places.filterTracks': 'Ίχνη',
'places.filterByRating': 'Φιλτράρισμα κατά βαθμολογία',
'places.yourRating': 'Η βαθμολογία σου',
+2
View File
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
'places.all': 'Összes',
'places.unplanned': 'Nem tervezett',
'places.planned': 'Tervezett',
'places.dayScoped': 'Csak a megnyitott nap látszik',
'places.dayScopedClear': 'Teljes utazás megjelenítése',
'places.filterTracks': 'Nyomvonalak',
'places.filterByRating': 'Szűrés értékelés szerint',
'places.yourRating': 'Az értékelésed',
+2
View File
@@ -47,6 +47,8 @@ const places: TranslationStrings = {
'places.all': 'Semua',
'places.unplanned': 'Belum direncanakan',
'places.planned': 'Direncanakan',
'places.dayScoped': 'Hanya menampilkan hari yang dibuka',
'places.dayScopedClear': 'Tampilkan seluruh perjalanan',
'places.filterTracks': 'Trek',
'places.filterByRating': 'Saring menurut penilaian',
'places.yourRating': 'Rating kamu',
+2
View File
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
'places.all': 'Tutti',
'places.unplanned': 'Non pianificati',
'places.planned': 'Pianificati',
'places.dayScoped': 'Viene mostrato solo il giorno aperto',
'places.dayScopedClear': 'Mostra tutto il viaggio',
'places.filterTracks': 'Tracce',
'places.filterByRating': 'Filtra per valutazione',
'places.yourRating': 'La tua valutazione',
+2
View File
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
'places.all': 'すべて',
'places.unplanned': '未計画',
'places.planned': '計画済み',
'places.dayScoped': '開いている日のみ表示中',
'places.dayScopedClear': '旅行全体を表示',
'places.filterTracks': 'トラック',
'places.filterByRating': '評価で絞り込む',
'places.yourRating': 'あなたの評価',
+2
View File
@@ -47,6 +47,8 @@ const places: TranslationStrings = {
'places.all': '전체',
'places.unplanned': '미계획',
'places.planned': '계획됨',
'places.dayScoped': '열린 날짜만 표시 중',
'places.dayScopedClear': '전체 여행 보기',
'places.filterTracks': '트랙',
'places.filterByRating': '평점으로 필터링',
'places.yourRating': '내 평점',
+2
View File
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
'places.all': 'Alle',
'places.unplanned': 'Ongepland',
'places.planned': 'Gepland',
'places.dayScoped': 'Alleen de geopende dag wordt getoond',
'places.dayScopedClear': 'Hele reis tonen',
'places.filterTracks': 'Tracks',
'places.filterByRating': 'Filteren op beoordeling',
'places.yourRating': 'Jouw beoordeling',
+2
View File
@@ -38,6 +38,8 @@ const places: TranslationStrings = {
'places.all': 'Wszystkie',
'places.unplanned': 'Niezaplanowane',
'places.planned': 'Zaplanowane',
'places.dayScoped': 'Widoczny tylko otwarty dzień',
'places.dayScopedClear': 'Pokaż całą podróż',
'places.filterTracks': 'Trasy',
'places.filterByRating': 'Filtruj według oceny',
'places.yourRating': 'Twoja ocena',
+2
View File
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
'places.all': 'Все',
'places.unplanned': 'Незапланированные',
'places.planned': 'Запланированные',
'places.dayScoped': 'Показан только открытый день',
'places.dayScopedClear': 'Показать всю поездку',
'places.filterTracks': 'Треки',
'places.filterByRating': 'Фильтр по оценке',
'places.yourRating': 'Твоя оценка',
+2
View File
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
'places.all': 'Alla',
'places.unplanned': 'Oplanerat',
'places.planned': 'Planerat',
'places.dayScoped': 'Visar bara den öppna dagen',
'places.dayScopedClear': 'Visa hela resan',
'places.filterTracks': 'Spår',
'places.filterByRating': 'Filtrera efter betyg',
'places.yourRating': 'Ditt betyg',
+2
View File
@@ -50,6 +50,8 @@ const places: TranslationStrings = {
'places.all': 'Tüm',
'places.unplanned': 'Planlanmamış',
'places.planned': 'Planlanmış',
'places.dayScoped': 'Yalnızca açık gün gösteriliyor',
'places.dayScopedClear': 'Tüm yolculuğu göster',
'places.filterTracks': 'Parçalar',
'places.filterByRating': 'Puana göre filtrele',
'places.yourRating': 'Senin puanın',
+2
View File
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
'places.all': 'Усі',
'places.unplanned': 'Незаплановані',
'places.planned': 'Заплановані',
'places.dayScoped': 'Показано лише відкритий день',
'places.dayScopedClear': 'Показати всю подорож',
'places.filterTracks': 'Треки',
'places.filterByRating': 'Фільтр за оцінкою',
'places.yourRating': 'Твоя оцінка',
+2
View File
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
'places.all': 'Tất cả',
'places.unplanned': 'Không có kế hoạch',
'places.planned': 'Có kế hoạch',
'places.dayScoped': 'Chỉ hiển thị ngày đang mở',
'places.dayScopedClear': 'Hiện toàn bộ chuyến đi',
'places.filterTracks': 'Bài hát',
'places.filterByRating': 'Lọc theo đánh giá',
'places.yourRating': 'Đánh giá của bạn',
+2
View File
@@ -47,6 +47,8 @@ const places: TranslationStrings = {
'places.all': '全部',
'places.unplanned': '未規劃',
'places.planned': '已規劃',
'places.dayScoped': '僅顯示目前開啟的日期',
'places.dayScopedClear': '顯示整趟行程',
'places.filterTracks': '路線',
'places.filterByRating': '依評分篩選',
'places.yourRating': '你的評分',
+2
View File
@@ -47,6 +47,8 @@ const places: TranslationStrings = {
'places.all': '全部',
'places.unplanned': '未规划',
'places.planned': '已规划',
'places.dayScoped': '仅显示当前打开的日期',
'places.dayScopedClear': '显示整个行程',
'places.filterTracks': '路线',
'places.filterByRating': '按评分筛选',
'places.yourRating': '你的评分',