mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
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:
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
|
||||
'places.all': 'الكل',
|
||||
'places.unplanned': 'غير مخطط',
|
||||
'places.planned': 'مخطط لها',
|
||||
'places.dayScoped': 'يظهر اليوم المفتوح فقط',
|
||||
'places.dayScopedClear': 'عرض الرحلة كاملة',
|
||||
'places.filterTracks': 'المسارات',
|
||||
'places.filterByRating': 'تصفية حسب التقييم',
|
||||
'places.yourRating': 'تقييمك',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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ó',
|
||||
|
||||
@@ -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í',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
|
||||
'places.all': 'Όλα',
|
||||
'places.unplanned': 'Μη προγραμματισμένα',
|
||||
'places.planned': 'Προγραμματισμένα',
|
||||
'places.dayScoped': 'Εμφανίζεται μόνο η ανοιχτή ημέρα',
|
||||
'places.dayScopedClear': 'Εμφάνιση όλου του ταξιδιού',
|
||||
'places.filterTracks': 'Ίχνη',
|
||||
'places.filterByRating': 'Φιλτράρισμα κατά βαθμολογία',
|
||||
'places.yourRating': 'Η βαθμολογία σου',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
|
||||
'places.all': 'すべて',
|
||||
'places.unplanned': '未計画',
|
||||
'places.planned': '計画済み',
|
||||
'places.dayScoped': '開いている日のみ表示中',
|
||||
'places.dayScopedClear': '旅行全体を表示',
|
||||
'places.filterTracks': 'トラック',
|
||||
'places.filterByRating': '評価で絞り込む',
|
||||
'places.yourRating': 'あなたの評価',
|
||||
|
||||
@@ -47,6 +47,8 @@ const places: TranslationStrings = {
|
||||
'places.all': '전체',
|
||||
'places.unplanned': '미계획',
|
||||
'places.planned': '계획됨',
|
||||
'places.dayScoped': '열린 날짜만 표시 중',
|
||||
'places.dayScopedClear': '전체 여행 보기',
|
||||
'places.filterTracks': '트랙',
|
||||
'places.filterByRating': '평점으로 필터링',
|
||||
'places.yourRating': '내 평점',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
|
||||
'places.all': 'Все',
|
||||
'places.unplanned': 'Незапланированные',
|
||||
'places.planned': 'Запланированные',
|
||||
'places.dayScoped': 'Показан только открытый день',
|
||||
'places.dayScopedClear': 'Показать всю поездку',
|
||||
'places.filterTracks': 'Треки',
|
||||
'places.filterByRating': 'Фильтр по оценке',
|
||||
'places.yourRating': 'Твоя оценка',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -48,6 +48,8 @@ const places: TranslationStrings = {
|
||||
'places.all': 'Усі',
|
||||
'places.unplanned': 'Незаплановані',
|
||||
'places.planned': 'Заплановані',
|
||||
'places.dayScoped': 'Показано лише відкритий день',
|
||||
'places.dayScopedClear': 'Показати всю подорож',
|
||||
'places.filterTracks': 'Треки',
|
||||
'places.filterByRating': 'Фільтр за оцінкою',
|
||||
'places.yourRating': 'Твоя оцінка',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -47,6 +47,8 @@ const places: TranslationStrings = {
|
||||
'places.all': '全部',
|
||||
'places.unplanned': '未規劃',
|
||||
'places.planned': '已規劃',
|
||||
'places.dayScoped': '僅顯示目前開啟的日期',
|
||||
'places.dayScopedClear': '顯示整趟行程',
|
||||
'places.filterTracks': '路線',
|
||||
'places.filterByRating': '依評分篩選',
|
||||
'places.yourRating': '你的評分',
|
||||
|
||||
@@ -47,6 +47,8 @@ const places: TranslationStrings = {
|
||||
'places.all': '全部',
|
||||
'places.unplanned': '未规划',
|
||||
'places.planned': '已规划',
|
||||
'places.dayScoped': '仅显示当前打开的日期',
|
||||
'places.dayScopedClear': '显示整个行程',
|
||||
'places.filterTracks': '路线',
|
||||
'places.filterByRating': '按评分筛选',
|
||||
'places.yourRating': '你的评分',
|
||||
|
||||
Reference in New Issue
Block a user