mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-19 13:21:46 +00:00
feat(transport): add bus, taxi, bicycle, ferry and other transport types (#1105)
Closes #718. Adds five new transport reservation types alongside the existing flight/train/car/cruise: bus, taxi, bicycle, ferry and a generic 'transport_other' catch-all. The new types are treated as first-class transports everywhere — the transport modal, day plan, route calculation, map overlays, file grouping and the PDF export — and are translated across all 20 locales. A dedicated 'transport_other' value is used for the catch-all so existing 'other' bookings are not reclassified as transport.
This commit is contained in:
@@ -1 +1 @@
|
|||||||
export const TRANSPORT_TYPES = new Set(['flight', 'train', 'car', 'cruise'])
|
export const TRANSPORT_TYPES = new Set(['flight', 'train', 'bus', 'car', 'taxi', 'bicycle', 'cruise', 'ferry', 'transport_other'])
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { FileText, FileImage, File, Plane, Train, Car, Ship } from 'lucide-react'
|
import { FileText, FileImage, File, Plane, Train, Car, Ship, Bus, Sailboat, Bike, CarTaxiFront, Route } from 'lucide-react'
|
||||||
import { downloadFile } from '../../utils/fileDownload'
|
import { downloadFile } from '../../utils/fileDownload'
|
||||||
|
|
||||||
export function isImage(mimeType?: string | null) {
|
export function isImage(mimeType?: string | null) {
|
||||||
@@ -33,7 +33,12 @@ export function formatDateWithLocale(dateStr?: string | null, locale?: string) {
|
|||||||
|
|
||||||
export function transportIcon(type: string) {
|
export function transportIcon(type: string) {
|
||||||
if (type === 'train') return Train
|
if (type === 'train') return Train
|
||||||
|
if (type === 'bus') return Bus
|
||||||
if (type === 'car') return Car
|
if (type === 'car') return Car
|
||||||
|
if (type === 'taxi') return CarTaxiFront
|
||||||
|
if (type === 'bicycle') return Bike
|
||||||
if (type === 'cruise') return Ship
|
if (type === 'cruise') return Ship
|
||||||
|
if (type === 'ferry') return Sailboat
|
||||||
|
if (type === 'transport_other') return Route
|
||||||
return Plane
|
return Plane
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { createElement, useEffect, useMemo, useRef, useState } from 'react'
|
|||||||
import { renderToStaticMarkup } from 'react-dom/server'
|
import { renderToStaticMarkup } from 'react-dom/server'
|
||||||
import { Marker, Polyline, Tooltip, useMap, useMapEvents } from 'react-leaflet'
|
import { Marker, Polyline, Tooltip, useMap, useMapEvents } from 'react-leaflet'
|
||||||
import L from 'leaflet'
|
import L from 'leaflet'
|
||||||
import { Plane, Train, Ship, Car } from 'lucide-react'
|
import { Plane, Train, Ship, Car, Bus, Sailboat, Bike, CarTaxiFront, Route } from 'lucide-react'
|
||||||
import { useSettingsStore } from '../../store/settingsStore'
|
import { useSettingsStore } from '../../store/settingsStore'
|
||||||
import type { Reservation, ReservationEndpoint } from '../../types'
|
import type { Reservation, ReservationEndpoint } from '../../types'
|
||||||
|
|
||||||
@@ -10,8 +10,8 @@ const ENDPOINT_PANE = 'reservation-endpoints'
|
|||||||
const AIRPORT_BADGE_HALF_PX = 16
|
const AIRPORT_BADGE_HALF_PX = 16
|
||||||
const BADGE_GAP_PX = 5
|
const BADGE_GAP_PX = 5
|
||||||
|
|
||||||
type TransportType = 'flight' | 'train' | 'cruise' | 'car'
|
type TransportType = 'flight' | 'train' | 'cruise' | 'car' | 'bus' | 'taxi' | 'bicycle' | 'ferry' | 'transport_other'
|
||||||
const TRANSPORT_TYPES: TransportType[] = ['flight', 'train', 'cruise', 'car']
|
const TRANSPORT_TYPES: TransportType[] = ['flight', 'train', 'cruise', 'car', 'bus', 'taxi', 'bicycle', 'ferry', 'transport_other']
|
||||||
|
|
||||||
const TRANSPORT_COLOR = '#3b82f6'
|
const TRANSPORT_COLOR = '#3b82f6'
|
||||||
|
|
||||||
@@ -20,6 +20,11 @@ const TYPE_META: Record<TransportType, { color: string; icon: typeof Plane; geod
|
|||||||
train: { color: TRANSPORT_COLOR, icon: Train, geodesic: false },
|
train: { color: TRANSPORT_COLOR, icon: Train, geodesic: false },
|
||||||
cruise: { color: TRANSPORT_COLOR, icon: Ship, geodesic: true },
|
cruise: { color: TRANSPORT_COLOR, icon: Ship, geodesic: true },
|
||||||
car: { color: TRANSPORT_COLOR, icon: Car, geodesic: false },
|
car: { color: TRANSPORT_COLOR, icon: Car, geodesic: false },
|
||||||
|
bus: { color: TRANSPORT_COLOR, icon: Bus, geodesic: false },
|
||||||
|
taxi: { color: TRANSPORT_COLOR, icon: CarTaxiFront, geodesic: false },
|
||||||
|
bicycle: { color: TRANSPORT_COLOR, icon: Bike, geodesic: false },
|
||||||
|
ferry: { color: TRANSPORT_COLOR, icon: Sailboat, geodesic: true },
|
||||||
|
transport_other: { color: TRANSPORT_COLOR, icon: Route, geodesic: false },
|
||||||
}
|
}
|
||||||
|
|
||||||
function useEndpointPane() {
|
function useEndpointPane() {
|
||||||
|
|||||||
@@ -9,14 +9,14 @@
|
|||||||
import { createElement } from 'react'
|
import { createElement } from 'react'
|
||||||
import { renderToStaticMarkup } from 'react-dom/server'
|
import { renderToStaticMarkup } from 'react-dom/server'
|
||||||
import mapboxgl from 'mapbox-gl'
|
import mapboxgl from 'mapbox-gl'
|
||||||
import { Plane, Train, Ship, Car } from 'lucide-react'
|
import { Plane, Train, Ship, Car, Bus, Sailboat, Bike, CarTaxiFront, Route } from 'lucide-react'
|
||||||
import type { Reservation, ReservationEndpoint } from '../../types'
|
import type { Reservation, ReservationEndpoint } from '../../types'
|
||||||
|
|
||||||
export const RESERVATION_SOURCE_ID = 'trek-reservations'
|
export const RESERVATION_SOURCE_ID = 'trek-reservations'
|
||||||
export const RESERVATION_LINE_LAYER_ID = 'trek-reservations-lines'
|
export const RESERVATION_LINE_LAYER_ID = 'trek-reservations-lines'
|
||||||
|
|
||||||
type TransportType = 'flight' | 'train' | 'cruise' | 'car'
|
type TransportType = 'flight' | 'train' | 'cruise' | 'car' | 'bus' | 'taxi' | 'bicycle' | 'ferry' | 'transport_other'
|
||||||
const TRANSPORT_TYPES: TransportType[] = ['flight', 'train', 'cruise', 'car']
|
const TRANSPORT_TYPES: TransportType[] = ['flight', 'train', 'cruise', 'car', 'bus', 'taxi', 'bicycle', 'ferry', 'transport_other']
|
||||||
const TRANSPORT_COLOR = '#3b82f6'
|
const TRANSPORT_COLOR = '#3b82f6'
|
||||||
|
|
||||||
const TYPE_META: Record<TransportType, { icon: typeof Plane; geodesic: boolean }> = {
|
const TYPE_META: Record<TransportType, { icon: typeof Plane; geodesic: boolean }> = {
|
||||||
@@ -24,6 +24,11 @@ const TYPE_META: Record<TransportType, { icon: typeof Plane; geodesic: boolean }
|
|||||||
train: { icon: Train, geodesic: false },
|
train: { icon: Train, geodesic: false },
|
||||||
cruise: { icon: Ship, geodesic: true },
|
cruise: { icon: Ship, geodesic: true },
|
||||||
car: { icon: Car, geodesic: false },
|
car: { icon: Car, geodesic: false },
|
||||||
|
bus: { icon: Bus, geodesic: false },
|
||||||
|
taxi: { icon: CarTaxiFront, geodesic: false },
|
||||||
|
bicycle: { icon: Bike, geodesic: false },
|
||||||
|
ferry: { icon: Sailboat, geodesic: true },
|
||||||
|
transport_other: { icon: Route, geodesic: false },
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── geometry helpers (ported from ReservationOverlay.tsx) ────────────────
|
// ── geometry helpers (ported from ReservationOverlay.tsx) ────────────────
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Trip PDF via browser print window
|
// Trip PDF via browser print window
|
||||||
import { createElement } from 'react'
|
import { createElement } from 'react'
|
||||||
import { getCategoryIcon } from '../shared/categoryIcons'
|
import { getCategoryIcon } from '../shared/categoryIcons'
|
||||||
import { FileText, Info, Clock, MapPin, Navigation, Train, Plane, Bus, Car, Ship, Coffee, Ticket, Star, Heart, Camera, Flag, Lightbulb, AlertTriangle, ShoppingBag, Bookmark, Hotel, LogIn, LogOut, KeyRound, BedDouble, Utensils, Users, LucideIcon } from 'lucide-react'
|
import { FileText, Info, Clock, MapPin, Navigation, Train, Plane, Bus, Car, Ship, Sailboat, Bike, CarTaxiFront, Route, Coffee, Ticket, Star, Heart, Camera, Flag, Lightbulb, AlertTriangle, ShoppingBag, Bookmark, Hotel, LogIn, LogOut, KeyRound, BedDouble, Utensils, Users, LucideIcon } from 'lucide-react'
|
||||||
import { accommodationsApi, mapsApi } from '../../api/client'
|
import { accommodationsApi, mapsApi } from '../../api/client'
|
||||||
import type { Trip, Day, Place, Category, AssignmentsMap, DayNote } from '../../types'
|
import type { Trip, Day, Place, Category, AssignmentsMap, DayNote } from '../../types'
|
||||||
import { isDayInAccommodationRange, getDayOrder } from '../../utils/dayOrder'
|
import { isDayInAccommodationRange, getDayOrder } from '../../utils/dayOrder'
|
||||||
@@ -20,8 +20,8 @@ function noteIconSvg(iconId) {
|
|||||||
return renderLucideIcon(Icon, { size: 14, strokeWidth: 1.8, color: '#94a3b8' })
|
return renderLucideIcon(Icon, { size: 14, strokeWidth: 1.8, color: '#94a3b8' })
|
||||||
}
|
}
|
||||||
|
|
||||||
const RESERVATION_ICON_MAP = { flight: Plane, train: Train, bus: Bus, car: Car, cruise: Ship, restaurant: Utensils, event: Ticket, tour: Users, other: FileText }
|
const RESERVATION_ICON_MAP = { flight: Plane, train: Train, bus: Bus, car: Car, taxi: CarTaxiFront, bicycle: Bike, cruise: Ship, ferry: Sailboat, transport_other: Route, restaurant: Utensils, event: Ticket, tour: Users, other: FileText }
|
||||||
const RESERVATION_COLOR_MAP = { flight: '#3b82f6', train: '#06b6d4', bus: '#6b7280', car: '#6b7280', cruise: '#0ea5e9', restaurant: '#ef4444', event: '#f59e0b', tour: '#10b981', other: '#6b7280' }
|
const RESERVATION_COLOR_MAP = { flight: '#3b82f6', train: '#06b6d4', bus: '#059669', car: '#6b7280', taxi: '#ca8a04', bicycle: '#84cc16', cruise: '#0ea5e9', ferry: '#0d9488', transport_other: '#6b7280', restaurant: '#ef4444', event: '#f59e0b', tour: '#10b981', other: '#6b7280' }
|
||||||
function reservationIconSvg(type) {
|
function reservationIconSvg(type) {
|
||||||
const Icon = RESERVATION_ICON_MAP[type] || Ticket
|
const Icon = RESERVATION_ICON_MAP[type] || Ticket
|
||||||
const color = RESERVATION_COLOR_MAP[type] || '#3b82f6'
|
const color = RESERVATION_COLOR_MAP[type] || '#3b82f6'
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
FileText, Info, Clock, MapPin, Navigation, Train, Plane, Bus, Car, Ship,
|
FileText, Info, Clock, MapPin, Navigation, Train, Plane, Bus, Car, Ship,
|
||||||
Coffee, Ticket, Star, Heart, Camera, Flag, Lightbulb, AlertTriangle,
|
Coffee, Ticket, Star, Heart, Camera, Flag, Lightbulb, AlertTriangle,
|
||||||
ShoppingBag, Bookmark, Hotel, Utensils, Users,
|
ShoppingBag, Bookmark, Hotel, Utensils, Users, Sailboat, Bike, CarTaxiFront, Route,
|
||||||
} from 'lucide-react'
|
} from 'lucide-react'
|
||||||
|
|
||||||
export const RES_ICONS = { flight: Plane, hotel: Hotel, restaurant: Utensils, train: Train, car: Car, cruise: Ship, event: Ticket, tour: Users, other: FileText }
|
export const RES_ICONS = { flight: Plane, hotel: Hotel, restaurant: Utensils, train: Train, car: Car, cruise: Ship, bus: Bus, ferry: Sailboat, bicycle: Bike, taxi: CarTaxiFront, transport_other: Route, event: Ticket, tour: Users, other: FileText }
|
||||||
|
|
||||||
export const NOTE_ICONS = [
|
export const NOTE_ICONS = [
|
||||||
{ id: 'FileText', Icon: FileText },
|
{ id: 'FileText', Icon: FileText },
|
||||||
@@ -33,7 +33,8 @@ export function getNoteIcon(iconId) { return NOTE_ICON_MAP[iconId] || FileText }
|
|||||||
|
|
||||||
export const TYPE_ICONS = {
|
export const TYPE_ICONS = {
|
||||||
flight: '✈️', hotel: '🏨', restaurant: '🍽️', train: '🚆',
|
flight: '✈️', hotel: '🏨', restaurant: '🍽️', train: '🚆',
|
||||||
car: '🚗', cruise: '🚢', event: '🎫', other: '📋',
|
car: '🚗', cruise: '🚢', bus: '🚌', ferry: '⛴️', bicycle: '🚲', taxi: '🚕',
|
||||||
|
transport_other: '🧭', event: '🎫', other: '📋',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TRANSPORT_DETAIL_COLORS = { flight: '#3b82f6', train: '#06b6d4', bus: '#f59e0b', car: '#6b7280', cruise: '#0ea5e9' }
|
export const TRANSPORT_DETAIL_COLORS = { flight: '#3b82f6', train: '#06b6d4', bus: '#059669', ferry: '#0d9488', bicycle: '#84cc16', taxi: '#ca8a04', car: '#6b7280', cruise: '#0ea5e9', transport_other: '#6b7280' }
|
||||||
|
|||||||
@@ -1608,7 +1608,7 @@ const DayPlanSidebar = React.memo(function DayPlanSidebar(props: DayPlanSidebarP
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{canEditDays && (() => {
|
{canEditDays && (() => {
|
||||||
const isTransport = ['flight','train','car','cruise','bus'].includes(res.type)
|
const isTransport = TRANSPORT_TYPES.has(res.type)
|
||||||
const handler = isTransport ? onEditTransport : onEditReservation
|
const handler = isTransport ? onEditTransport : onEditReservation
|
||||||
if (!handler) return null
|
if (!handler) return null
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { useSettingsStore } from '../../store/settingsStore'
|
|||||||
import { useToast } from '../shared/Toast'
|
import { useToast } from '../shared/Toast'
|
||||||
import { useTranslation } from '../../i18n'
|
import { useTranslation } from '../../i18n'
|
||||||
import {
|
import {
|
||||||
Plane, Hotel, Utensils, Train, Car, Ship, Ticket, FileText, MapPin,
|
Plane, Hotel, Utensils, Train, Car, Ship, Bus, Sailboat, Bike, CarTaxiFront, Route, Ticket, FileText, MapPin,
|
||||||
Calendar, Hash, CheckCircle2, Circle, Pencil, Trash2, Plus, ChevronDown, ChevronRight, Users,
|
Calendar, Hash, CheckCircle2, Circle, Pencil, Trash2, Plus, ChevronDown, ChevronRight, Users,
|
||||||
ExternalLink, BookMarked, Lightbulb, Link2, Clock, ArrowRight, AlertCircle,
|
ExternalLink, BookMarked, Lightbulb, Link2, Clock, ArrowRight, AlertCircle,
|
||||||
} from 'lucide-react'
|
} from 'lucide-react'
|
||||||
@@ -31,8 +31,13 @@ const TYPE_OPTIONS = [
|
|||||||
{ value: 'hotel', labelKey: 'reservations.type.hotel', Icon: Hotel, color: '#8b5cf6' },
|
{ value: 'hotel', labelKey: 'reservations.type.hotel', Icon: Hotel, color: '#8b5cf6' },
|
||||||
{ value: 'restaurant', labelKey: 'reservations.type.restaurant', Icon: Utensils, color: '#ef4444' },
|
{ value: 'restaurant', labelKey: 'reservations.type.restaurant', Icon: Utensils, color: '#ef4444' },
|
||||||
{ value: 'train', labelKey: 'reservations.type.train', Icon: Train, color: '#06b6d4' },
|
{ value: 'train', labelKey: 'reservations.type.train', Icon: Train, color: '#06b6d4' },
|
||||||
|
{ value: 'bus', labelKey: 'reservations.type.bus', Icon: Bus, color: '#059669' },
|
||||||
{ value: 'car', labelKey: 'reservations.type.car', Icon: Car, color: '#6b7280' },
|
{ value: 'car', labelKey: 'reservations.type.car', Icon: Car, color: '#6b7280' },
|
||||||
|
{ value: 'taxi', labelKey: 'reservations.type.taxi', Icon: CarTaxiFront, color: '#ca8a04' },
|
||||||
|
{ value: 'bicycle', labelKey: 'reservations.type.bicycle', Icon: Bike, color: '#84cc16' },
|
||||||
{ value: 'cruise', labelKey: 'reservations.type.cruise', Icon: Ship, color: '#0ea5e9' },
|
{ value: 'cruise', labelKey: 'reservations.type.cruise', Icon: Ship, color: '#0ea5e9' },
|
||||||
|
{ value: 'ferry', labelKey: 'reservations.type.ferry', Icon: Sailboat, color: '#0d9488' },
|
||||||
|
{ value: 'transport_other', labelKey: 'reservations.type.transport_other', Icon: Route, color: '#6b7280' },
|
||||||
{ value: 'event', labelKey: 'reservations.type.event', Icon: Ticket, color: '#f59e0b' },
|
{ value: 'event', labelKey: 'reservations.type.event', Icon: Ticket, color: '#f59e0b' },
|
||||||
{ value: 'tour', labelKey: 'reservations.type.tour', Icon: Users, color: '#10b981' },
|
{ value: 'tour', labelKey: 'reservations.type.tour', Icon: Users, color: '#10b981' },
|
||||||
{ value: 'other', labelKey: 'reservations.type.other', Icon: FileText, color: '#6b7280' },
|
{ value: 'other', labelKey: 'reservations.type.other', Icon: FileText, color: '#6b7280' },
|
||||||
@@ -104,7 +109,7 @@ function ReservationCard({ r, tripId, onEdit, onDelete, files = [], onNavigateTo
|
|||||||
const hasCode = !!r.confirmation_number
|
const hasCode = !!r.confirmation_number
|
||||||
const dateCols = [hasDate, hasTime, hasCode].filter(Boolean).length
|
const dateCols = [hasDate, hasTime, hasCode].filter(Boolean).length
|
||||||
|
|
||||||
const TRANSPORT_TYPES_SET = new Set(['flight', 'train', 'bus', 'car', 'cruise'])
|
const TRANSPORT_TYPES_SET = new Set(['flight', 'train', 'bus', 'car', 'taxi', 'bicycle', 'cruise', 'ferry', 'transport_other'])
|
||||||
const isTransportType = TRANSPORT_TYPES_SET.has(r.type)
|
const isTransportType = TRANSPORT_TYPES_SET.has(r.type)
|
||||||
const isHotel = r.type === 'hotel'
|
const isHotel = r.type === 'hotel'
|
||||||
const startDay = r.day_id ? days.find(d => d.id === r.day_id)
|
const startDay = r.day_id ? days.find(d => d.id === r.day_id)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useState, useEffect, useMemo, useRef } from 'react'
|
import { useState, useEffect, useMemo, useRef } from 'react'
|
||||||
import { useParams } from 'react-router-dom'
|
import { useParams } from 'react-router-dom'
|
||||||
import { Plane, Train, Car, Ship, Paperclip, FileText, X, ExternalLink, Link2 } from 'lucide-react'
|
import { Plane, Train, Car, Ship, Bus, Sailboat, Bike, CarTaxiFront, Route, Paperclip, FileText, X, ExternalLink, Link2 } from 'lucide-react'
|
||||||
import Modal from '../shared/Modal'
|
import Modal from '../shared/Modal'
|
||||||
import CustomSelect from '../shared/CustomSelect'
|
import CustomSelect from '../shared/CustomSelect'
|
||||||
import CustomTimePicker from '../shared/CustomTimePicker'
|
import CustomTimePicker from '../shared/CustomTimePicker'
|
||||||
@@ -15,7 +15,7 @@ import { openFile } from '../../utils/fileDownload'
|
|||||||
import apiClient from '../../api/client'
|
import apiClient from '../../api/client'
|
||||||
import type { Day, Reservation, ReservationEndpoint, TripFile } from '../../types'
|
import type { Day, Reservation, ReservationEndpoint, TripFile } from '../../types'
|
||||||
|
|
||||||
const TRANSPORT_TYPES = ['flight', 'train', 'car', 'cruise'] as const
|
const TRANSPORT_TYPES = ['flight', 'train', 'bus', 'car', 'taxi', 'bicycle', 'cruise', 'ferry', 'transport_other'] as const
|
||||||
type TransportType = typeof TRANSPORT_TYPES[number]
|
type TransportType = typeof TRANSPORT_TYPES[number]
|
||||||
|
|
||||||
interface EndpointPick {
|
interface EndpointPick {
|
||||||
@@ -64,10 +64,15 @@ function locationFromEndpoint(e: ReservationEndpoint | undefined): LocationPoint
|
|||||||
}
|
}
|
||||||
|
|
||||||
const TYPE_OPTIONS = [
|
const TYPE_OPTIONS = [
|
||||||
{ value: 'flight', labelKey: 'reservations.type.flight', Icon: Plane },
|
{ value: 'flight', labelKey: 'reservations.type.flight', Icon: Plane },
|
||||||
{ value: 'train', labelKey: 'reservations.type.train', Icon: Train },
|
{ value: 'train', labelKey: 'reservations.type.train', Icon: Train },
|
||||||
{ value: 'car', labelKey: 'reservations.type.car', Icon: Car },
|
{ value: 'bus', labelKey: 'reservations.type.bus', Icon: Bus },
|
||||||
{ value: 'cruise', labelKey: 'reservations.type.cruise', Icon: Ship },
|
{ value: 'car', labelKey: 'reservations.type.car', Icon: Car },
|
||||||
|
{ value: 'taxi', labelKey: 'reservations.type.taxi', Icon: CarTaxiFront },
|
||||||
|
{ value: 'bicycle', labelKey: 'reservations.type.bicycle', Icon: Bike },
|
||||||
|
{ value: 'cruise', labelKey: 'reservations.type.cruise', Icon: Ship },
|
||||||
|
{ value: 'ferry', labelKey: 'reservations.type.ferry', Icon: Sailboat },
|
||||||
|
{ value: 'transport_other', labelKey: 'reservations.type.transport_other', Icon: Route },
|
||||||
]
|
]
|
||||||
|
|
||||||
const defaultForm = {
|
const defaultForm = {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { calculateRouteWithLegs } from '../components/Map/RouteCalculator'
|
|||||||
import type { TripStoreState } from '../store/tripStore'
|
import type { TripStoreState } from '../store/tripStore'
|
||||||
import type { RouteSegment, RouteResult } from '../types'
|
import type { RouteSegment, RouteResult } from '../types'
|
||||||
|
|
||||||
const TRANSPORT_TYPES = ['flight', 'train', 'bus', 'car', 'cruise']
|
const TRANSPORT_TYPES = ['flight', 'train', 'bus', 'car', 'taxi', 'bicycle', 'cruise', 'ferry', 'transport_other']
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages route calculation state for a selected day. Extracts geo-coded waypoints from
|
* Manages route calculation state for a selected day. Extracts geo-coded waypoints from
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ export function useTripPlanner() {
|
|||||||
}).catch(() => {})
|
}).catch(() => {})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const TRANSPORT_TYPES = new Set(['flight', 'train', 'car', 'cruise', 'bus'])
|
const TRANSPORT_TYPES = new Set(['flight', 'train', 'bus', 'car', 'taxi', 'bicycle', 'cruise', 'ferry', 'transport_other'])
|
||||||
|
|
||||||
const TRIP_TABS = [
|
const TRIP_TABS = [
|
||||||
{ id: 'plan', label: t('trip.tabs.plan'), icon: Map },
|
{ id: 'plan', label: t('trip.tabs.plan'), icon: Map },
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export const TRANSPORT_TYPES = new Set(['flight', 'train', 'bus', 'car', 'cruise'])
|
export const TRANSPORT_TYPES = new Set(['flight', 'train', 'bus', 'car', 'taxi', 'bicycle', 'cruise', 'ferry', 'transport_other'])
|
||||||
|
|
||||||
export interface MergedItem {
|
export interface MergedItem {
|
||||||
type: 'place' | 'note' | 'transport'
|
type: 'place' | 'note' | 'transport'
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': 'فعالية',
|
'reservations.type.event': 'فعالية',
|
||||||
'reservations.type.tour': 'جولة',
|
'reservations.type.tour': 'جولة',
|
||||||
'reservations.type.other': 'أخرى',
|
'reservations.type.other': 'أخرى',
|
||||||
|
'reservations.type.bus': 'حافلة',
|
||||||
|
'reservations.type.ferry': 'عبّارة',
|
||||||
|
'reservations.type.bicycle': 'دراجة',
|
||||||
|
'reservations.type.taxi': 'سيارة أجرة',
|
||||||
|
'reservations.type.transport_other': 'أخرى',
|
||||||
'reservations.confirm.delete': 'هل تريد حذف الحجز "{name}"؟',
|
'reservations.confirm.delete': 'هل تريد حذف الحجز "{name}"؟',
|
||||||
'reservations.confirm.deleteTitle': 'حذف الحجز؟',
|
'reservations.confirm.deleteTitle': 'حذف الحجز؟',
|
||||||
'reservations.confirm.deleteBody': 'سيتم حذف "{name}" نهائيًا.',
|
'reservations.confirm.deleteBody': 'سيتم حذف "{name}" نهائيًا.',
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': 'Evento',
|
'reservations.type.event': 'Evento',
|
||||||
'reservations.type.tour': 'Passeio',
|
'reservations.type.tour': 'Passeio',
|
||||||
'reservations.type.other': 'Outro',
|
'reservations.type.other': 'Outro',
|
||||||
|
'reservations.type.bus': 'Ônibus',
|
||||||
|
'reservations.type.ferry': 'Balsa',
|
||||||
|
'reservations.type.bicycle': 'Bicicleta',
|
||||||
|
'reservations.type.taxi': 'Táxi',
|
||||||
|
'reservations.type.transport_other': 'Outro',
|
||||||
'reservations.confirm.delete':
|
'reservations.confirm.delete':
|
||||||
'Tem certeza de que deseja excluir a reserva "{name}"?',
|
'Tem certeza de que deseja excluir a reserva "{name}"?',
|
||||||
'reservations.confirm.deleteTitle': 'Excluir reserva?',
|
'reservations.confirm.deleteTitle': 'Excluir reserva?',
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': 'Událost',
|
'reservations.type.event': 'Událost',
|
||||||
'reservations.type.tour': 'Prohlídka',
|
'reservations.type.tour': 'Prohlídka',
|
||||||
'reservations.type.other': 'Jiné',
|
'reservations.type.other': 'Jiné',
|
||||||
|
'reservations.type.bus': 'Autobus',
|
||||||
|
'reservations.type.ferry': 'Trajekt',
|
||||||
|
'reservations.type.bicycle': 'Kolo',
|
||||||
|
'reservations.type.taxi': 'Taxi',
|
||||||
|
'reservations.type.transport_other': 'Ostatní',
|
||||||
'reservations.confirm.delete': 'Opravdu chcete smazat rezervaci „{name}”?',
|
'reservations.confirm.delete': 'Opravdu chcete smazat rezervaci „{name}”?',
|
||||||
'reservations.confirm.deleteTitle': 'Smazat rezervaci?',
|
'reservations.confirm.deleteTitle': 'Smazat rezervaci?',
|
||||||
'reservations.confirm.deleteBody': '„{name}” bude trvale smazána.',
|
'reservations.confirm.deleteBody': '„{name}” bude trvale smazána.',
|
||||||
|
|||||||
@@ -55,6 +55,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': 'Veranstaltung',
|
'reservations.type.event': 'Veranstaltung',
|
||||||
'reservations.type.tour': 'Tour',
|
'reservations.type.tour': 'Tour',
|
||||||
'reservations.type.other': 'Sonstiges',
|
'reservations.type.other': 'Sonstiges',
|
||||||
|
'reservations.type.bus': 'Bus',
|
||||||
|
'reservations.type.ferry': 'Fähre',
|
||||||
|
'reservations.type.bicycle': 'Fahrrad',
|
||||||
|
'reservations.type.taxi': 'Taxi',
|
||||||
|
'reservations.type.transport_other': 'Sonstiges',
|
||||||
'reservations.confirm.delete':
|
'reservations.confirm.delete':
|
||||||
'Möchtest du die Reservierung "{name}" wirklich löschen?',
|
'Möchtest du die Reservierung "{name}" wirklich löschen?',
|
||||||
'reservations.confirm.deleteTitle': 'Buchung löschen?',
|
'reservations.confirm.deleteTitle': 'Buchung löschen?',
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': 'Event',
|
'reservations.type.event': 'Event',
|
||||||
'reservations.type.tour': 'Tour',
|
'reservations.type.tour': 'Tour',
|
||||||
'reservations.type.other': 'Other',
|
'reservations.type.other': 'Other',
|
||||||
|
'reservations.type.bus': 'Bus',
|
||||||
|
'reservations.type.ferry': 'Ferry',
|
||||||
|
'reservations.type.bicycle': 'Bicycle',
|
||||||
|
'reservations.type.taxi': 'Taxi',
|
||||||
|
'reservations.type.transport_other': 'Other',
|
||||||
'reservations.confirm.delete':
|
'reservations.confirm.delete':
|
||||||
'Are you sure you want to delete the reservation "{name}"?',
|
'Are you sure you want to delete the reservation "{name}"?',
|
||||||
'reservations.confirm.deleteTitle': 'Delete booking?',
|
'reservations.confirm.deleteTitle': 'Delete booking?',
|
||||||
|
|||||||
@@ -32,6 +32,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': 'Evento',
|
'reservations.type.event': 'Evento',
|
||||||
'reservations.type.tour': 'Excursión',
|
'reservations.type.tour': 'Excursión',
|
||||||
'reservations.type.other': 'Otro',
|
'reservations.type.other': 'Otro',
|
||||||
|
'reservations.type.bus': 'Autobús',
|
||||||
|
'reservations.type.ferry': 'Ferry',
|
||||||
|
'reservations.type.bicycle': 'Bicicleta',
|
||||||
|
'reservations.type.taxi': 'Taxi',
|
||||||
|
'reservations.type.transport_other': 'Otro',
|
||||||
'reservations.confirm.delete':
|
'reservations.confirm.delete':
|
||||||
'¿Seguro que quieres eliminar la reserva "{name}"?',
|
'¿Seguro que quieres eliminar la reserva "{name}"?',
|
||||||
'reservations.confirm.deleteTitle': '¿Eliminar reserva?',
|
'reservations.confirm.deleteTitle': '¿Eliminar reserva?',
|
||||||
|
|||||||
@@ -55,6 +55,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': 'Événement',
|
'reservations.type.event': 'Événement',
|
||||||
'reservations.type.tour': 'Visite',
|
'reservations.type.tour': 'Visite',
|
||||||
'reservations.type.other': 'Autre',
|
'reservations.type.other': 'Autre',
|
||||||
|
'reservations.type.bus': 'Bus',
|
||||||
|
'reservations.type.ferry': 'Ferry',
|
||||||
|
'reservations.type.bicycle': 'Vélo',
|
||||||
|
'reservations.type.taxi': 'Taxi',
|
||||||
|
'reservations.type.transport_other': 'Autre',
|
||||||
'reservations.confirm.delete':
|
'reservations.confirm.delete':
|
||||||
'Voulez-vous vraiment supprimer la réservation « {name} » ?',
|
'Voulez-vous vraiment supprimer la réservation « {name} » ?',
|
||||||
'reservations.confirm.deleteTitle': 'Supprimer la réservation ?',
|
'reservations.confirm.deleteTitle': 'Supprimer la réservation ?',
|
||||||
|
|||||||
@@ -55,6 +55,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': 'Εκδήλωση',
|
'reservations.type.event': 'Εκδήλωση',
|
||||||
'reservations.type.tour': 'Περιήγηση',
|
'reservations.type.tour': 'Περιήγηση',
|
||||||
'reservations.type.other': 'Άλλο',
|
'reservations.type.other': 'Άλλο',
|
||||||
|
'reservations.type.bus': 'Λεωφορείο',
|
||||||
|
'reservations.type.ferry': 'Φέρι',
|
||||||
|
'reservations.type.bicycle': 'Ποδήλατο',
|
||||||
|
'reservations.type.taxi': 'Ταξί',
|
||||||
|
'reservations.type.transport_other': 'Άλλο',
|
||||||
'reservations.confirm.delete':
|
'reservations.confirm.delete':
|
||||||
'Είστε σίγουροι ότι θέλετε να διαγράψετε την κράτηση "{name}";',
|
'Είστε σίγουροι ότι θέλετε να διαγράψετε την κράτηση "{name}";',
|
||||||
'reservations.confirm.deleteTitle': 'Διαγραφή κράτησης;',
|
'reservations.confirm.deleteTitle': 'Διαγραφή κράτησης;',
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': 'Esemény',
|
'reservations.type.event': 'Esemény',
|
||||||
'reservations.type.tour': 'Túra',
|
'reservations.type.tour': 'Túra',
|
||||||
'reservations.type.other': 'Egyéb',
|
'reservations.type.other': 'Egyéb',
|
||||||
|
'reservations.type.bus': 'Busz',
|
||||||
|
'reservations.type.ferry': 'Komp',
|
||||||
|
'reservations.type.bicycle': 'Kerékpár',
|
||||||
|
'reservations.type.taxi': 'Taxi',
|
||||||
|
'reservations.type.transport_other': 'Egyéb',
|
||||||
'reservations.confirm.delete':
|
'reservations.confirm.delete':
|
||||||
'Biztosan törölni szeretnéd a(z) "{name}" foglalást?',
|
'Biztosan törölni szeretnéd a(z) "{name}" foglalást?',
|
||||||
'reservations.confirm.deleteTitle': 'Foglalás törlése?',
|
'reservations.confirm.deleteTitle': 'Foglalás törlése?',
|
||||||
|
|||||||
@@ -55,6 +55,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': 'Acara',
|
'reservations.type.event': 'Acara',
|
||||||
'reservations.type.tour': 'Tur',
|
'reservations.type.tour': 'Tur',
|
||||||
'reservations.type.other': 'Lainnya',
|
'reservations.type.other': 'Lainnya',
|
||||||
|
'reservations.type.bus': 'Bus',
|
||||||
|
'reservations.type.ferry': 'Feri',
|
||||||
|
'reservations.type.bicycle': 'Sepeda',
|
||||||
|
'reservations.type.taxi': 'Taksi',
|
||||||
|
'reservations.type.transport_other': 'Lainnya',
|
||||||
'reservations.confirm.delete': 'Yakin ingin menghapus reservasi "{name}"?',
|
'reservations.confirm.delete': 'Yakin ingin menghapus reservasi "{name}"?',
|
||||||
'reservations.confirm.deleteTitle': 'Hapus pemesanan?',
|
'reservations.confirm.deleteTitle': 'Hapus pemesanan?',
|
||||||
'reservations.confirm.deleteBody': '"{name}" akan dihapus permanen.',
|
'reservations.confirm.deleteBody': '"{name}" akan dihapus permanen.',
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': 'Evento',
|
'reservations.type.event': 'Evento',
|
||||||
'reservations.type.tour': 'Tour',
|
'reservations.type.tour': 'Tour',
|
||||||
'reservations.type.other': 'Altro',
|
'reservations.type.other': 'Altro',
|
||||||
|
'reservations.type.bus': 'Autobus',
|
||||||
|
'reservations.type.ferry': 'Traghetto',
|
||||||
|
'reservations.type.bicycle': 'Bicicletta',
|
||||||
|
'reservations.type.taxi': 'Taxi',
|
||||||
|
'reservations.type.transport_other': 'Altro',
|
||||||
'reservations.confirm.delete':
|
'reservations.confirm.delete':
|
||||||
'Sei sicuro di voler eliminare la prenotazione "{name}"?',
|
'Sei sicuro di voler eliminare la prenotazione "{name}"?',
|
||||||
'reservations.confirm.deleteTitle': 'Eliminare la prenotazione?',
|
'reservations.confirm.deleteTitle': 'Eliminare la prenotazione?',
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': 'イベント',
|
'reservations.type.event': 'イベント',
|
||||||
'reservations.type.tour': 'ツアー',
|
'reservations.type.tour': 'ツアー',
|
||||||
'reservations.type.other': 'その他',
|
'reservations.type.other': 'その他',
|
||||||
|
'reservations.type.bus': 'バス',
|
||||||
|
'reservations.type.ferry': 'フェリー',
|
||||||
|
'reservations.type.bicycle': '自転車',
|
||||||
|
'reservations.type.taxi': 'タクシー',
|
||||||
|
'reservations.type.transport_other': 'その他',
|
||||||
'reservations.confirm.delete': '予約「{name}」を削除しますか?',
|
'reservations.confirm.delete': '予約「{name}」を削除しますか?',
|
||||||
'reservations.confirm.deleteTitle': '予約を削除しますか?',
|
'reservations.confirm.deleteTitle': '予約を削除しますか?',
|
||||||
'reservations.confirm.deleteBody': '「{name}」は完全に削除されます。',
|
'reservations.confirm.deleteBody': '「{name}」は完全に削除されます。',
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': '이벤트',
|
'reservations.type.event': '이벤트',
|
||||||
'reservations.type.tour': '투어',
|
'reservations.type.tour': '투어',
|
||||||
'reservations.type.other': '기타',
|
'reservations.type.other': '기타',
|
||||||
|
'reservations.type.bus': '버스',
|
||||||
|
'reservations.type.ferry': '페리',
|
||||||
|
'reservations.type.bicycle': '자전거',
|
||||||
|
'reservations.type.taxi': '택시',
|
||||||
|
'reservations.type.transport_other': '기타',
|
||||||
'reservations.confirm.delete': '예약 "{name}"을(를) 삭제할까요?',
|
'reservations.confirm.delete': '예약 "{name}"을(를) 삭제할까요?',
|
||||||
'reservations.confirm.deleteTitle': '예약을 삭제할까요?',
|
'reservations.confirm.deleteTitle': '예약을 삭제할까요?',
|
||||||
'reservations.confirm.deleteBody': '"{name}"이(가) 영구 삭제됩니다.',
|
'reservations.confirm.deleteBody': '"{name}"이(가) 영구 삭제됩니다.',
|
||||||
|
|||||||
@@ -55,6 +55,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': 'Evenement',
|
'reservations.type.event': 'Evenement',
|
||||||
'reservations.type.tour': 'Rondleiding',
|
'reservations.type.tour': 'Rondleiding',
|
||||||
'reservations.type.other': 'Overig',
|
'reservations.type.other': 'Overig',
|
||||||
|
'reservations.type.bus': 'Bus',
|
||||||
|
'reservations.type.ferry': 'Veerboot',
|
||||||
|
'reservations.type.bicycle': 'Fiets',
|
||||||
|
'reservations.type.taxi': 'Taxi',
|
||||||
|
'reservations.type.transport_other': 'Overig',
|
||||||
'reservations.confirm.delete':
|
'reservations.confirm.delete':
|
||||||
'Weet je zeker dat je de reservering "{name}" wilt verwijderen?',
|
'Weet je zeker dat je de reservering "{name}" wilt verwijderen?',
|
||||||
'reservations.confirm.deleteTitle': 'Boeking verwijderen?',
|
'reservations.confirm.deleteTitle': 'Boeking verwijderen?',
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': 'Wydarzenie',
|
'reservations.type.event': 'Wydarzenie',
|
||||||
'reservations.type.tour': 'Wycieczka',
|
'reservations.type.tour': 'Wycieczka',
|
||||||
'reservations.type.other': 'Inne',
|
'reservations.type.other': 'Inne',
|
||||||
|
'reservations.type.bus': 'Autobus',
|
||||||
|
'reservations.type.ferry': 'Prom',
|
||||||
|
'reservations.type.bicycle': 'Rower',
|
||||||
|
'reservations.type.taxi': 'Taksówka',
|
||||||
|
'reservations.type.transport_other': 'Inne',
|
||||||
'reservations.confirm.delete':
|
'reservations.confirm.delete':
|
||||||
'Czy na pewno chcesz usunąć rezerwację "{name}"?',
|
'Czy na pewno chcesz usunąć rezerwację "{name}"?',
|
||||||
'reservations.confirm.deleteTitle': 'Usunąć rezerwację?',
|
'reservations.confirm.deleteTitle': 'Usunąć rezerwację?',
|
||||||
|
|||||||
@@ -55,6 +55,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': 'Мероприятие',
|
'reservations.type.event': 'Мероприятие',
|
||||||
'reservations.type.tour': 'Экскурсия',
|
'reservations.type.tour': 'Экскурсия',
|
||||||
'reservations.type.other': 'Другое',
|
'reservations.type.other': 'Другое',
|
||||||
|
'reservations.type.bus': 'Автобус',
|
||||||
|
'reservations.type.ferry': 'Паром',
|
||||||
|
'reservations.type.bicycle': 'Велосипед',
|
||||||
|
'reservations.type.taxi': 'Такси',
|
||||||
|
'reservations.type.transport_other': 'Другое',
|
||||||
'reservations.confirm.delete':
|
'reservations.confirm.delete':
|
||||||
'Вы уверены, что хотите удалить бронирование «{name}»?',
|
'Вы уверены, что хотите удалить бронирование «{name}»?',
|
||||||
'reservations.confirm.deleteTitle': 'Удалить бронирование?',
|
'reservations.confirm.deleteTitle': 'Удалить бронирование?',
|
||||||
|
|||||||
@@ -55,6 +55,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': 'Etkinlik',
|
'reservations.type.event': 'Etkinlik',
|
||||||
'reservations.type.tour': 'Tur',
|
'reservations.type.tour': 'Tur',
|
||||||
'reservations.type.other': 'Diğer',
|
'reservations.type.other': 'Diğer',
|
||||||
|
'reservations.type.bus': 'Otobüs',
|
||||||
|
'reservations.type.ferry': 'Feribot',
|
||||||
|
'reservations.type.bicycle': 'Bisiklet',
|
||||||
|
'reservations.type.taxi': 'Taksi',
|
||||||
|
'reservations.type.transport_other': 'Diğer',
|
||||||
'reservations.confirm.delete':
|
'reservations.confirm.delete':
|
||||||
'"{name}" rezervasyonunu silmek istediğinizden emin misiniz?',
|
'"{name}" rezervasyonunu silmek istediğinizden emin misiniz?',
|
||||||
'reservations.confirm.deleteTitle': 'Rezervasyon silinsin mi?',
|
'reservations.confirm.deleteTitle': 'Rezervasyon silinsin mi?',
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': 'Заходи',
|
'reservations.type.event': 'Заходи',
|
||||||
'reservations.type.tour': 'Екскурсія',
|
'reservations.type.tour': 'Екскурсія',
|
||||||
'reservations.type.other': 'Інше',
|
'reservations.type.other': 'Інше',
|
||||||
|
'reservations.type.bus': 'Автобус',
|
||||||
|
'reservations.type.ferry': 'Пором',
|
||||||
|
'reservations.type.bicycle': 'Велосипед',
|
||||||
|
'reservations.type.taxi': 'Таксі',
|
||||||
|
'reservations.type.transport_other': 'Інше',
|
||||||
'reservations.confirm.delete':
|
'reservations.confirm.delete':
|
||||||
'Ви впевнені, що хочете видалити бронювання «{name}»?',
|
'Ви впевнені, що хочете видалити бронювання «{name}»?',
|
||||||
'reservations.confirm.deleteTitle': 'Видалити бронювання?',
|
'reservations.confirm.deleteTitle': 'Видалити бронювання?',
|
||||||
|
|||||||
@@ -53,6 +53,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': '活動',
|
'reservations.type.event': '活動',
|
||||||
'reservations.type.tour': '旅遊團',
|
'reservations.type.tour': '旅遊團',
|
||||||
'reservations.type.other': '其他',
|
'reservations.type.other': '其他',
|
||||||
|
'reservations.type.bus': '公車',
|
||||||
|
'reservations.type.ferry': '渡輪',
|
||||||
|
'reservations.type.bicycle': '自行車',
|
||||||
|
'reservations.type.taxi': '計程車',
|
||||||
|
'reservations.type.transport_other': '其他',
|
||||||
'reservations.confirm.delete': '確定要刪除預訂「{name}」嗎?',
|
'reservations.confirm.delete': '確定要刪除預訂「{name}」嗎?',
|
||||||
'reservations.confirm.deleteTitle': '刪除預訂?',
|
'reservations.confirm.deleteTitle': '刪除預訂?',
|
||||||
'reservations.confirm.deleteBody': '"{name}" 將被永久刪除。',
|
'reservations.confirm.deleteBody': '"{name}" 將被永久刪除。',
|
||||||
|
|||||||
@@ -53,6 +53,11 @@ const reservations: TranslationStrings = {
|
|||||||
'reservations.type.event': '活动',
|
'reservations.type.event': '活动',
|
||||||
'reservations.type.tour': '旅游团',
|
'reservations.type.tour': '旅游团',
|
||||||
'reservations.type.other': '其他',
|
'reservations.type.other': '其他',
|
||||||
|
'reservations.type.bus': '公交车',
|
||||||
|
'reservations.type.ferry': '渡轮',
|
||||||
|
'reservations.type.bicycle': '自行车',
|
||||||
|
'reservations.type.taxi': '出租车',
|
||||||
|
'reservations.type.transport_other': '其他',
|
||||||
'reservations.confirm.delete': '确定要删除预订「{name}」吗?',
|
'reservations.confirm.delete': '确定要删除预订「{name}」吗?',
|
||||||
'reservations.confirm.deleteTitle': '删除预订?',
|
'reservations.confirm.deleteTitle': '删除预订?',
|
||||||
'reservations.confirm.deleteBody': '"{name}" 将被永久删除。',
|
'reservations.confirm.deleteBody': '"{name}" 将被永久删除。',
|
||||||
|
|||||||
Reference in New Issue
Block a user