{"version":3,"mappings":"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","names":["defaultMessages","merge","en","_en","no","_no","setupI18n","options","i18n","createI18n","setI18nLanguage","locale","_a","loadLocaleMessages","axios","useContainer","IAxiosId","mainStore","useMainStore","messages","e","nextTick","routeMiddleware","to","_from","next","paramLocale","isEmpty","i18nRoute","devModeRequestInterceptor","config","devModeConfiguration","isDevMode","ax","error","ISODateFormat","isIsoDateString","value","handleDates","data","parseISO","key","val","rep","IBookingServiceId","IConfigServiceId","ILinesServiceId","IPlaceServiceId","ISearchServiceId","WalkSpeedType","WalkSpeedType2","DateType","GeolocationError","CustomError","message","PlacesError","BookingError","ApiService","__publicField","__decorateClass","inject","injectable","SearchService","searchRequest","method","modes","walkSpeedType","transferSlack","showTripsWithTransfers","lines","walkSpeed","params","_b","response","meta","request","type","PlaceService","keyword","id","latLng","AppConfigService","resolve","reject","LinesService","BookingService","activeDate","serviceJourneyRef","stopSequence","format","__INVERSIFY_SYMBOL__","injectionKey","createContainer","container","Container","app","_container","SearchMode","defineStore","configService","ready","ref","isLoading","language","isDebugMode","computed","searchMode","defaultConfig","menuItems","lastKnownError","showAppDrawer","menu","currentTime","startOfMinute","loadConfig","supportedLanguages","l","registerError","init","menuProvider","useMenuProvider","toggleSearch","isErrorWithMessage","updateCurrentTime","toExactMinute","isUndefined","isNull","isObject","GetTripModeDto","TripMode","PlaceType","TransportMode","NotificationMessageType","BookingStatus","BookingMethod","_getGeolocation","abortController","position","useGeolocationHelper","t","useI18n","isSupported","getCurrentPosition","props","__props","circleRadius","circleMarkerProps","colors","circleProps","useMapHelpers","map","calcPaddingOffset","_paddingTL","isArray","_paddingBR","paddingTL","point","addOffsets","zoom","leafletObject","paddingOffset","removeOffsets","isLeafletMap","Map","isLatLngBounds","LatLngBounds","_decode","str","precision","index","lat","lng","coordinates","shift","result","byte","latitude_change","longitude_change","factor","encode","output","prevLat","prevLng","encodeValue","currentLat","currentLng","toLineString","coords","acc","curr","pointsToLineString","points","useGeojsonHelper","mapLegToLineString","leg","pointsOnLink","properties","mapDepartureToLineString","departure","_","mapQuayToPoint","quay","latitude","longitude","useMapStore","state","reactive","googleMutantOptions","watch","toRefs","defaultPadding","useMapUnderlay","isMobile","useDisplay","storeToRefs","mapStore","userLocation","paddingTopLeft","_paddingBottomRight","storeRefs","locateUser","paddingBottomRight","emit","__emit","_center","useVModel","_zoom","_bounds","cssClasses","mapOptions","onMapReady","_map","item","flyTo","padding","fitBounds","latLngBounds","zoomIn","zoomOut","triggerResize","__expose","AppProvideKey","SearchPageProvideKey","MapUnderlayProvideKey","OnlineBookingIsAvailableKey","BookingCardProvideKey","BookingFormCardProvideKey","underlay","center","bounds","canUseGeolocation","grayscale","contextmenu","mainRect","useLayout","provide","mode","useSearchModeToggle","showHeader","showHeaderAppend","page","setHeaderVisibility","setHeaderAppendVisibility","setPage","routeNames","router","createRouter","createWebHistory","Home","SearchPageLayout","__vitePreload","maxEntryLength","usePlaceAutocompleteHistory","name","storage","historyStorage","useStorage","items","addItem","_items","toValue","existingItemIndex","x","existingItem","clear","useBookingFeature","userStore","useUserStore","bookingStore","useBookingStore","tripSearchStore","useTripSearchStore","departureSearchStore","useDeparturesSearchStore","bookings","maxBookingExceeded","selectedBooking","selectedDeparture","hasDepartureResult","selectedTripPattern","hasTripPatternResult","loadBookingData","legOrDeparture","bookingLimitDateTime","isDate","isAfter","isSameDay","reset","resultWatcher","tripPatternWatcher","departureWatcher","startWatchers","oldValue","bookingLeg","stopWatchers","_i18n","useBookingMessages","formatRelativeLocaleEnUS","formatRelativeLocaleNb","enUS","_enUS","token","nb","_nb","generateDescriptionText","fromQuay","bookingMethods","bookingContact","now","bookingLimitDateTimeString","toLocalDate","toLocaleTimeString","addDays","generateDeadlineExpiredDescriptionText","bookingLimitDateTimeAndOrBookingMethod","generateBookingExistsDescriptionText","transportMode","transportModeString","getTransportMode","generateCancelledBookingDescriptionText","booking","quayName","_pickupTime","localPickupTime","pickupTime","formatRelative","createBookingParams","departureOrLeg","bookingMetadata","notificationMessages","bookingCancellationLimitDateTime","aimedDepartureTime","from","aimedStartTime","bookingNotificationMessage","aimedDepartureDateTime","hasValidStopOrder","stopOrder","hasValidBooking","updateTripPatternBookingNotifications","tripPatternGroups","stopOrders","processedGroups","tripPattern","updateNotificationMessage","updateDepartureBookingNotifications","departureGroups","hasExistingBooking","hasExistingStopOrder","notificationMessageIndex","_c","_d","_e","msg","isTransfer","legDto","getTransferTime","prev","prevEndTime","nextStartTime","differenceInSeconds","isTransitMode","tripMode","isNumber","sortTripPatternsByArrival","arriveBy","tripPatterns","b","aEndTime","bEndTime","comparison","markAndFilterExpensiveTripPatterns","removeExpensiveTripPatterns","maxPatternsPerHour","tripPatternsByHour","hour","expensiveTripPatterns","expensiveTripPattern","defaultSearchFilters","defaultSearchRequest","defaultSearchResult","tripSearchService","addPastPlace","gtm","useGtm","searchResult","_footSearchResult","footSearchResult","_bikeSearchResult","bikeSearchResult","searchingState","loadingStates","isSearching","canSearch","isValidSearchRequest","filterIsDirty","isEqual","hasResult","addTransferLegs","removeDuplicateTripPatterns","setIsMyLocation","removeHiddenLegs","generalizedCostMean","isInNonTransitMode","m","$reset","resetResult","resetFilters","swapFromTo","isDefined","selectFirstTripPattern","searchAbortController","_executeSearch","searchFunc","onError","searchFoot","signal","searchResponse","searchBike","searchTransit","_search","omit","search","cancelSearch","searchMore","nextPageCursors","previousPageCursors","mergeWith","mergeArray","obj","src","y","myLocationPlaceId","self","i","arr","previousLeg","transferLeg","defaultUserInfo","bookingService","bookingIsEnabled","isBooking","createBookingProps","onlineBookingIsAvailable","bookingDeadlineExceeded","bookingTooFarAhead","canBook","canCancel","isBefore","userInfo","userInfoIsValid","loadStopOrderAbortController","loadBookingsAbortController","loadStopOrder","isAxiosError","loadBookings","loadBooking","createBooking","recaptchaToken","phoneVerificationCode","_createBookingProps","countryCode","number","cancelBooking","REALTIME_THRESHOLD_MINUTES","sortDepartureGroups","departures","sorted","aTime","bTime","updateDeparturesTimeStatusFlags","updatedGroups","groupKey","estimatedCall","stopTime","currentTimeMs","adjustExpectedTimesBasedOnAimed","adjustedGroups","expectedStopTime","aimedStopTime","estimatedCalls","expectedTime","aimedTime","searchService","stopPlaceTransportModes","stopPlaceQuays","a","found","removeDuplicateDepartures","availableTransportModes","d","useRouter","currentRoute","tripStore","departuresStore","disabled","setMode","MIN_THRESHOLD","useDevModeActivator","devModeSessionStorage","useSessionStorage","devModeConfigurationSessionStorage","modeChangeCounter","dialogIsVisible","showDevModeNotification","syncRef","right","left","setInitialDevModeConfiguration","unwatchRoute","unwatchDebounced","watchDebounced","unwatchCounter","resetConfig","model","_useModel","_modelValue","mainStyles","_type","localType","__type","_types","showDateTimePicker","confirmEditRef","save","cancel","themeClasses","provideTheme","route","useRoute","departuresSearchStore","initDevModeActivator","userLoaded","drawerIsFullHeight","setDrawerFullHeight","fullHeight","instance","getCurrentInstance","onMounted","useEventListener","createGtm","refresh","pinia","createPinia","createApp","App","createVuetify","v1","createVueI18nAdapter","VueReCaptcha"],"ignoreList":[],"sources":["../../ClientApp/src/i18n/index.ts","../../ClientApp/src/plugins/axiosInterceptors.ts","../../ClientApp/src/plugins/axios.ts","../../ClientApp/src/services/IBookingService.ts","../../ClientApp/src/services/IConfigService.ts","../../ClientApp/src/services/ILinesService.ts","../../ClientApp/src/services/IPlaceService.ts","../../ClientApp/src/services/ISearchService.ts","../../ClientApp/src/features/trips/models/TripSearchFilters.ts","../../ClientApp/src/features/common/models/DateType.ts","../../ClientApp/src/features/common/models/CustomErrors.ts","../../ClientApp/src/services/ApiService.ts","../../ClientApp/src/services/SearchService.ts","../../ClientApp/src/services/PlaceService.ts","../../ClientApp/src/services/AppConfigService.ts","../../ClientApp/src/services/LinesService.ts","../../ClientApp/src/services/BookingService.ts","../../ClientApp/src/plugins/inversify.ts","../../ClientApp/src/features/common/stores/mainStore.ts","../../ClientApp/src/types/webapi/GetTripModeDto.generated.ts","../../ClientApp/src/types/webapi/TripMode.generated.ts","../../ClientApp/src/types/webapi/PlaceType.generated.ts","../../ClientApp/src/types/webapi/TransportMode.generated.ts","../../ClientApp/src/types/webapi/NotificationMessageType.generated.ts","../../ClientApp/src/types/webapi/BookingStatus.generated.ts","../../ClientApp/src/types/webapi/BookingMethod.generated.ts","../../ClientApp/src/features/common/composables/useGeolocationHelper.ts","../../ClientApp/src/features/map/components/GeolocationMarker.vue","../../ClientApp/src/features/map/components/Map/mapHelpers.ts","../../ClientApp/src/features/map/composables/usePolylineHelper/useGeojsonHelper.ts","../../ClientApp/src/features/map/stores/mapStore.ts","../../ClientApp/src/features/map/composables/useMapUnderlay.ts","../../ClientApp/src/features/map/components/Map/MapUnderlay.vue","../../ClientApp/src/injectionKeys.ts","../../ClientApp/src/pages/Home.vue","../../ClientApp/src/pages/layouts/SearchPageLayout.vue","../../ClientApp/src/router/index.ts","../../ClientApp/src/features/places/composables/usePlaceAutocompleteHistory.ts","../../ClientApp/src/features/bookings/composables/useBooking.ts","../../ClientApp/src/features/bookings/composables/useBookingMessages.ts","../../ClientApp/src/features/bookings/functions/createBookingParams.ts","../../ClientApp/src/features/bookings/functions/bookingHelpers.ts","../../ClientApp/src/features/bookings/composables/useBookingHelpers.ts","../../ClientApp/src/features/trips/helpers/legHelpers.ts","../../ClientApp/src/features/trips/helpers/tripModeHelpers.ts","../../ClientApp/src/features/trips/helpers/tripPatternHelpers.ts","../../ClientApp/src/features/trips/stores/tripSearchStore.ts","../../ClientApp/src/features/bookings/stores/bookingStore.ts","../../ClientApp/src/features/departures/helpers/departureGroupHelpers.ts","../../ClientApp/src/features/departures/stores/departuresSearchStore.ts","../../ClientApp/src/features/common/composables/useSearchModeToggle.ts","../../ClientApp/src/features/common/composables/useDevModeActivator.ts","../../ClientApp/src/features/common/components/SearchDialog/SearchModeToggle.vue","../../ClientApp/src/features/common/components/AppDrawer/AppDrawer.vue","../../ClientApp/src/features/common/components/DateTimeSelector/DateTimeSelector.vue","../../ClientApp/src/features/common/components/DevModeConfigurator/DevModeConfigurator.vue","../../ClientApp/src/features/trips/components/TripLegList/TripLegList.vue","../../ClientApp/src/App.vue","../../ClientApp/src/store/index.ts","../../ClientApp/src/main.ts"],"sourcesContent":["import { createI18n, type I18n } from 'vue-i18n';\nimport { nextTick } from 'vue';\nimport type { RouteLocationNormalized, NavigationGuardNext, RouteLocationRaw } from 'vue-router';\nimport { useMainStore } from '@/features/common/stores';\nimport { isEmpty, merge } from 'lodash-es';\nimport { useContainer } from '@/plugins/inversify';\nimport { IAxiosId } from '@/plugins/axios';\nimport type { AxiosInstance } from 'axios';\nimport { en, no } from 'vuetify/locale';\nimport { en as _en, no as _no } from '@geta/kolumbus-frontend/locale';\n\nconst defaultMessages: any = {\n en: {\n $vuetify: merge(en, _en)\n },\n no: {\n $vuetify: merge(no, _no)\n }\n};\n\nfunction setupI18n(options = { locale: 'no' }) {\n const i18n = createI18n({\n fallbackLocale: 'en',\n legacy: false,\n globalInjection: true,\n ...options\n });\n setI18nLanguage(i18n, options.locale);\n return i18n;\n}\n\nconst i18n = setupI18n();\nexport default i18n;\n\nfunction setI18nLanguage(i18n: I18n<{}, {}, {}, string, false>, locale: string) {\n i18n.global.locale.value = locale;\n document.querySelector('html')?.setAttribute('lang', locale);\n}\n\nasync function loadLocaleMessages(i18n: I18n<{}, {}, {}, string, false>, locale: string) {\n const container = useContainer();\n const axios = container.get<AxiosInstance>(IAxiosId);\n const mainStore = useMainStore();\n\n try {\n // load locale messages with dynamic import\n const res = await axios.get(`/jsl10n/Kolumbus.TravelPlanner?camel=true&json=true&lang=${locale}`);\n const messages = res.data.kolumbus.travelPlanner;\n\n // set locale and locale message\n i18n.global.setLocaleMessage(locale, merge({}, defaultMessages[locale], messages));\n\n // additional messages\n if (locale === 'no') {\n i18n.global.mergeLocaleMessage('no', {\n trips: {\n resources: {\n transferNotice: {\n travelGuaranteeAboutPageLinkUrl: new URL('/reisegaranti', mainStore.config.kolumbusWebsiteBaseUrl).toString()\n }\n }\n }\n });\n } else if (locale === 'en') {\n i18n.global.mergeLocaleMessage('en', {\n trips: {\n resources: {\n transferNotice: {\n travelGuaranteeAboutPageLinkUrl: new URL(\n '/travel-guarantee',\n mainStore.config.kolumbusWebsiteBaseUrl\n ).toString()\n }\n }\n }\n });\n }\n } catch (e) {\n mainStore.registerError(e);\n }\n\n return nextTick();\n}\n\nexport async function routeMiddleware(to: RouteLocationNormalized, _from: RouteLocationNormalized, next: NavigationGuardNext) {\n const paramLocale = Array.isArray(to.params.locale) ? to.params.locale[0] : to.params.locale;\n const mainStore = useMainStore();\n\n // use locale if paramsLocale is not in SUPPORT_LOCALES\n if (mainStore.config.supportedLanguages.indexOf(paramLocale) == -1) {\n return next({ params: { locale: mainStore.language } });\n }\n\n // set language in mainStore\n mainStore.language = paramLocale;\n\n // load locale messages\n if (!i18n.global.availableLocales.includes(paramLocale) || isEmpty(i18n.global.getLocaleMessage(paramLocale))) {\n await loadLocaleMessages(i18n, paramLocale);\n }\n\n // set i18n language\n setI18nLanguage(i18n, paramLocale);\n\n return next();\n}\n\nexport function i18nRoute(to: RouteLocationRaw): RouteLocationRaw {\n return merge(to, { params: { locale: i18n.global.locale.value } });\n}\n","import { useMainStore } from '@/features/common/stores';\nimport { InternalAxiosRequestConfig } from 'axios';\n\nexport function devModeRequestInterceptor(config: InternalAxiosRequestConfig) {\n const mainStore = useMainStore();\n const { devModeConfiguration, isDevMode } = mainStore;\n\n if (isDevMode && devModeConfiguration) {\n config.headers['X-Booking-Enabled'] = devModeConfiguration.enableBooking || undefined;\n config.headers['X-Debug-Mode-Enabled'] = devModeConfiguration.enableDebugMode || undefined;\n config.headers['X-Entur-Endpoint-Type'] = devModeConfiguration.enturEndpointType || undefined;\n config.headers['X-Ng-Endpoint-Type'] = devModeConfiguration.ngEndpointType || undefined;\n config.headers['X-Direct-Search-Enabled'] = devModeConfiguration.enableDirectSearchMode || undefined;\n }\n\n return config;\n}\n","import axios from 'axios';\nimport i18n from '@/i18n';\nimport { parseISO } from 'date-fns';\nimport { devModeRequestInterceptor } from './axiosInterceptors';\n\nconst ax = axios.create();\nax.interceptors.request.use(\n config => {\n config.headers['Accept-Language'] = i18n.global.locale.value;\n return config;\n },\n error => {\n return Promise.reject(error);\n }\n);\n\n// Axios response interceptor that converts ISO date strings to JS Date instances.\n// ref: https://medium.com/@vladkens/automatic-parsing-of-date-strings-in-rest-protocol-with-typescript-cf43554bd157\nconst ISODateFormat = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d*)?(?:[-+]\\d{2}:?\\d{2}|Z)?$/;\n\nfunction isIsoDateString(value: unknown): value is string {\n return typeof value === 'string' && ISODateFormat.test(value);\n}\n\nfunction handleDates(data: unknown) {\n if (isIsoDateString(data)) return parseISO(data);\n\n if (data === null || data === undefined || typeof data !== 'object') return data;\n\n for (const [key, val] of Object.entries(data)) {\n // @ts-expect-error this is a hack to make the type checker happy\n if (isIsoDateString(val)) data[key] = parseISO(val);\n else if (typeof val === 'object') handleDates(val);\n }\n\n return data;\n}\n\nax.interceptors.response.use(rep => {\n handleDates(rep.data);\n return rep;\n});\n\nax.interceptors.request.use(devModeRequestInterceptor);\n\nexport const IAxiosId = Symbol.for('Axios');\nexport { ax };\nexport type { AxiosInstance } from 'axios';\n","import { BookingDto, CreateBookingDto, StopOrderDto } from '@/types/webapi';\nimport ServiceOptions from './ServiceOptions';\n\nexport const IBookingServiceId = Symbol.for('IBookingService');\n\nexport interface GetBookingsFilter {\n serviceJourneyRef?: string;\n activeDate?: Date;\n stopSequence?: number;\n}\n\nexport interface GetStopOrderParams {\n serviceJourneyRef: string;\n activeDate: Date;\n stopSequence: number;\n}\n\nexport interface IBookingService {\n /**\n * Get all bookings for current user.\n */\n getAllBookings(options?: ServiceOptions): Promise<BookingDto[]>;\n\n /**\n * Get all bookings for current user.\n * @param filters Filters to use when fetching bookings\n */\n getBookings(filters?: GetBookingsFilter, options?: ServiceOptions): Promise<BookingDto[]>;\n\n /**\n * Get single booking by ID.\n * @param id Booking ID\n */\n getBooking(id: string): Promise<BookingDto>;\n\n /**\n * Create new booking\n * @param params Values to pass to API when creating new booking\n */\n createBooking(params: CreateBookingDto): Promise<BookingDto>;\n\n /**\n * Cancel existing booking\n * @param id Booking ID\n */\n cancelBooking(id: string): Promise<BookingDto>;\n\n /**\n * Get stop order for serviceJourney, null if it does not exist.\n * @param params Parameters to pass to API service\n */\n getStopOrder(params: GetStopOrderParams, options?: ServiceOptions): Promise<StopOrderDto | undefined>;\n}\n","import type { AppConfigDto } from '@/types/webapi';\n\nexport const IConfigServiceId = Symbol.for('IConfigService');\n\nexport interface IConfigService {\n getConfig(): Promise<AppConfigDto>;\n}\n","import { LineDto } from '@/types/webapi';\nimport ServiceOptions from './ServiceOptions';\n\nexport const ILinesServiceId = Symbol.for('ILinesService');\n\nexport interface ILinesServiceOptions extends ServiceOptions {\n /**\n * Time for lines to fetch\n */\n dateTime?: Date;\n}\n\nexport interface ILinesService {\n /**\n * Fetches all lines from web API.\n * @param options Request options\n */\n getAllLines(options?: ILinesServiceOptions): Promise<LineDto[]>;\n}\n","import type { PlaceAutocompleteModelDto } from '@/types/webapi';\nimport type ServiceOptions from './ServiceOptions';\nimport { type LatLngLiteral } from 'leaflet';\n\nexport const IPlaceServiceId = Symbol.for('IPlaceService');\n\nexport interface IPlaceServiceOptions extends ServiceOptions {\n origin?: LatLngLiteral;\n stopPlacesOnly?: boolean;\n}\n\nexport interface IPlaceService {\n /**\n * Fetches a list of places for the given search term.\n * @param keyword String value to use in search query\n * @param options Additional options to pass to the Places API\n */\n getPlacesAutocomplete(keyword: string, options?: IPlaceServiceOptions): Promise<PlaceAutocompleteModelDto[]>;\n\n /**\n * Fetches Google Place or StopPlace for the given ID.\n * @param id Google Place ID or StopPlace NSR ID\n * @param options Additional options to pass to the Places API\n */\n getPlaceDetails(id: string, options?: ServiceOptions): Promise<PlaceAutocompleteModelDto | null>;\n\n /**\n * Fetches Google Place for the given geolocation.\n * @param geolocation Geolocation object\n * @param options Additional options to pass to the Places API\n */\n getPlaceDetailsForGeolocation(geolocation: LatLngLiteral, options?: ServiceOptions): Promise<PlaceAutocompleteModelDto | null>;\n}\n","import type { DeparturesSearchRequest } from '@/features/departures/models';\nimport type { TripSearchRequest } from '@/features/trips/models/TripSearchRequest';\nimport type { GetTripResponseDto, StopPlaceDto } from '@/types/webapi';\nimport type ServiceOptions from './ServiceOptions';\n\nexport const ISearchServiceId = Symbol.for('ISearchService');\n\nexport interface ISearchService {\n searchForTrips(request: TripSearchRequest, options?: ServiceOptions): Promise<GetTripResponseDto | null>;\n searchForMoreTrips(request: TripSearchRequest, options?: ServiceOptions): Promise<GetTripResponseDto | null>;\n searchForDepartures(request: DeparturesSearchRequest, options?: ServiceOptions): Promise<StopPlaceDto | null>;\n}\n","import type { GetTripModeDto } from '@/types/webapi';\n\nexport enum WalkSpeedType {\n Normal,\n Slow,\n Fast\n}\n\nexport interface TripSearchFilters {\n modes: GetTripModeDto[];\n walkSpeed: WalkSpeedType;\n transferSlack: number;\n showTripsWithTransfers: boolean;\n lines: string[];\n}\n","export enum DateType {\n Now = 0,\n DepartAt = 1,\n ArriveBy = 2\n}\n","import { CustomError } from '@geta/kolumbus-frontend/features/common';\n\nexport class GeolocationError extends CustomError {\n constructor(message: string) {\n super('GeolocationError', message);\n }\n}\n\nexport class PlacesError extends CustomError {\n constructor(message: string) {\n super('PlacesError', message);\n }\n}\n\nexport class BookingError extends CustomError {\n constructor(message: string) {\n super('BookingError', message);\n }\n}\n","import { useMainStore } from '@/features/common/stores';\nimport { AxiosInstance, IAxiosId } from '@/plugins/axios';\nimport { inject, injectable } from 'inversify';\n\n@injectable()\nexport class ApiService {\n @inject(IAxiosId)\n protected axios: AxiosInstance;\n\n _mainStore: ReturnType<typeof useMainStore>;\n get mainStore(): ReturnType<typeof useMainStore> {\n if (!this._mainStore) {\n this._mainStore = useMainStore();\n }\n\n return this._mainStore;\n }\n}\n","import { type DeparturesSearchRequest } from '@/features/departures/models';\nimport { type TripSearchRequest, WalkSpeedType } from '@/features/trips/models';\nimport type { GetDeparturesRequestDto, GetTripRequestDto, ApiResponse, StopPlaceDto, GetTripResponseDto } from '@/types/webapi';\nimport { injectable } from 'inversify';\nimport type { ISearchService } from '.';\nimport type ServiceOptions from './ServiceOptions';\nimport { DateType } from '@/features/common/models';\nimport { ApiService } from './ApiService';\n\n@injectable()\nexport class SearchService extends ApiService implements ISearchService {\n async searchForTrips(searchRequest: TripSearchRequest, options?: ServiceOptions) {\n return this.executeSearch(searchRequest, 'get', options);\n }\n\n async searchForMoreTrips(searchRequest: TripSearchRequest, options?: ServiceOptions) {\n return this.executeSearch(searchRequest, 'post', options);\n }\n\n async executeSearch(\n searchRequest: TripSearchRequest,\n method: 'get' | 'post',\n options?: ServiceOptions\n ): Promise<GetTripResponseDto | null> {\n const { modes, walkSpeed: walkSpeedType, transferSlack, showTripsWithTransfers, lines } = searchRequest.filters;\n const walkSpeed = this.getWalkSpeed(walkSpeedType);\n\n const params: GetTripRequestDto = {\n fromPlaceId: searchRequest.from?.id,\n toPlaceId: searchRequest.to?.id,\n dateTime: searchRequest.dateTimeType !== DateType.Now ? searchRequest.dateTime : undefined,\n arriveBy: searchRequest.dateTimeType === DateType.ArriveBy || undefined,\n modes: modes.length ? modes.join(',') : undefined,\n lines: lines.length ? lines.join(',') : undefined,\n walkSpeed,\n transferSlack,\n maximumTransfers: showTripsWithTransfers ? undefined : 1,\n nextPageCursors: searchRequest.nextPageCursors,\n previousPageCursors: searchRequest.previousPageCursors\n };\n\n const response =\n method == 'get'\n ? await this.axios.get<GetTripResponseDto>('/api/v1.0/trips', {\n signal: options?.signal,\n params\n })\n : await this.axios.post<GetTripResponseDto>('/api/v1.0/trips', params, { signal: options?.signal });\n\n const { data, meta } = response.data;\n if (!data) return null;\n\n return { data, meta };\n }\n\n async searchForDepartures(request: DeparturesSearchRequest, options?: ServiceOptions | undefined): Promise<StopPlaceDto | null> {\n if (!request.quay?.id) throw new Error('Required param missing');\n\n const { modes } = request.filters;\n\n const params: GetDeparturesRequestDto = {\n id: request.quay.id,\n dateTime: request.dateTime,\n modes: modes.length ? modes.join(',') : undefined\n };\n\n const response = await this.axios.get<ApiResponse<StopPlaceDto>>('/api/v1.0/departures', {\n signal: options?.signal,\n params\n });\n\n return response.data.data;\n }\n\n private getWalkSpeed(type: WalkSpeedType) {\n switch (type) {\n case WalkSpeedType.Fast:\n return 2.0;\n case WalkSpeedType.Slow:\n return 0.6;\n default:\n return 1.3;\n }\n }\n}\n","import type { PlaceAutocompleteModelDto, ApiResponse } from '@/types/webapi';\nimport { AxiosInstance, IAxiosId } from '@/plugins/axios';\nimport { inject, injectable } from 'inversify';\nimport type { IPlaceService, IPlaceServiceOptions } from '.';\nimport ServiceOptions from './ServiceOptions';\nimport { type LatLngLiteral } from 'leaflet';\n\n@injectable()\nexport class PlaceService implements IPlaceService {\n @inject(IAxiosId)\n protected axios: AxiosInstance;\n\n async getPlacesAutocomplete(keyword: string, options?: IPlaceServiceOptions) {\n const response = await this.axios.get<ApiResponse<PlaceAutocompleteModelDto[]>>('/api/v1.0/places/autocomplete', {\n signal: options?.signal,\n params: {\n keyword,\n origin: options?.origin ? options?.origin.lat + ',' + options?.origin.lng : null,\n stopPlacesOnly: options?.stopPlacesOnly || false\n }\n });\n\n return response.data.data || [];\n }\n\n async getPlaceDetails(id: string, options?: ServiceOptions): Promise<PlaceAutocompleteModelDto | null> {\n const response = await this.axios.get<ApiResponse<PlaceAutocompleteModelDto>>(`/api/v1.0/places/details/${id}`, {\n signal: options?.signal\n });\n\n return response.data.data || null;\n }\n\n async getPlaceDetailsForGeolocation(\n latLng: LatLngLiteral,\n options?: ServiceOptions | undefined\n ): Promise<PlaceAutocompleteModelDto | null> {\n const response = await this.axios.get<ApiResponse<PlaceAutocompleteModelDto>>(\n `/api/v1.0/places/lookup?coordinates=${latLng.lat},${latLng.lng}`,\n {\n signal: options?.signal\n }\n );\n\n return response.data.data || null;\n }\n}\n","import { ApiResponse, type AppConfigDto } from '@/types/webapi';\nimport { IConfigService } from './IConfigService';\nimport { inject, injectable } from 'inversify';\nimport { AxiosInstance, IAxiosId } from '@/plugins/axios';\nimport { useMainStore } from '@/features/common/stores';\n\n@injectable()\nexport class AppConfigService implements IConfigService {\n @inject(IAxiosId)\n protected axios: AxiosInstance;\n\n _mainStore: ReturnType<typeof useMainStore>;\n get mainStore(): ReturnType<typeof useMainStore> {\n if (!this._mainStore) {\n this._mainStore = useMainStore();\n }\n\n return this._mainStore;\n }\n\n getConfig() {\n return new Promise<AppConfigDto>((resolve, reject) => {\n this.axios\n .get<ApiResponse<AppConfigDto>>('/api/v1.0/config')\n .then(response => resolve(response.data.data))\n .catch(e => {\n this.mainStore.registerError(e);\n reject(e);\n });\n });\n }\n}\n","import { ApiResponse, LineDto } from '@/types/webapi';\nimport { ILinesService, ILinesServiceOptions } from '.';\nimport { inject, injectable } from 'inversify';\nimport { IAxiosId } from '@/plugins/axios';\nimport { AxiosInstance } from 'axios';\n\n@injectable()\nexport class LinesService implements ILinesService {\n @inject(IAxiosId)\n protected axios: AxiosInstance;\n\n async getAllLines(options?: ILinesServiceOptions | undefined): Promise<LineDto[]> {\n const response = await this.axios.get<ApiResponse<LineDto[]>>('/api/v1.0/lines', { signal: options?.signal });\n\n return response.data.data;\n }\n}\n","import { injectable } from 'inversify';\nimport { GetBookingsFilter, GetStopOrderParams, IBookingService } from './IBookingService';\nimport { ApiResponse, BookingDto, CreateBookingDto, StopOrderDto } from '@/types/webapi';\nimport { format } from 'date-fns';\nimport ServiceOptions from './ServiceOptions';\nimport { ApiService } from './ApiService';\n\n@injectable()\nexport class BookingService extends ApiService implements IBookingService {\n getAllBookings(options?: ServiceOptions): Promise<BookingDto[]> {\n return this.getBookings(undefined, options);\n }\n\n getBookings(params?: GetBookingsFilter, options?: ServiceOptions): Promise<BookingDto[]> {\n return new Promise<BookingDto[]>((resolve, reject) => {\n this.axios\n .get<ApiResponse<BookingDto[]>>('/api/v1.0/bookings/my', { params, signal: options?.signal })\n .then(response => resolve(response.data.data))\n .catch(reject);\n });\n }\n\n getBooking(id: string): Promise<BookingDto> {\n return new Promise<BookingDto>((resolve, reject) => {\n this.axios\n .get<ApiResponse<BookingDto>>(`/api/v1.0/bookings/${id}`)\n .then(response => resolve(response.data.data))\n .catch(reject);\n });\n }\n\n createBooking(params: CreateBookingDto): Promise<BookingDto> {\n return new Promise<BookingDto>((resolve, reject) => {\n this.axios\n .post<ApiResponse<BookingDto>>('/api/v1.0/bookings', params)\n .then(response => resolve(response.data.data))\n .catch(reject);\n });\n }\n\n cancelBooking(id: string): Promise<BookingDto> {\n return new Promise((resolve, reject) => {\n this.axios\n .put<ApiResponse<BookingDto>>(`/api/v1.0/bookings/${id}/cancel`)\n .then(response => resolve(response.data.data))\n .catch(reject);\n });\n }\n\n getStopOrder(params: GetStopOrderParams, options?: ServiceOptions): Promise<StopOrderDto | undefined> {\n return new Promise((resolve, reject) => {\n const { activeDate, serviceJourneyRef, stopSequence } = params;\n\n this.axios\n .get<ApiResponse<StopOrderDto>>(\n `/api/v1.0/stop-orders/${format(activeDate, 'yyyy-MM-dd')}/${serviceJourneyRef}/${stopSequence}`,\n {\n signal: options?.signal\n }\n )\n .then(response => resolve(response.data.data || undefined))\n .catch(reject);\n });\n }\n}\n","import { Container } from 'inversify';\nimport { ax, AxiosInstance, IAxiosId } from './axios';\nimport { InjectionKey, Plugin, inject } from 'vue';\nimport {\n IBookingService,\n IBookingServiceId,\n IPlaceService,\n IPlaceServiceId,\n ISearchService,\n ISearchServiceId,\n IConfigService,\n IConfigServiceId,\n ILinesService,\n ILinesServiceId\n} from '@/services';\nimport { SearchService } from '@/services/SearchService';\nimport { PlaceService } from '@/services/PlaceService';\nimport { AppConfigService } from '@/services/AppConfigService';\nimport { LinesService } from '@/services/LinesService';\nimport { BookingService } from '@/services/BookingService';\n\nconst __INVERSIFY_SYMBOL__ = Symbol.for('app-inversify-container');\nconst injectionKey: InjectionKey<Container> = __INVERSIFY_SYMBOL__;\n\nexport function createContainer(): Plugin {\n const container = new Container();\n\n container.bind<AxiosInstance>(IAxiosId).toConstantValue(ax);\n\n container.bind<IPlaceService>(IPlaceServiceId).to(PlaceService).inSingletonScope();\n container.bind<ISearchService>(ISearchServiceId).to(SearchService).inSingletonScope();\n container.bind<IConfigService>(IConfigServiceId).to(AppConfigService);\n container.bind<ILinesService>(ILinesServiceId).to(LinesService).inSingletonScope();\n container.bind<IBookingService>(IBookingServiceId).to(BookingService).inSingletonScope();\n\n return {\n install(app) {\n app.provide(injectionKey, container);\n }\n };\n}\n\nexport function useContainer() {\n const _container = inject(injectionKey);\n if (!_container) throw new Error('You must call createContainer() first');\n\n return _container;\n}\n","import { useContainer } from '@/plugins/inversify';\nimport { IConfigService, IConfigServiceId } from '@/services/IConfigService';\nimport { AppConfigDto } from '@/types/webapi';\nimport { MenuStructure, useMenuProvider } from '@geta/kolumbus-frontend/composables';\nimport { isNull, isObject, isUndefined, merge } from 'lodash-es';\nimport { defineStore } from 'pinia';\nimport { computed, ref } from 'vue';\nimport { DevModeConfiguration } from '../models';\nimport { startOfMinute } from 'date-fns';\n\nexport enum SearchMode {\n None = 0,\n Trip = 1,\n Departures = 2\n}\n\nexport const useMainStore = defineStore('mainStore', () => {\n const container = useContainer();\n const configService = container.get<IConfigService>(IConfigServiceId);\n\n const ready = ref(false);\n const isLoading = ref(false);\n const language = ref<string>(document.documentElement.lang || 'no');\n const isDebugMode = computed(() => !!config.value.isDebugModeEnabled);\n const searchMode = ref<SearchMode>(SearchMode.Trip);\n const defaultConfig = ref<AppConfigDto>();\n const config = ref<AppConfigDto & { supportedLanguages: string[] }>({\n kolumbusWebsiteBaseUrl: '',\n supportedLanguages: ['no', 'en'],\n googleMapsConfig: {\n apiKey: '',\n center: {\n latitude: 58.97,\n longitude: 5.7331\n }\n },\n silentLoginEnabled: true,\n defaultCulture: 'no',\n isDebugModeEnabled: false,\n devModeEnabled: false,\n searchConfig: {\n directSearchEnabled: false\n }\n });\n const menuItems = ref<MenuStructure>({ baseUrl: '/' });\n const lastKnownError = ref<Error | null>(null);\n const showAppDrawer = ref(true);\n const isDevMode = ref(false);\n const devModeConfiguration = ref<DevModeConfiguration | undefined>();\n\n const menu = computed(() => menuItems.value);\n const currentTime = ref<Date>(startOfMinute(new Date()));\n\n async function loadConfig() {\n try {\n // fetch app config\n defaultConfig.value = await configService.getConfig();\n\n // set up app state\n const supportedLanguages = merge(['no', 'en'], menuItems.value.supportedLanguages?.map(l => l.code) || []);\n config.value = merge(config.value, defaultConfig.value, { supportedLanguages });\n } catch (e) {\n registerError(e);\n }\n }\n\n async function init() {\n try {\n isLoading.value = true;\n\n // set up menus\n const menuProvider = useMenuProvider(config.value.kolumbusWebsiteBaseUrl);\n menuItems.value = await menuProvider.getMenuItems();\n } catch (e) {\n registerError(e);\n } finally {\n isLoading.value = false;\n }\n }\n\n function toggleSearch() {\n searchMode.value = searchMode.value === SearchMode.None ? SearchMode.Trip : SearchMode.None;\n }\n\n function registerError(error: any) {\n lastKnownError.value = isErrorWithMessage(error) ? error : new Error(String(error));\n }\n\n function updateCurrentTime() {\n currentTime.value = startOfMinute(new Date());\n }\n\n const toExactMinute = 60000 - (new Date().getTime() % 60000); // calculate how many milliseconds to next exact minute\n setTimeout(() => {\n // set interval to update currentTime to exact minute\n setInterval(updateCurrentTime, 60000);\n // update currentTime to exact minute\n updateCurrentTime();\n }, toExactMinute);\n\n return {\n ready,\n isLoading,\n language,\n isDebugMode,\n searchMode,\n defaultConfig,\n config,\n menuItems,\n lastKnownError,\n showAppDrawer,\n isDevMode,\n devModeConfiguration,\n currentTime,\n menu,\n init,\n loadConfig,\n toggleSearch,\n registerError\n };\n});\n\nfunction isErrorWithMessage(error: unknown): error is Error {\n return !isUndefined(error) && !isNull(error) && isObject(error) && 'message' in error && typeof error.message === 'string';\n}\n","/**\n * This is a TypeGen auto-generated file.\n * Any changes made to this file can be lost when this file is regenerated.\n */\n\nexport enum GetTripModeDto {\n Air = 'air',\n Bicycle = 'bicycle',\n Bus = 'bus',\n CarFerry = 'carFerry',\n PassengerFerry = 'passengerFerry',\n Rail = 'rail',\n Express = 'express',\n Foot = 'foot',\n AirportBus = 'airportBus',\n}\n","/**\n * This is a TypeGen auto-generated file.\n * Any changes made to this file can be lost when this file is regenerated.\n */\n\nexport enum TripMode {\n Air = 0,\n Bicycle = 1,\n Bus = 2,\n Cableway = 3,\n Water = 4,\n Funicular = 5,\n Lift = 6,\n Rail = 7,\n Metro = 8,\n Taxi = 9,\n Tram = 10,\n Trolleybus = 11,\n Monorail = 12,\n Coach = 13,\n Foot = 14,\n Car = 15,\n Scooter = 16,\n}\n","/**\n * This is a TypeGen auto-generated file.\n * Any changes made to this file can be lost when this file is regenerated.\n */\n\nexport enum PlaceType {\n Unknown = 0,\n Point = 1,\n TransitStation = 2,\n}\n","/**\n * This is a TypeGen auto-generated file.\n * Any changes made to this file can be lost when this file is regenerated.\n */\n\nexport enum TransportMode {\n None = 0,\n Unknown = 1,\n Bus = 2,\n Water = 3,\n Bike = 4,\n Rail = 5,\n Air = 6,\n Tram = 7,\n Coach = 8,\n Metro = 9,\n}\n","/**\n * This is a TypeGen auto-generated file.\n * Any changes made to this file can be lost when this file is regenerated.\n */\n\nexport enum NotificationMessageType {\n None = 0,\n BookingArrangement = 1,\n Notice = 2,\n Warning = 3,\n Deviation = 4,\n Information = 5,\n Cancellation = 6,\n BookingConfirmation = 7,\n OnlineBookingArrangement = 8,\n}\n","/**\n * This is a TypeGen auto-generated file.\n * Any changes made to this file can be lost when this file is regenerated.\n */\n\nexport enum BookingStatus {\n Unknown = 0,\n Created = 1,\n Completed = 10,\n Cancelled = 99,\n}\n","/**\n * This is a TypeGen auto-generated file.\n * Any changes made to this file can be lost when this file is regenerated.\n */\n\nexport enum BookingMethod {\n Unknown = 0,\n CallDriver = 1,\n CallOffice = 2,\n Online = 3,\n PhoneAtStop = 4,\n Text = 5,\n}\n","import { isUndefined } from 'lodash-es';\nimport { computed } from 'vue';\nimport { useI18n } from 'vue-i18n';\nimport { GeolocationError } from '../models';\n\nfunction _getGeolocation(abortController?: AbortController): Promise<GeolocationPosition | null> {\n return new Promise((resolve, reject) => {\n if (abortController) {\n abortController.signal.addEventListener('abort', () => resolve(null));\n }\n\n navigator.geolocation.getCurrentPosition(\n position => {\n if (abortController?.signal.aborted) return;\n\n resolve(position);\n },\n reject,\n { enableHighAccuracy: true, timeout: 30000 }\n );\n });\n}\n\nexport function useGeolocationHelper() {\n const { t } = useI18n();\n const isSupported = computed(() => !isUndefined(navigator.geolocation));\n\n async function getCurrentPosition(abortController?: AbortController) {\n // abort any existing requests\n abortController?.abort();\n\n try {\n // reset abortController\n abortController = new AbortController();\n // request for geolocation\n const position = await _getGeolocation(abortController);\n // set if geolocation is valid\n if (!position)\n throw new GeolocationError(\n t('places.resources.errorMessages.geolocationGeneralError', 'Geolocation failed. Please try again.')\n );\n\n return position;\n } catch (e) {\n if (e instanceof GeolocationPositionError) {\n switch (e.code) {\n case 1:\n throw new GeolocationError(\n t(\n 'places.resources.errorMessages.geolocationPermissionError',\n 'Please allow the browser to access your location.'\n )\n );\n\n default:\n throw new GeolocationError(\n t('places.resources.errorMessages.geolocationGeneralError', 'Geolocation failed. Please try again.')\n );\n }\n }\n\n throw e;\n }\n }\n\n return {\n isSupported,\n getCurrentPosition\n };\n}\n","<template>\n <l-layer-group>\n <l-circle :lat-lng=\"latLng\" :visible=\"visible\" v-bind=\"circleProps\">\n <l-circle-marker :lat-lng=\"latLng\" :visible=\"visible\" v-bind=\"circleMarkerProps\" />\n </l-circle>\n </l-layer-group>\n</template>\n\n<script setup lang=\"ts\">\nimport { LLayerGroup, LCircle, LCircleMarker } from '@vue-leaflet/vue-leaflet';\nimport { CircleMarkerOptions, CircleOptions, LatLngExpression } from 'leaflet';\nimport { computed } from 'vue';\nimport colors from '@geta/kolumbus-frontend/styles/colors.module.scss';\n\ninterface Props {\n modelValue: GeolocationCoordinates;\n visible?: boolean;\n}\n\nconst props = defineProps<Props>();\n\nconst latLng = computed<LatLngExpression>(() => ({ lat: props.modelValue.latitude, lng: props.modelValue.longitude }));\nconst circleRadius = computed(() => props.modelValue.accuracy || 0);\n\nconst circleMarkerProps: CircleMarkerOptions = {\n stroke: true,\n color: colors.white,\n weight: 2,\n fill: true,\n fillColor: colors.blue,\n fillOpacity: 1,\n interactive: false,\n pane: 'markerPane',\n radius: 10\n};\n\nconst circleProps = computed<CircleOptions>(() => ({\n color: colors.blue,\n opacity: 0.1,\n fillColor: colors.blue,\n fillOpacity: 0.1,\n interactive: false,\n radius: circleRadius.value,\n pane: 'markerPane'\n}));\n</script>\n","import {\n type LatLngBoundsExpression,\n type LatLngExpression,\n type PointExpression,\n type PointTuple,\n LatLngBounds,\n Map,\n point\n} from 'leaflet';\nimport { type Ref } from 'vue';\nimport { type LMap } from '@vue-leaflet/vue-leaflet';\nimport { isArray, isEmpty, isUndefined } from 'lodash-es';\n\nexport interface PaddingOptions {\n padding?: PointTuple;\n paddingTopLeft?: PointTuple;\n paddingBottomRight?: PointTuple;\n}\n\nexport function useMapHelpers(map: Ref<typeof LMap | undefined>) {\n function calcPaddingOffset(options?: PaddingOptions): PointExpression {\n if (isEmpty(options)) return [0, 0];\n\n const _paddingTL: PointTuple = isArray(options.paddingTopLeft)\n ? options.paddingTopLeft\n : isArray(options.padding)\n ? options.padding\n : [0, 0],\n _paddingBR: PointTuple = isArray(options.paddingBottomRight)\n ? options.paddingBottomRight\n : isArray(options.padding)\n ? options.padding\n : [0, 0];\n\n const paddingTL = point(_paddingTL),\n paddingBR = point(_paddingBR);\n\n return paddingBR.subtract(paddingTL).divideBy(2);\n }\n\n function addOffsets(latLng: LatLngExpression, zoom: number, options?: PaddingOptions): LatLngExpression {\n if (!map.value?.ready || isEmpty(options)) return latLng;\n\n const leafletObject = map.value.leafletObject as Map;\n const paddingOffset = calcPaddingOffset(options);\n\n return leafletObject.unproject(leafletObject.project(latLng, zoom).add(paddingOffset), zoom);\n }\n\n function removeOffsets(latLng: LatLngExpression, zoom: number, options?: PaddingOptions): LatLngExpression {\n if (!map.value?.ready || isEmpty(options)) return latLng;\n\n const leafletObject = map.value.leafletObject as Map;\n const paddingOffset = calcPaddingOffset(options);\n\n return leafletObject.unproject(leafletObject.project(latLng, zoom).subtract(paddingOffset), zoom);\n }\n\n return {\n addOffsets,\n removeOffsets\n };\n}\n\nexport function isLeafletMap(value: unknown): value is Map {\n return !isUndefined(value) && value instanceof Map;\n}\n\nexport function isLatLngBounds(value: LatLngBoundsExpression): value is LatLngBounds {\n return !isUndefined(value) && value instanceof LatLngBounds;\n}\n","import { DepartureDto, LegDto, QuayDto, PointsOnLinkDto } from '@/types/webapi';\nimport type { Feature, LineString, Point } from 'geojson';\nimport { isEmpty } from 'lodash-es';\n\n// Ref: https://jsfiddle.net/welesley/tw7qLvh4/2/\n\n/**\n * Decodes to a [latitude, longitude] coordinates array.\n *\n * This is adapted from the implementation in Project-OSRM.\n *\n * @param {String} str\n * @param {Number} precision\n * @returns {Array}\n *\n * @see https://github.com/Project-OSRM/osrm-frontend/blob/master/WebContent/routing/OSRM.RoutingGeometry.js\n */\nfunction _decode(str: string, precision: number = 5): number[][] {\n if (!str) return [];\n\n let index = 0,\n lat = 0,\n lng = 0,\n coordinates = [],\n shift = 0,\n result = 0,\n byte = null,\n latitude_change,\n longitude_change,\n factor = Math.pow(10, precision || 5);\n\n // Coordinates have variable length when encoded, so just keep\n // track of whether we've hit the end of the string. In each\n // loop iteration, a single coordinate is decoded.\n while (index < str.length) {\n // Reset shift, result, and byte\n byte = null;\n shift = 0;\n result = 0;\n\n do {\n byte = str.charCodeAt(index++) - 63;\n result |= (byte & 0x1f) << shift;\n shift += 5;\n } while (byte >= 0x20);\n\n latitude_change = result & 1 ? ~(result >> 1) : result >> 1;\n\n shift = result = 0;\n\n do {\n byte = str.charCodeAt(index++) - 63;\n result |= (byte & 0x1f) << shift;\n shift += 5;\n } while (byte >= 0x20);\n\n longitude_change = result & 1 ? ~(result >> 1) : result >> 1;\n\n lat += latitude_change;\n lng += longitude_change;\n\n coordinates.push([lat / factor, lng / factor]);\n }\n\n return coordinates;\n}\n\n/**\n * Encodes a [latitude, longitude] coordinates array to a polyline string.\n *\n * This is adapted from the implementation in Project-OSRM.\n *\n * @param {Array} coordinates\n * @param {Number} precision\n * @returns {String}\n *\n * @see https://github.com/Project-OSRM/osrm-frontend/blob/master/WebContent/routing/OSRM.RoutingGeometry.js\n */\nexport function encode(coordinates: number[][], precision: number = 5): string {\n if (!coordinates.length) return '';\n\n const output: string[] = [];\n let prevLat = 0;\n let prevLng = 0;\n const factor = Math.pow(10, precision);\n\n const encodeValue = (value: number) => {\n // ZigZag encode signed integers to unsigned\n let val = (value << 1) ^ (value >> 31);\n do {\n let byte = val & 0x1f;\n val = val >> 5;\n if (val !== 0) {\n byte |= 0x20;\n }\n output.push(String.fromCharCode(byte + 63));\n } while (val !== 0);\n };\n\n for (const [lat, lng] of coordinates) {\n const currentLat = Math.round(lat * factor);\n const currentLng = Math.round(lng * factor);\n\n // Calculate deltas from previous coordinates\n encodeValue(currentLat - prevLat);\n encodeValue(currentLng - prevLng);\n\n prevLat = currentLat;\n prevLng = currentLng;\n }\n\n return output.join('');\n}\n\n/**\n * Decodes to a GeoJSON LineString geometry.\n *\n * @param {String} str\n * @param {Number} precision\n * @returns {LineString}\n */\nfunction toLineString(str: string, precision: number = 5): LineString {\n var coords = _decode(str, precision);\n return {\n type: 'LineString',\n coordinates: coords.reduce<number[][]>((acc, curr) => {\n acc.push(curr.slice().reverse());\n\n return acc;\n }, [])\n };\n}\n\n/**\n * Decodes all given point links to a GeoJSON LineString geometry.\n *\n * @param {PointsOnLinkDto[]} point links\n * @param {Number} precision\n * @returns {LineString}\n */\nfunction pointsToLineString(points: PointsOnLinkDto[], precision: number = 5): LineString {\n const lines = points.reduce<LineString[]>((acc, curr) => {\n acc.push(toLineString(curr.points, precision));\n return acc;\n }, []);\n\n return {\n type: 'LineString',\n coordinates: lines.flatMap(l => l.coordinates)\n };\n}\n\nexport type LegLineStringProperties = Omit<LegDto, 'pointsOnLink'> & { [key: string]: any };\n\nexport type DepartureLineStringProperties = Omit<DepartureDto, 'pointsOnLink'> & { [key: string]: any };\n\nexport type QuayPointProperties = Omit<QuayDto, 'coordinates'> & { [key: string]: any };\n\nexport function useGeojsonHelper() {\n function mapLegToLineString(leg: LegDto): Feature<LineString, LegLineStringProperties> | null {\n if (!leg || isEmpty(leg)) return null;\n\n const { pointsOnLink, ...properties } = leg;\n if (!pointsOnLink?.length) return null;\n\n return {\n type: 'Feature',\n geometry: pointsToLineString(pointsOnLink),\n properties\n };\n }\n\n function mapDepartureToLineString(departure: DepartureDto): Feature<LineString, DepartureLineStringProperties> | null {\n if (!departure || isEmpty(departure.pointsOnLink)) return null;\n\n const { pointsOnLink: _, ...properties } = departure;\n\n return {\n type: 'Feature',\n geometry: toLineString(departure.pointsOnLink.points),\n properties\n };\n }\n\n function mapQuayToPoint(quay: QuayDto): Feature<Point, QuayPointProperties> | null {\n if (!quay || isEmpty(quay?.coordinates)) return null;\n\n const {\n coordinates: { latitude, longitude },\n ...properties\n } = quay;\n\n return {\n id: properties.id,\n type: 'Feature',\n geometry: {\n type: 'Point',\n coordinates: [longitude, latitude]\n },\n properties\n };\n }\n\n return {\n mapLegToLineString,\n mapQuayToPoint,\n mapDepartureToLineString,\n toLineString\n };\n}\n","/// <reference types=\"leaflet-contextmenu\" />\nimport { type ContextMenuItem, LatLngBounds, type LatLngExpression, type PointTuple } from 'leaflet';\nimport { defineStore } from 'pinia';\nimport { useMainStore } from '@/features/common/stores';\nimport { computed, reactive, toRefs, watch } from 'vue';\n\nconst useMapStore = defineStore('mapStore', () => {\n const mainStore = useMainStore();\n\n const state = reactive({\n center: { lat: 58.97, lng: 5.7331 } as LatLngExpression,\n zoom: 15,\n bounds: new LatLngBounds([\n [0, 0],\n [0, 0]\n ]),\n userLocation: null as GeolocationCoordinates | null,\n paddingTopLeft: undefined as PointTuple | undefined,\n paddingBottomRight: undefined as PointTuple | undefined,\n grayscale: false,\n contextmenu: undefined as ContextMenuItem[] | undefined\n });\n\n const googleMutantOptions = computed(() => ({\n apiKey: mainStore.config.googleMapsConfig.apiKey,\n mapId: mainStore.config.googleMapsConfig.cloudStyleMapId\n }));\n\n watch(\n () => mainStore.config.googleMapsConfig.center,\n value => {\n const { latitude: lat, longitude: lng } = value;\n state.center = { lat, lng };\n },\n { deep: true }\n );\n\n return {\n ...toRefs(state),\n googleMutantOptions\n };\n});\n\nexport default useMapStore;\n","import { useGeolocationHelper } from '@/features/common/composables';\nimport { useMapStore } from '@/features/map/stores';\nimport { storeToRefs } from 'pinia';\nimport { useMainStore } from '@/features/common/stores';\nimport { computed } from 'vue';\nimport { PointTuple } from 'leaflet';\nimport { useDisplay } from 'vuetify';\n\nexport const defaultPadding = 25;\n\nexport function useMapUnderlay() {\n const { mobile: isMobile } = useDisplay();\n const { showAppDrawer } = storeToRefs(useMainStore());\n const mapStore = useMapStore();\n const { userLocation, paddingTopLeft, paddingBottomRight: _paddingBottomRight, ...storeRefs } = storeToRefs(mapStore);\n const { isSupported, getCurrentPosition } = useGeolocationHelper();\n\n let abortController: AbortController;\n async function locateUser() {\n // abort any existing requests\n abortController?.abort();\n\n try {\n // reset abortController\n abortController = new AbortController();\n // request for geolocation\n const position = await getCurrentPosition(abortController);\n // set if geolocation is valid\n if (position) {\n userLocation.value = position.coords;\n }\n } catch (e) {\n userLocation.value = null;\n\n throw e;\n }\n }\n\n // set bottom padding based on drawer height in mobile mode - this is set by relevant pages\n const paddingBottomRight = computed(() => (showAppDrawer.value && isMobile.value ? _paddingBottomRight.value : undefined));\n\n return {\n ...storeRefs,\n padding: [defaultPadding, defaultPadding] as PointTuple,\n paddingTopLeft,\n paddingBottomRight,\n userLocation,\n canUseGeolocation: isSupported,\n locateUser\n };\n}\n","<template>\n <l-map\n ref=\"map\"\n v-model:center=\"_center\"\n v-model:zoom=\"_zoom\"\n :options=\"mapOptions\"\n @ready=\"onMapReady\"\n @update:bounds=\"_bounds = $event\"\n >\n <template v-if=\"ready\">\n <l-google-mutant v-bind=\"googleMutantOptions\" :class=\"cssClasses\" />\n <l-control-attribution\n position=\"bottomright\"\n prefix=\"<a href='https://leafletjs.com' target='_blank' title='A JavaScript library for interactive maps'>Leaflet</a>\"\n />\n <l-control v-if=\"!isMobile\" position=\"bottomright\" class=\"d-flex flex-column\">\n <v-btn v-if=\"canUseGeolocation\" fab class=\"ma-1\" icon=\"mdi-crosshairs-gps\" size=\"large\" @click=\"emit('locate-user')\" />\n <v-btn fab class=\"ma-1\" icon=\"mdi-plus\" size=\"large\" @click=\"zoomIn\" />\n <v-btn fab class=\"ma-1\" icon=\"mdi-minus\" size=\"large\" @click=\"zoomOut\" />\n </l-control>\n <geolocation-marker v-if=\"userLocation\" :model-value=\"userLocation\" />\n <slot />\n </template>\n </l-map>\n</template>\n\n<script setup lang=\"ts\">\nimport 'leaflet/dist/leaflet.css';\nimport 'leaflet-contextmenu/dist/leaflet.contextmenu.min.css';\nimport 'leaflet-contextmenu';\nimport { LMap, LControl, LControlAttribution } from '@vue-leaflet/vue-leaflet';\nimport { ContextMenuItem, LatLngBoundsExpression, LatLngExpression, Map, MapOptions, PointTuple, latLngBounds } from 'leaflet';\nimport { computed, nextTick, ref, watch } from 'vue';\nimport LGoogleMutant from '@geta/vue-leaflet-googlemutant';\nimport { GeolocationMarker } from '..';\nimport { useVModel } from '@vueuse/core';\nimport { isLatLngBounds, isLeafletMap, useMapHelpers } from './mapHelpers';\nimport { isEmpty, merge } from 'lodash-es';\nimport { defaultPadding } from '@/features/map/composables';\nimport { useDisplay } from 'vuetify';\n\ninterface GoogleMutantOptions {\n apiKey: string;\n mapId?: string;\n}\n\ninterface Props {\n center: LatLngExpression;\n zoom: number;\n bounds: LatLngBoundsExpression;\n userLocation?: GeolocationCoordinates | null;\n canUseGeolocation?: boolean;\n grayscale?: boolean;\n contextmenu?: ContextMenuItem[];\n padding?: PointTuple;\n paddingTopLeft?: PointTuple;\n paddingBottomRight?: PointTuple;\n googleMutantOptions?: GoogleMutantOptions;\n}\n\ninterface Emits {\n (e: 'update:center', value: LatLngExpression): void;\n (e: 'update:zoom', value: number): void;\n (e: 'update:bounds', value: LatLngBoundsExpression): void;\n (e: 'locate-user'): void;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n padding: () => [defaultPadding, defaultPadding],\n contextmenu: () => []\n});\nconst emit = defineEmits<Emits>();\n\nconst map = ref<typeof LMap>();\nconst ready = ref(false);\n\nconst { mobile: isMobile } = useDisplay();\n\nconst { addOffsets } = useMapHelpers(map);\n\nconst _center = useVModel(props, 'center', emit);\nconst _zoom = useVModel(props, 'zoom', emit);\nconst _bounds = useVModel(props, 'bounds', emit);\n\nconst googleMutantOptions = computed(() => ({\n loaderOptions: {\n apiKey: props.googleMutantOptions?.apiKey || ''\n },\n mapId: props.googleMutantOptions?.mapId\n}));\n\nconst cssClasses = computed(() => ({ 'tilelayer--grayscale': props.grayscale }));\n\nconst mapOptions: MapOptions & { useGlobalLeaflet: boolean } = {\n useGlobalLeaflet: false,\n attributionControl: false,\n zoomControl: false,\n contextmenu: true,\n contextmenuItems: props.contextmenu || []\n};\n\nfunction onMapReady(_map: Map) {\n // add additional map panes\n _map.createPane('servicejourneymarkersPane');\n _map.createPane('servicejourneypolylinesPane');\n\n // set up watcher for contextmenu\n watch(\n () => props.contextmenu,\n value => {\n if (!map.value?.leafletObject) return;\n\n // reset menu items\n map.value.leafletObject.contextmenu.removeAllItems();\n\n if (!value?.length) return;\n\n // add menu items\n value.forEach(item => map.value!.leafletObject.contextmenu.addItem(item));\n },\n {\n immediate: true\n }\n );\n\n nextTick(() => {\n // set initial bounds\n _bounds.value = _map.getBounds();\n\n ready.value = true;\n });\n}\n\nfunction flyTo(latLng: LatLngExpression, zoom?: number) {\n nextTick(() => {\n if (!map.value || !latLng) return;\n\n const leafletObject = map.value.leafletObject as Map;\n const { padding, paddingTopLeft = padding, paddingBottomRight = padding } = props;\n zoom = zoom || _zoom.value;\n\n leafletObject.flyTo(addOffsets(latLng, zoom, { padding, paddingTopLeft, paddingBottomRight }), zoom, { animate: true });\n });\n}\n\nfunction fitBounds(\n value: LatLngBoundsExpression,\n options?: { maxZoom?: number; padding?: PointTuple; paddingTopLeft?: PointTuple; paddingBottomRight?: PointTuple }\n) {\n nextTick(() => {\n // convert to LatLngBounds instance\n if (!isLatLngBounds(value)) value = latLngBounds(value);\n\n if (!map.value || !value || !value.isValid()) return;\n\n const leafletObject = map.value.leafletObject as Map;\n const { padding, paddingTopLeft = padding, paddingBottomRight = padding } = props;\n options = merge({ padding, paddingTopLeft, paddingBottomRight }, options);\n\n leafletObject.fitBounds(value, options);\n });\n}\n\nfunction zoomIn() {\n _zoom.value++;\n}\n\nfunction zoomOut() {\n _zoom.value--;\n}\n\nfunction triggerResize() {\n map.value?.leafletObject?.invalidateSize();\n}\n\nwatch(\n () => props.userLocation,\n value =>\n nextTick(() => {\n if (!value) return;\n\n flyTo({ lat: value.latitude, lng: value.longitude }, 15);\n }),\n { immediate: true }\n);\n\nwatch(_bounds, value => {\n if (!map.value || !isLeafletMap(map.value.leafletObject) || isEmpty(value)) return;\n\n // need to check if paddings have changed, and update as necessary\n if (map.value.leafletObject.getBounds().equals(value)) return;\n\n nextTick(() => fitBounds(value, { maxZoom: 15 }));\n});\n\ndefineExpose({ fitBounds, flyTo, triggerResize });\n</script>\n\n<style lang=\"scss\">\n.leaflet-tile-pane {\n transition:\n 0.2s filter linear,\n 0.2s -webkit-filter linear;\n}\n\n.leaflet-overlay-pane,\n.leaflet-marker-pane,\n.leaflet-servicejourneymarkers-pane,\n.leaflet-servicejourneypolylines-pane {\n svg {\n z-index: inherit;\n }\n}\n\n.leaflet-servicejourneymarkers-pane {\n z-index: 360;\n}\n\n.leaflet-servicejourneypolylines-pane {\n z-index: 350;\n}\n\n.leaflet-container:has(.tilelayer--grayscale) .leaflet-tile-pane {\n filter: grayscale(1);\n}\n\n// override default context menu styles\n.leaflet-contextmenu {\n padding: 8px 0;\n\n a.leaflet-contextmenu-item {\n font-size: 1.1rem;\n }\n}\n</style>\n","import { LatLngExpression } from 'leaflet';\nimport { InjectionKey, Ref } from 'vue';\nimport { useBookingCard, useBookingFormCard } from './features/bookings/composables';\n\ninterface AppProvide {\n currentTime: Ref<Date>;\n setDrawerFullHeight: (fullHeight: boolean) => void;\n}\n\ninterface SearchPageProvide {\n setHeaderVisibility: (value: boolean) => void;\n setHeaderAppendVisibility: (value: boolean) => void;\n setPage: (value: number) => void;\n}\n\ninterface MapUnderlayProvide {\n flyTo(latLng: LatLngExpression, zoom?: number): void;\n}\n\nexport const AppProvideKey: InjectionKey<AppProvide> = Symbol.for('travelplanner:app');\nexport const SearchPageProvideKey: InjectionKey<SearchPageProvide> = Symbol.for('travelplanner:searchWrapper');\nexport const MapUnderlayProvideKey: InjectionKey<MapUnderlayProvide> = Symbol.for('travelplanner:mapUnderlay');\nexport const OnlineBookingIsAvailableKey: InjectionKey<Ref<boolean>> = Symbol.for('travelplanner:onlineBookingIsAvailable');\nexport const BookingCardProvideKey: InjectionKey<ReturnType<typeof useBookingCard>> = Symbol.for('travelplanner:bookingCard');\nexport const BookingFormCardProvideKey: InjectionKey<ReturnType<typeof useBookingFormCard>> = Symbol.for('travelplanner:bookingFormCard');\n","<template>\n <map-underlay\n ref=\"underlay\"\n v-model:center=\"center\"\n v-model:zoom=\"zoom\"\n v-model:bounds=\"bounds\"\n :grayscale=\"grayscale\"\n :contextmenu=\"contextmenu\"\n :google-mutant-options=\"googleMutantOptions\"\n :user-location=\"userLocation\"\n :can-use-geolocation=\"canUseGeolocation\"\n :padding=\"padding\"\n :padding-top-left=\"paddingTopLeft\"\n :padding-bottom-right=\"paddingBottomRight\"\n @locate-user=\"locateUser\"\n >\n <router-view name=\"mapUnderlay\" />\n </map-underlay>\n</template>\n\n<script setup lang=\"ts\">\nimport { MapUnderlay } from '@/features/map/components';\nimport { useMapUnderlay } from '@/features/map/composables';\nimport { MapUnderlayProvideKey } from '@/injectionKeys';\nimport { provide, ref, watch } from 'vue';\nimport { useLayout } from 'vuetify';\n\nconst underlay = ref<typeof MapUnderlay>();\nconst {\n center,\n zoom,\n bounds,\n padding,\n paddingTopLeft,\n paddingBottomRight,\n googleMutantOptions,\n userLocation,\n canUseGeolocation,\n locateUser,\n grayscale,\n contextmenu\n} = useMapUnderlay();\nconst { mainRect } = useLayout();\n\nprovide(MapUnderlayProvideKey, { flyTo: (latLng, zoom) => underlay.value?.flyTo(latLng, zoom) });\n\n// trigger resize when layout changes\nwatch(mainRect, () => setTimeout(() => underlay.value?.triggerResize(), 200));\n</script>\n","<template>\n <div class=\"search-page\">\n <v-window :model-value=\"page\" :touch=\"false\" class=\"search-page__inner\">\n <v-window-item value=\"0\" :transition=\"!isMobile\">\n <div class=\"search-page__header\">\n <div class=\"search-page__header-content pt-md-6 px-md-6\">\n <search-mode-toggle v-model=\"mode\" class=\"search-page__header-top\" />\n <div class=\"search-page__header-bottom pa-4\">\n <router-view name=\"header\" />\n </div>\n </div>\n <div v-show=\"showHeaderAppend\" class=\"search-page__header-append\">\n <router-view name=\"headerAppend\" />\n </div>\n </div>\n\n <div class=\"search-page__content px-4 pb-4 pt-md-4 px-md-6\">\n <router-view />\n </div>\n </v-window-item>\n <v-window-item value=\"1\" :transition=\"!isMobile\">\n <router-view name=\"page1\" />\n </v-window-item>\n </v-window>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { SearchModeToggle } from '@/features/common/components';\nimport { useSearchModeToggle } from '@/features/common/composables';\nimport { SearchPageProvideKey } from '@/injectionKeys';\nimport { provide, ref, watch } from 'vue';\nimport { useDisplay } from 'vuetify';\n\nconst { mode } = useSearchModeToggle();\nconst { mobile: isMobile } = useDisplay();\n\nconst showHeader = ref(true);\nconst showHeaderAppend = ref(false);\nconst page = ref(0);\n\nfunction setHeaderVisibility(value: boolean) {\n showHeader.value = value;\n}\n\nfunction setHeaderAppendVisibility(value: boolean) {\n showHeaderAppend.value = value;\n}\n\nfunction setPage(value = 0) {\n page.value = value;\n}\n\nprovide(SearchPageProvideKey, { setHeaderVisibility, setHeaderAppendVisibility, setPage });\n\nwatch(isMobile, value => {\n if (!value) {\n setPage(0);\n }\n});\n</script>\n\n<style lang=\"scss\">\n@use '@geta/kolumbus-frontend/styles/vuetify' as *;\n@use 'sass:map';\n\n.search-page {\n --v-search-page-border-color: #e6e6e6;\n\n width: 100%;\n height: 100%;\n\n &__inner {\n height: 100%;\n }\n\n .v-window-item {\n min-height: 100%;\n\n &--active {\n overflow-y: overlay;\n\n &:has(.search-result) {\n --scrollbar-color-track: var(--v-color-grey-lighten-3);\n }\n }\n }\n\n &__header {\n z-index: 1;\n\n &-top,\n &-bottom {\n position: relative;\n }\n\n &-bottom {\n @media #{map.get($display-breakpoints, 'md-and-up')} {\n border: 1px solid var(--v-search-page-border-color);\n border-radius: #{map.get($rounded, 'lg')};\n border-top-left-radius: 0;\n }\n }\n\n &-content,\n &-append {\n position: relative;\n }\n\n &-content {\n z-index: 2;\n }\n\n &-append {\n z-index: 1;\n }\n }\n\n .search-mode-toggle__container {\n position: relative;\n bottom: -1px;\n // offset with margin so we don't end up with empty space at top\n margin-top: -1px;\n }\n\n &:has(.v-autocomplete--active-menu.place-autocomplete) .search-page__content {\n min-height: 500px;\n }\n}\n\n.search-result {\n display: flex;\n flex-direction: column;\n min-height: 100%;\n background: var(--search-result-bg-color);\n\n &__header {\n display: flex;\n\n @media #{map.get($display-breakpoints, 'md-and-up')} {\n min-height: 100px;\n box-shadow:\n 0px 1px 4px 0px rgba(0, 0, 0, 0.1),\n 0px 1px 2px 0px rgba(0, 0, 0, 0.12);\n }\n }\n\n &--mobile {\n background: var(--v-color-white);\n\n .search-result__header,\n .search-result__footer {\n display: flex;\n }\n\n .search-result__footer {\n flex-direction: column;\n justify-content: center;\n background: var(--v-color-white);\n }\n\n &.search-result--expanded {\n background: var(--v-color-grey-lighten-3);\n\n .search-result__content {\n padding-bottom: 80px;\n\n .tp-app--has-focused & {\n padding-bottom: 20px;\n }\n }\n\n .search-result__footer {\n position: fixed;\n width: 100%;\n bottom: 0;\n z-index: 100;\n\n .tp-app--has-focused & {\n position: sticky;\n }\n }\n }\n }\n}\n</style>\n","import { createRouter, createWebHistory } from 'vue-router';\nimport { routeMiddleware } from '@/i18n';\nimport Home from '@/pages/Home.vue';\nimport SearchPageLayout from '@/pages/layouts/SearchPageLayout.vue';\n\nexport const routeNames = {\n home: 'home',\n tripSearch: 'trip-search',\n tripSearchResult: 'trip-search-result',\n departuresSearch: 'departures-search',\n departuresSearchResult: 'departures-search-result',\n notFound: 'not-found',\n bookingDetails: 'booking-details'\n};\n\nconst router = createRouter({\n history: createWebHistory(),\n routes: [\n {\n path: '/:locale?',\n components: {\n main: Home,\n appDrawer: SearchPageLayout\n },\n children: [\n {\n path: '',\n name: routeNames.home,\n redirect: { name: routeNames.tripSearch }\n },\n {\n path: 'search',\n name: routeNames.tripSearch,\n components: {\n default: () => import('@/pages/trips/TripSearchPage.vue'),\n header: () => import('@/pages/trips/TripSearchPageHeader.vue'),\n mapUnderlay: () => import('@/features/common/components/MapComponents/MapComponents.vue'),\n page1: () => import('@/pages/trips/TripSearchDetails.vue')\n }\n },\n {\n path: 'departures',\n name: routeNames.departuresSearch,\n components: {\n default: () => import('@/pages/departures/DeparturesSearchPage.vue'),\n header: () => import('@/pages/departures/DeparturesSearchPageHeader.vue'),\n mapUnderlay: () => import('@/features/common/components/MapComponents/MapComponents.vue'),\n page1: () => import('@/pages/departures/DeparturesSearchDetails.vue')\n }\n },\n {\n path: 'bookings/:id',\n name: routeNames.bookingDetails,\n components: {\n default: () => import('@/pages/bookings/BookingPage.vue'),\n mapUnderlay: () => import('@/features/common/components/MapComponents/MapComponents.vue'),\n page1: () => import('@/pages/bookings/BookingDetailsPage.vue')\n },\n props: {\n default: false,\n page1: true\n }\n }\n ]\n },\n {\n path: '/:pathMatch(.*)*',\n redirect: { name: routeNames.home }\n }\n ]\n});\n\nrouter.beforeEach(routeMiddleware);\n\nexport default router;\n","import { type StorageLike, useStorage } from '@vueuse/core';\nimport { computed, toValue } from 'vue';\n\n// TODO: set up mechanism to change this\nconst maxEntryLength = 3;\n\nexport function usePlaceAutocompleteHistory<T extends { id: string } & unknown>(name: string, storage?: StorageLike) {\n if (!name) throw new Error('You must specify a name for the storage location.');\n\n const historyStorage = useStorage<T[]>(`travelplanner__${name}`, [], storage);\n // readonly modifier for storage list so consumers cannot modify it\n const items = computed(() => historyStorage.value || []);\n\n /**\n * Adds item to history. Removes oldest item if resulting list is longer than maxEntryLength. Promotes existing item to top of list.\n * @param item Item to add to history\n */\n function addItem(item: T) {\n const _items = toValue(items);\n const existingItemIndex = _items.findIndex(x => x.id === item.id);\n\n if (existingItemIndex > -1) {\n // move existing item item to top of list\n const existingItem = _items.splice(existingItemIndex, 1);\n _items.unshift(existingItem[0]);\n } else {\n _items.unshift(item);\n\n // if item exceeds maxEntryLength, remove last item\n if (_items.length > maxEntryLength) _items.pop();\n }\n\n historyStorage.value = _items;\n }\n\n /**\n * Clears all data from storage\n */\n function clear() {\n historyStorage.value = [];\n }\n\n return {\n items,\n addItem,\n clear\n };\n}\n","import { nextTick, watch, WatchHandle } from 'vue';\nimport { useBookingStore } from '../stores';\nimport { useMainStore } from '@/features/common/stores';\nimport { useTripSearchStore } from '@/features/trips/stores';\nimport { useDeparturesSearchStore } from '@/features/departures/stores';\nimport { isAfter, isDate, isSameDay } from 'date-fns';\nimport { storeToRefs } from 'pinia';\nimport { useUserStore } from '@geta/kolumbus-frontend/features/authentication';\nimport { isEmpty } from 'lodash-es';\nimport { DepartureDto, LegDto } from '@/types/webapi';\n\nexport function useBookingFeature() {\n const mainStore = useMainStore();\n const userStore = useUserStore();\n const bookingStore = useBookingStore();\n const tripSearchStore = useTripSearchStore();\n const departureSearchStore = useDeparturesSearchStore();\n const { bookings, maxBookingExceeded, selectedBooking } = storeToRefs(bookingStore);\n const { selectedDeparture, hasResult: hasDepartureResult } = storeToRefs(departureSearchStore);\n const { selectedTripPattern, hasResult: hasTripPatternResult } = storeToRefs(tripSearchStore);\n\n async function loadBookingData(legOrDeparture: LegDto | DepartureDto) {\n if (!legOrDeparture.bookingMetadata) return;\n\n // if booking limit date time has been exceeded, load stop order\n const { bookingLimitDateTime } = legOrDeparture.bookingMetadata;\n if (isDate(bookingLimitDateTime) && isAfter(mainStore.currentTime, bookingLimitDateTime)) {\n await bookingStore.loadStopOrder();\n }\n\n await nextTick();\n\n if (!legOrDeparture.bookingMetadata) return;\n\n // set selected booking based on selected legOrDeparture, if it exists\n selectedBooking.value = bookings.value.find(\n x =>\n x.serviceJourneyRef === legOrDeparture.bookingMetadata!.serviceJourneyRef &&\n isDate(legOrDeparture.bookingMetadata!.activeDate) &&\n isSameDay(x.activeDate, legOrDeparture.bookingMetadata!.activeDate) &&\n x.stopSequence === legOrDeparture.bookingMetadata!.stopSequence\n );\n }\n\n function reset() {\n selectedBooking.value = undefined;\n maxBookingExceeded.value = false;\n }\n\n let resultWatcher: WatchHandle | undefined;\n let tripPatternWatcher: WatchHandle | undefined;\n let departureWatcher: WatchHandle | undefined;\n\n function startWatchers() {\n // load user bookings when hasResult changes\n resultWatcher = watch([hasDepartureResult, hasTripPatternResult], async ([hasDepartureResult, hasTripPatternResult]) => {\n reset();\n\n if (!userStore.isLoggedIn || (!hasDepartureResult && !hasTripPatternResult)) return;\n\n // load user bookings\n await bookingStore.loadBookings();\n });\n\n tripPatternWatcher = watch(\n selectedTripPattern,\n async (value, oldValue) => {\n if (isEmpty(value) || value.id === oldValue?.id) return;\n\n reset();\n\n const bookingLeg = value.legs?.find(x => x.bookingMetadata?.onlineBookingIsAvailable);\n if (!bookingLeg) return;\n\n await loadBookingData(bookingLeg);\n },\n { immediate: true }\n );\n\n departureWatcher = watch(\n selectedDeparture,\n async (value, oldValue) => {\n if (isEmpty(value?.bookingMetadata) || value.isCancelled || value.id === oldValue?.id) return;\n\n reset();\n\n await loadBookingData(value);\n },\n { immediate: true }\n );\n }\n\n function stopWatchers() {\n resultWatcher?.();\n tripPatternWatcher?.();\n departureWatcher?.();\n }\n\n watch(\n () => mainStore.config.bookingConfig?.enabled,\n value => {\n if (value) {\n startWatchers();\n } else {\n stopWatchers();\n }\n },\n {\n immediate: true\n }\n );\n}\n","import { BookingContactDto, BookingDto, BookingMethod, TransportMode } from '@/types/webapi';\nimport { toLocalDate, toLocaleTimeString } from '@geta/kolumbus-frontend/composables';\nimport { addDays, format, formatRelative, isAfter, isDate, isSameDay } from 'date-fns';\nimport { useI18n } from 'vue-i18n';\nimport i18n from '@/i18n';\nimport { enUS as _enUS, nb as _nb } from 'date-fns/locale';\n\nexport interface GenerateDescriptionTextParams {\n fromQuay?: string;\n bookingLimitDateTime?: Date;\n bookingMethods?: BookingMethod[];\n bookingContact?: BookingContactDto;\n transportMode?: TransportMode;\n now?: Date;\n}\n\n// this allows us to use the i18n instance in the store\nconst _i18n = () => {\n try {\n return useI18n();\n } catch {\n return i18n.global;\n }\n};\n\nexport function useBookingMessages() {\n const { t, locale } = _i18n();\n\n // override formatRelative function\n const formatRelativeLocaleEnUS: { [key: string]: string } = {\n lastWeek: \"'last' eeee 'at' HH:mm\",\n yesterday: \"'yesterday at' HH:mm\",\n today: \"'today at' HH:mm\",\n tomorrow: \"'tomorrow at' HH:mm\",\n nextWeek: \"MMMM do 'at' HH:mm\",\n other: 'P'\n };\n const formatRelativeLocaleNb: { [key: string]: string } = {\n lastWeek: \"p 'forrige' eeee\",\n yesterday: \"p 'i går'\",\n today: \"p 'i dag'\",\n tomorrow: \"p 'i morgen'\",\n nextWeek: \"do MMMM 'kl.' p\",\n other: 'P'\n };\n\n const enUS = {\n ..._enUS,\n formatRelative: (token: string): string => formatRelativeLocaleEnUS[token]\n };\n const nb = {\n ..._nb,\n formatRelative: (token: string): string => formatRelativeLocaleNb[token]\n };\n\n const options = { locale: locale.value == 'no' ? nb : enUS };\n\n function generateDescriptionText(params: GenerateDescriptionTextParams) {\n if (!params) return '';\n\n const { fromQuay, bookingLimitDateTime, bookingMethods = [], bookingContact, now = new Date() } = params;\n\n let result: string[] = [];\n if (fromQuay && isDate(bookingLimitDateTime)) {\n let bookingLimitDateTimeString: string;\n\n if (isSameDay(toLocalDate(bookingLimitDateTime), now)) {\n // today\n bookingLimitDateTimeString = t('common.resources.bookingArrangements.beforeTimeToday', [\n toLocaleTimeString(bookingLimitDateTime, locale.value)\n ]);\n } else if (isSameDay(toLocalDate(bookingLimitDateTime), addDays(now, 1))) {\n // tomorrow\n bookingLimitDateTimeString = t('common.resources.bookingArrangements.beforeTimeTomorrow', [\n toLocaleTimeString(bookingLimitDateTime, locale.value)\n ]);\n } else {\n // other dates\n bookingLimitDateTimeString = t('common.resources.bookingArrangements.beforeTimeOtherDay', [\n format(toLocalDate(bookingLimitDateTime), t('booking.resources.dateTimeFormats.weekday'), options),\n toLocaleTimeString(bookingLimitDateTime, locale.value)\n ]);\n }\n\n result.push(\n t('booking.resources.descriptionTexts.bookingOriginAndDeadline', {\n fromQuay,\n bookingLimitDateTime: bookingLimitDateTimeString\n })\n );\n }\n\n if (\n (bookingMethods.includes(BookingMethod.CallDriver) || bookingMethods.includes(BookingMethod.CallOffice)) &&\n bookingContact?.phone\n ) {\n result.push(t('booking.resources.descriptionTexts.bookingMethodTel', { contactPhone: bookingContact.phone }));\n }\n\n return result.join(' ');\n }\n\n function generateDeadlineExpiredDescriptionText(params: GenerateDescriptionTextParams) {\n if (!params) return '';\n\n const { fromQuay, bookingLimitDateTime, bookingMethods = [], bookingContact } = params;\n let result: string[] = [];\n\n if (fromQuay && isDate(bookingLimitDateTime)) {\n let bookingLimitDateTimeAndOrBookingMethod = t('booking.resources.descriptionTexts.bookingLimitTime', [\n toLocaleTimeString(bookingLimitDateTime, locale.value)\n ]);\n\n if (\n (bookingMethods.includes(BookingMethod.CallDriver) || bookingMethods.includes(BookingMethod.CallOffice)) &&\n bookingContact?.phone\n ) {\n bookingLimitDateTimeAndOrBookingMethod += t('booking.resources.descriptionTexts.bookingDeadlineMethodTel', {\n contactPhone: bookingContact.phone\n });\n }\n\n result.push(\n t('booking.resources.descriptionTexts.bookingDeadlineOriginAndDeadline', {\n fromQuay,\n bookingLimitDateTimeAndOrBookingMethod\n })\n );\n }\n\n result.push(`<span class=\"text-error\">${t('booking.resources.descriptionTexts.bookingDeadlineExpired')}</span>`);\n\n return result.join(' ');\n }\n\n function generateBookingExistsDescriptionText(params: GenerateDescriptionTextParams) {\n if (!params) return '';\n\n const { fromQuay, transportMode } = params;\n let result: string[] = [];\n\n if (fromQuay && transportMode) {\n const transportModeString = getTransportMode(transportMode);\n\n result.push(\n t('booking.resources.descriptionTexts.bookingAlreadyMadeByOther', { fromQuay, transportMode: transportModeString })\n );\n }\n\n return result.join(' ');\n }\n\n function generateCancelledBookingDescriptionText(booking: BookingDto, now?: Date) {\n if (!booking) return '';\n\n const { pickupQuayName: quayName, pickupTime: _pickupTime } = booking;\n const localPickupTime = toLocalDate(_pickupTime);\n\n const pickupTime =\n isDate(now) && isAfter(_pickupTime, now)\n ? formatRelative(localPickupTime, now, options)\n : format(localPickupTime, t('booking.resources.dateTimeFormats.weekdayAndTime'), options);\n\n return t('booking.resources.bookingCancelledDescription', { quayName, pickupTime });\n }\n\n function getTransportMode(transportMode: TransportMode) {\n switch (transportMode) {\n case TransportMode.Bus:\n return t('booking.resources.descriptionTexts.bookingTransportModeBus');\n case TransportMode.Water:\n return t('booking.resources.descriptionTexts.bookingTransportModeWater');\n default:\n return '';\n }\n }\n\n return {\n generateDescriptionText,\n generateDeadlineExpiredDescriptionText,\n generateBookingExistsDescriptionText,\n generateCancelledBookingDescriptionText\n };\n}\n","import { BookingContactDto, BookingMethod, DepartureDto, LegDto, NotificationMessageType, TransportMode } from '@/types/webapi';\nimport { isDate } from 'date-fns';\nimport { isEmpty, isObject, isUndefined } from 'lodash-es';\n\nexport interface BookingParams {\n selectedItemId?: string;\n serviceJourneyRef: string;\n activeDate: Date;\n stopSequence: number;\n bookingLimitDateTime?: Date;\n bookingCancellationLimitDateTime?: Date;\n fromQuay?: string;\n bookingMethods: BookingMethod[];\n bookingContact?: BookingContactDto;\n transportMode?: TransportMode;\n bookingNotificationMessage?: string;\n aimedDepartureDateTime?: Date;\n}\n\nexport function createBookingParams(departureOrLeg?: DepartureDto | LegDto): BookingParams | undefined {\n if (\n isUndefined(departureOrLeg) ||\n !isObject(departureOrLeg) ||\n isEmpty(departureOrLeg) ||\n !departureOrLeg.bookingMetadata?.onlineBookingIsAvailable\n )\n return undefined;\n\n const { bookingMetadata, notificationMessages } = departureOrLeg;\n const {\n bookingCancellationLimitDateTime,\n bookingLimitDateTime,\n bookingMethods,\n bookingContact,\n transportMode,\n activeDate,\n serviceJourneyRef,\n stopSequence = -1\n } = bookingMetadata;\n const { quay, aimedDepartureTime } = departureOrLeg as Partial<DepartureDto>;\n const { from, aimedStartTime } = departureOrLeg as Partial<LegDto>;\n const bookingNotificationMessage = notificationMessages?.find(x => x.type === NotificationMessageType.BookingArrangement)?.text;\n\n if (!isDate(activeDate) || !serviceJourneyRef || stopSequence === -1) return undefined;\n\n const fromQuay = quay?.name || from?.name;\n\n const aimedDepartureDateTime = aimedDepartureTime || aimedStartTime;\n\n return {\n selectedItemId: departureOrLeg.id,\n activeDate,\n serviceJourneyRef,\n stopSequence,\n bookingCancellationLimitDateTime,\n bookingLimitDateTime,\n fromQuay,\n bookingMethods,\n bookingContact,\n transportMode,\n bookingNotificationMessage,\n aimedDepartureDateTime\n };\n}\n","import { BookingDto, StopOrderDto } from '@/types/webapi';\nimport { isSameDay } from 'date-fns';\n\n/**\n * Check if the stop order is valid\n * @param stopOrder - The stop order to check\n * @param params - The params to check against\n * @returns True if the stop order is valid, false otherwise\n */\nexport function hasValidStopOrder(\n stopOrder: StopOrderDto,\n params?: { serviceJourneyRef?: string; activeDate?: Date; stopSequence?: number }\n) {\n if (!params?.serviceJourneyRef || !params.activeDate || !params.stopSequence) return false;\n\n return (\n stopOrder.serviceJourneyRef === params.serviceJourneyRef &&\n isSameDay(stopOrder.activeDate, params.activeDate) &&\n stopOrder.stopSequence === params.stopSequence &&\n !stopOrder.isCancelled\n );\n}\n\n/**\n * Check if the booking is valid\n * @param booking - The booking to check\n * @param params - The params to check against\n * @returns True if the booking is valid, false otherwise\n */\nexport function hasValidBooking(booking: BookingDto, params?: { serviceJourneyRef?: string; activeDate?: Date; stopSequence?: number }) {\n if (!params?.serviceJourneyRef || !params.activeDate || !params.stopSequence) return false;\n\n return (\n booking.serviceJourneyRef === params.serviceJourneyRef &&\n isSameDay(booking.activeDate, params.activeDate) &&\n booking.stopSequence === params.stopSequence\n );\n}\n","import {\n type DepartureDto,\n type LegDto,\n NotificationMessageType,\n type TripPatternDto,\n type BookingDto,\n type StopOrderDto\n} from '@/types/webapi';\nimport { isDate, isSameDay } from 'date-fns';\nimport { useBookingMessages } from './useBookingMessages';\nimport { hasValidStopOrder } from '../functions';\n\n/**\n * Update the trip pattern groups with booking notifications\n * @param tripPatternGroups - The trip pattern groups to update\n * @param bookings - The bookings to check against\n * @returns The updated trip pattern groups\n */\nexport function updateTripPatternBookingNotifications(\n tripPatternGroups: Record<string, TripPatternDto[]>,\n bookings: BookingDto[],\n stopOrders: StopOrderDto[]\n): Record<string, TripPatternDto[]> {\n const processedGroups = { ...tripPatternGroups };\n\n for (const key in processedGroups) {\n processedGroups[key] = processedGroups[key].map(tripPattern => ({\n ...tripPattern,\n legs: updateNotificationMessage(tripPattern.legs || [], bookings, stopOrders)\n }));\n }\n\n return processedGroups;\n}\n\n/**\n * Update the departure groups with booking notifications\n * @param departureGroups - The departure groups to update\n * @param bookings - The bookings to check against\n * @returns The updated departure groups\n */\nexport function updateDepartureBookingNotifications(\n departureGroups: Record<string, DepartureDto[]>,\n bookings: BookingDto[],\n stopOrders: StopOrderDto[]\n): Record<string, DepartureDto[]> {\n const processedGroups = { ...departureGroups };\n\n for (const key in processedGroups) {\n processedGroups[key] = updateNotificationMessage(processedGroups[key], bookings, stopOrders);\n }\n\n return processedGroups;\n}\n\n/**\n * Update the notification message for the given items\n * @param items - The items to update\n * @param bookings - The bookings to check against\n * @returns The updated items\n */\nexport function updateNotificationMessage<T extends LegDto | DepartureDto>(\n items: T[],\n bookings: BookingDto[],\n stopOrders: StopOrderDto[]\n): T[] {\n const { generateBookingExistsDescriptionText } = useBookingMessages();\n\n return items.map(item => {\n const { activeDate, serviceJourneyRef, stopSequence } = item.bookingMetadata || {};\n if (!activeDate || !serviceJourneyRef || !stopSequence) return item;\n\n const hasExistingBooking = bookings.some(\n booking =>\n isDate(activeDate) &&\n isSameDay(booking.activeDate, activeDate) &&\n booking.serviceJourneyRef === serviceJourneyRef &&\n booking.stopSequence === stopSequence\n );\n\n const hasExistingStopOrder = stopOrders.some(x => hasValidStopOrder(x, { activeDate, serviceJourneyRef, stopSequence }));\n\n if (!hasExistingBooking && !hasExistingStopOrder) return item;\n\n // find the index of the notification message that is the online booking arrangement\n const notificationMessageIndex = item.notificationMessages\n ? item.notificationMessages.findIndex(x => x.type === NotificationMessageType.OnlineBookingArrangement)\n : -1;\n\n const leg = item as LegDto;\n const departure = item as DepartureDto;\n const fromQuay = leg.from?.quay?.name || departure.quay?.name;\n const transportMode = leg.transitInfo?.transportMode || departure.transportMode;\n\n // if the notification message index is found, update the text and type\n // else add a new notification message\n return {\n ...item,\n notificationMessages:\n notificationMessageIndex !== -1\n ? item.notificationMessages?.map((msg, index) =>\n index === notificationMessageIndex\n ? {\n ...msg,\n text: generateBookingExistsDescriptionText({ fromQuay, transportMode }),\n type: NotificationMessageType.BookingConfirmation\n }\n : msg\n )\n : [\n ...(item.notificationMessages || []),\n {\n id: 'booking-confirmation',\n text: generateBookingExistsDescriptionText({ fromQuay, transportMode }),\n type: NotificationMessageType.BookingConfirmation\n }\n ]\n };\n });\n}\n","import { PlaceType, type PlaceDto, TripMode, LegDto } from '@/types/webapi';\nimport { differenceInSeconds, isDate } from 'date-fns';\nimport { isUndefined, isNull, isEmpty, isObject } from 'lodash-es';\n\n/**\n * Determines whether a trip leg is a transfer between quays.\n * @param legDto Trip leg object\n * @returns True if leg is a transfer, false otherwise\n */\nexport function isTransfer(legDto: { from: PlaceDto; to: PlaceDto; tripMode: TripMode }): boolean {\n return (\n !isUndefined(legDto) &&\n !isNull(legDto) &&\n !isEmpty(legDto) &&\n isObject(legDto) &&\n legDto.from.type === PlaceType.TransitStation &&\n legDto.to.type === PlaceType.TransitStation &&\n (legDto.tripMode === TripMode.Foot || legDto.tripMode === TripMode.Bicycle)\n );\n}\n\n/**\n * Get the transfer time between two legs\n * @param prev - The previous leg\n * @param next - The next leg\n * @param curr - The current leg\n * @returns The transfer time in seconds\n */\nexport function getTransferTime(prev: LegDto, next: LegDto, curr?: Partial<LegDto>) {\n if (!prev || !next) return 0;\n\n const prevEndTime = prev.isEndingSoon ? prev.expectedEndTime : prev.aimedEndTime;\n const nextStartTime = next.isStartingSoon ? next.expectedStartTime : next.aimedStartTime;\n\n if (!isDate(prevEndTime) || !isDate(nextStartTime)) return 0;\n\n return differenceInSeconds(nextStartTime, prevEndTime) - (curr?.duration ?? 0);\n}\n","import { TripMode } from '@/types/webapi';\nimport { isNumber, isUndefined } from 'lodash-es';\n\n/**\n * Determines if the tripMode is a transit type.\n * @param tripMode TripMode value\n * @returns True if input is transit type, false otherwise.\n */\nexport function isTransitMode(tripMode?: TripMode) {\n return isNumber(tripMode) && !isUndefined(TripMode[tripMode]) && tripMode !== TripMode.Foot && tripMode !== TripMode.Bicycle;\n}\n","import type { TripPattern } from '@/features/trips/models';\n\n/**\n * Sorts trip patterns by arrival time\n * @param tripPatternGroups - A record of trip patterns grouped by a key\n * @param arriveBy - Reverse sorting order when true (for arrival time-based sorting)\n * @returns A new record of trip patterns grouped by a key, sorted by arrival time\n */\nexport function sortTripPatternsByArrival(\n tripPatternGroups: Record<string, TripPattern[]>,\n arriveBy = false\n): Record<string, TripPattern[]> {\n return Object.fromEntries(\n Object.entries(tripPatternGroups).map(([key, tripPatterns]) => [\n key,\n [...tripPatterns].sort((a, b) => {\n const aEndTime = a.isEndingSoon ? a.expectedEndTime : a.aimedEndTime;\n const bEndTime = b.isEndingSoon ? b.expectedEndTime : b.aimedEndTime;\n const comparison = aEndTime.getTime() - bEndTime.getTime();\n return arriveBy ? comparison * -1 : comparison;\n })\n ])\n );\n}\n\n/**\n * Marks and filters expensive trip patterns\n * @param tripPatternGroups - A record of trip patterns grouped by a key\n * @param removeExpensiveTripPatterns - Whether to remove expensive trip patterns\n * @param maxPatternsPerHour - The maximum number of patterns per hour before marking and filtering expensive trip patterns\n * @returns The trip patterns with expensive trip patterns disabled\n */\nexport function markAndFilterExpensiveTripPatterns(\n tripPatternGroups: Record<string, TripPattern[]>,\n removeExpensiveTripPatterns = false,\n maxPatternsPerHour = 3\n): Record<string, TripPattern[]> {\n return Object.fromEntries(\n Object.entries(tripPatternGroups).map(([key, tripPatterns]) => {\n if (removeExpensiveTripPatterns) {\n return [key, tripPatterns.filter(tripPattern => !tripPattern.isExpensiveTripPattern)];\n }\n\n // Group trip patterns by hour\n const tripPatternsByHour = tripPatterns.reduce(\n (acc, tripPattern) => {\n const hour = tripPattern.aimedStartTime.getHours();\n acc[hour] = [...(acc[hour] || []), tripPattern];\n return acc;\n },\n {} as Record<number, TripPattern[]>\n );\n\n // Get all trip patterns that are expensive and have more than 5 items in the same hour\n const expensiveTripPatterns = Object.values(tripPatternsByHour)\n .filter(tripPatterns => tripPatterns.length > maxPatternsPerHour)\n .flatMap(tripPatterns => tripPatterns.map(tripPattern => tripPattern.id));\n\n return [\n key,\n tripPatterns.map(tripPattern => ({\n ...tripPattern,\n disabled:\n tripPattern.isExpensiveTripPattern &&\n expensiveTripPatterns.some(expensiveTripPattern => expensiveTripPattern === tripPattern.id)\n }))\n ];\n })\n );\n}\n","import { useContainer } from '@/plugins/inversify';\nimport { ISearchService, ISearchServiceId } from '@/services';\nimport {\n type PlaceAutocompleteModelDto,\n type TripDto,\n GetTripModeDto,\n type LegDto,\n PlaceType,\n TripMode,\n type GetTripResponseMetadata\n} from '@/types/webapi';\nimport { defineStore, storeToRefs } from 'pinia';\nimport { isArray, isEmpty, isEqual, merge, mergeWith, omit } from 'lodash-es';\nimport { type TripSearchRequest, type TripSearchFilters, WalkSpeedType, TripPattern } from '@/features/trips/models';\nimport { computed, reactive, toRefs, toValue, watch } from 'vue';\nimport { useMainStore } from '@/features/common/stores';\nimport { type SearchHistoryItem } from '@/features/places/models';\nimport { usePlaceAutocompleteHistory } from '@/features/places/composables';\nimport { isDefined } from '@vueuse/core';\nimport { DateType } from '@/features/common/models';\nimport { type AxiosError } from 'axios';\nimport { useGtm } from 'vue-gtm';\nimport { updateTripPatternBookingNotifications } from '@/features/bookings/composables';\nimport { useBookingStore } from '@/features/bookings/stores';\nimport { markAndFilterExpensiveTripPatterns, isTransfer, isTransitMode, sortTripPatternsByArrival } from '../helpers';\nimport { encode } from '@/features/map/composables';\n\nconst defaultSearchFilters: TripSearchFilters = {\n modes: [],\n walkSpeed: WalkSpeedType.Normal,\n transferSlack: 120,\n showTripsWithTransfers: true,\n lines: []\n};\n\nconst defaultSearchRequest: TripSearchRequest = {\n from: null,\n to: null,\n dateTime: undefined,\n dateTimeType: DateType.Now,\n filters: { ...defaultSearchFilters },\n nextPageCursors: {},\n previousPageCursors: {}\n};\n\nconst defaultSearchResult = {\n errors: [] as string[],\n trip: null as TripDto | null,\n meta: null as GetTripResponseMetadata | null\n};\n\nconst useTripSearchStore = defineStore('tripSearchStore', () => {\n const container = useContainer();\n const tripSearchService = container.get<ISearchService>(ISearchServiceId);\n const { addItem } = usePlaceAutocompleteHistory<SearchHistoryItem>('historyItems');\n const { addItem: addPastPlace } = usePlaceAutocompleteHistory<SearchHistoryItem>('pastPlaces');\n const mainStore = useMainStore();\n const { config } = storeToRefs(mainStore);\n const gtm = useGtm();\n const bookingStore = useBookingStore();\n\n const state = reactive({\n isDirty: false,\n searchRequest: { ...defaultSearchRequest },\n selectedTripPatternId: null as string | null,\n selectedTripPatternIdIsExpanded: false,\n selectedMode: GetTripModeDto.Bus\n });\n const searchResult = reactive({ ...defaultSearchResult });\n const _footSearchResult = reactive({ ...defaultSearchResult });\n const footSearchResult = computed(() =>\n _footSearchResult.trip ? Object.values(_footSearchResult.trip.tripPatternGroups)[0]?.[0] : undefined\n );\n const _bikeSearchResult = reactive({ ...defaultSearchResult });\n const bikeSearchResult = computed(() =>\n _bikeSearchResult.trip ? Object.values(_bikeSearchResult.trip.tripPatternGroups)[0]?.[0] : undefined\n );\n\n const searchingState = reactive({\n transitIsSearching: false,\n footIsSearching: false,\n bikeIsSearching: false\n });\n const loadingStates = reactive({\n transitIsLoading: false,\n footIsLoading: false,\n bikeIsLoading: false\n });\n const isSearching = computed(\n () => searchingState.transitIsSearching || searchingState.footIsSearching || searchingState.bikeIsSearching\n );\n const isLoading = computed(() => loadingStates.transitIsLoading || loadingStates.footIsLoading || loadingStates.bikeIsLoading);\n const canSearch = computed(() => isValidSearchRequest(state.searchRequest));\n const filterIsDirty = computed(() => !isEqual(toValue(state.searchRequest.filters), defaultSearchFilters));\n const hasResult = computed(() => Boolean(searchResult.trip));\n const tripPatternGroups = computed(\n (): Record<string, TripPattern[]> =>\n markAndFilterExpensiveTripPatterns(\n sortTripPatternsByArrival(\n addTransferLegs(\n removeDuplicateTripPatterns(\n updateTripPatternBookingNotifications(\n setIsMyLocation(removeHiddenLegs(searchResult.trip?.tripPatternGroups || {}), state.searchRequest),\n bookingStore.bookings,\n bookingStore.stopOrders\n )\n )\n ),\n state.searchRequest.dateTimeType === DateType.ArriveBy\n ),\n !config.value.isDebugModeEnabled,\n config.value.searchConfig.maxPatternsPerHour\n )\n );\n const tripPatterns = computed(() => Object.values(tripPatternGroups.value).flatMap(x => x));\n const selectedTripPattern = computed((): TripPattern | undefined => {\n if (!state.selectedTripPatternId) return undefined;\n\n return (\n tripPatterns.value.find(x => x.id === state.selectedTripPatternId) ||\n (state.selectedTripPatternId === footSearchResult.value?.id && footSearchResult.value) ||\n (state.selectedTripPatternId === bikeSearchResult.value?.id && bikeSearchResult.value) ||\n undefined\n );\n });\n const generalizedCostMean = computed(() => {\n return tripPatterns.value.reduce((acc, tripPattern) => acc + (tripPattern.generalizedCost || 0), 0) / tripPatterns.value.length;\n });\n\n const isInNonTransitMode = computed(() =>\n [GetTripModeDto.Foot, GetTripModeDto.Bicycle].some(m => state.searchRequest.filters.modes.includes(m))\n );\n\n function $reset() {\n resetResult();\n\n state.isDirty = false;\n state.searchRequest = { ...defaultSearchRequest };\n state.selectedTripPatternId = null;\n state.selectedTripPatternIdIsExpanded = false;\n state.selectedMode = GetTripModeDto.Bus;\n }\n\n function resetResult() {\n Object.assign(searchResult, { ...defaultSearchResult });\n Object.assign(_bikeSearchResult, { ...defaultSearchResult });\n Object.assign(_footSearchResult, { ...defaultSearchResult });\n }\n\n function resetFilters() {\n state.searchRequest.filters = { ...defaultSearchFilters };\n }\n\n function swapFromTo() {\n state.searchRequest = {\n ...state.searchRequest,\n from: state.searchRequest.to,\n to: state.searchRequest.from\n };\n }\n\n function isValidSearchRequest(\n request: TripSearchRequest\n ): request is { from: PlaceAutocompleteModelDto; to: PlaceAutocompleteModelDto } & TripSearchRequest {\n return (\n isDefined(request.from?.id) &&\n request.from.type !== PlaceType.Unknown &&\n isDefined(request.to?.id) &&\n request.to.type !== PlaceType.Unknown\n );\n }\n\n function selectFirstTripPattern() {\n if (!tripPatterns.value.length) return;\n\n state.selectedTripPatternId = tripPatterns.value[0].id;\n }\n\n let searchAbortController: AbortController | undefined;\n\n async function _executeSearch(searchFunc: Function, onError?: Function) {\n try {\n await searchFunc();\n } catch (e) {\n const { name } = e as AxiosError;\n // in case of AbortController being triggered, do nothing\n if (name === 'CanceledError') return;\n\n mainStore.registerError(e);\n onError?.();\n }\n }\n\n // foot mode search\n async function searchFoot({ signal }: { signal: AbortSignal }) {\n if (!isValidSearchRequest(state.searchRequest)) return;\n\n await _executeSearch(\n async () => {\n loadingStates.footIsLoading = true;\n searchingState.footIsSearching = true;\n // force mode\n const searchRequest = merge({}, state.searchRequest, { filters: { modes: [GetTripModeDto.Foot] } });\n const searchResponse = await tripSearchService.searchForTrips(searchRequest, { signal });\n _footSearchResult.trip = searchResponse?.data || null;\n\n searchingState.footIsSearching = false;\n loadingStates.footIsLoading = false;\n },\n () => {\n searchingState.footIsSearching = false;\n loadingStates.footIsLoading = false;\n }\n );\n }\n\n // bike mode search\n async function searchBike({ signal }: { signal: AbortSignal }) {\n if (!isValidSearchRequest(state.searchRequest)) return;\n\n loadingStates.bikeIsLoading = true;\n\n await _executeSearch(\n async () => {\n searchingState.bikeIsSearching = true;\n // force mode\n const searchRequest = merge({}, state.searchRequest, { filters: { modes: [GetTripModeDto.Bicycle] } });\n const searchResponse = await tripSearchService.searchForTrips(searchRequest, { signal });\n _bikeSearchResult.trip = searchResponse?.data || null;\n\n searchingState.bikeIsSearching = false;\n loadingStates.bikeIsLoading = false;\n },\n () => {\n searchingState.bikeIsSearching = false;\n loadingStates.bikeIsLoading = false;\n }\n );\n }\n\n async function searchTransit({ signal }: { signal: AbortSignal }) {\n if (!isValidSearchRequest(state.searchRequest)) return;\n loadingStates.transitIsLoading = true;\n\n await _executeSearch(\n async () => {\n searchingState.transitIsSearching = true;\n\n // TODO: check for bookings against booking store\n const searchResponse = await tripSearchService.searchForTrips(state.searchRequest, { signal });\n searchResult.trip = searchResponse?.data || null;\n searchResult.meta = searchResponse?.meta || null;\n\n searchingState.transitIsSearching = false;\n loadingStates.transitIsLoading = false;\n },\n () => {\n searchingState.transitIsSearching = false;\n loadingStates.transitIsLoading = false;\n }\n );\n }\n\n function _search({ signal }: { signal: AbortSignal }) {\n if (signal.aborted) {\n return Promise.reject(new DOMException('Cancelled', 'CanceledError'));\n }\n\n return new Promise<void>((resolve, reject) => {\n // if searchRequest is not valid, do nothing\n if (!isValidSearchRequest(state.searchRequest)) return reject();\n\n signal.addEventListener('abort', () => reject(new DOMException('Cancelled', 'CanceledError')));\n\n // remove distance and isMyLocation\n const from = omit(state.searchRequest.from, ['distance', 'isMyLocation']);\n const to = omit(state.searchRequest.to, ['distance', 'isMyLocation']);\n\n // save individual places\n addPastPlace({ id: from.id, from });\n addPastPlace({ id: to.id, from: to });\n\n // register history\n addItem({ id: `${from.id}__${to.id}`, from, to });\n\n Promise.all([searchTransit({ signal }), searchFoot({ signal }), searchBike({ signal })])\n .then(() => {\n // track event\n gtm?.trackEvent({\n event: 'app_event',\n category: 'trip_search',\n action: 'search',\n hasTransitStation: from.type === PlaceType.TransitStation || to.type === PlaceType.TransitStation,\n hasDateTime: !!state.searchRequest.dateTime,\n hasFilters: !isEqual(defaultSearchFilters, state.searchRequest.filters)\n });\n\n resolve();\n })\n .catch(reject);\n });\n }\n\n // search all modes\n async function search() {\n await _executeSearch(async () => {\n // if searchRequest is not valid, do nothing\n if (!isValidSearchRequest(state.searchRequest)) return;\n\n // abort previous request\n searchAbortController?.abort();\n searchAbortController = new AbortController();\n\n resetResult();\n state.isDirty = true;\n\n await _search({ signal: searchAbortController!.signal });\n });\n }\n\n function cancelSearch() {\n searchAbortController?.abort();\n }\n\n async function searchMore() {\n if (searchingState.transitIsSearching || !isValidSearchRequest(state.searchRequest)) return;\n\n loadingStates.transitIsLoading = true;\n\n try {\n if (!isEmpty(searchResult.meta?.nextPageCursors) || !isEmpty(searchResult.meta?.previousPageCursors)) {\n searchingState.transitIsSearching = true;\n\n const searchResponse = await tripSearchService.searchForMoreTrips(\n merge({}, state.searchRequest, {\n nextPageCursors: searchResult.meta?.nextPageCursors,\n previousPageCursors: searchResult.meta?.previousPageCursors\n })\n );\n\n if (!searchResponse) return;\n\n const {\n data: { tripPatternGroups },\n meta: { nextPageCursors, previousPageCursors }\n } = searchResponse;\n\n // we need to append trip patterns to groups\n mergeWith(searchResult.trip?.tripPatternGroups || {}, tripPatternGroups, mergeArray);\n\n // and save next page cursors\n if (searchResult.trip) {\n searchResult.meta.nextPageCursors = nextPageCursors || {};\n searchResult.meta.previousPageCursors = previousPageCursors || {};\n }\n }\n } catch (e) {\n mainStore.registerError(e);\n } finally {\n searchingState.transitIsSearching = false;\n loadingStates.transitIsLoading = false;\n }\n }\n\n watch(\n () => state.selectedTripPatternId,\n (value, oldValue) => {\n if (value === oldValue) return;\n\n // reset expanded item\n state.selectedTripPatternIdIsExpanded = false;\n }\n );\n\n watch(hasResult, value => {\n if (!value || !tripPatterns.value.length) {\n state.selectedTripPatternId = null;\n state.selectedTripPatternIdIsExpanded = false;\n return;\n }\n\n // check if selectedTripPatternId exists in list\n // if it doesn't, reset selected trip pattern stuff\n if (!tripPatterns.value.some(x => x.id === state.selectedTripPatternId)) {\n // TODO: show error for invalid trip pattern ID?\n state.selectedTripPatternId = null;\n state.selectedTripPatternIdIsExpanded = false;\n }\n });\n\n // trigger search when enturEndpointType changes\n watch(config, async (value, oldValue) => {\n if (isEqual(value, oldValue)) return;\n\n await search();\n });\n\n return {\n ...toRefs(state),\n ...toRefs(searchingState),\n ...toRefs(loadingStates),\n isSearching,\n isLoading,\n canSearch,\n filterIsDirty,\n hasResult,\n tripPatternGroups,\n selectedTripPattern,\n searchResult,\n footSearchResult,\n bikeSearchResult,\n $reset,\n resetResult,\n swapFromTo,\n search,\n searchMore,\n cancelSearch,\n resetFilters,\n selectFirstTripPattern,\n isInNonTransitMode,\n generalizedCostMean\n };\n});\n\nfunction mergeArray(obj: Record<string, TripPattern[]>, src: Record<string, TripPattern[]>) {\n if (isArray(obj)) {\n return obj.concat(src);\n }\n}\n\n/**\n * Remove hidden legs from trip patterns\n * @param tripPatternGroups - The trip pattern groups to remove hidden legs from\n * @returns The trip pattern groups with hidden legs removed\n */\nfunction removeHiddenLegs(tripPatternGroups: Record<string, TripPattern[]>): Record<string, TripPattern[]> {\n return Object.fromEntries(\n Object.entries(tripPatternGroups).map(([key, tripPatterns]) => [\n key,\n tripPatterns.map(x => ({\n ...x,\n legs: x.legs?.filter(y => !y.isHidden)\n }))\n ])\n );\n}\n\n/**\n * Set isMyLocation for origin/destination\n * @param tripPatternGroups - The trip pattern groups to set isMyLocation for\n * @param searchRequest - The search request\n * @returns The trip pattern groups with isMyLocation set for origin/destination\n */\nfunction setIsMyLocation(\n tripPatternGroups: Record<string, TripPattern[]>,\n searchRequest: TripSearchRequest\n): Record<string, TripPattern[]> {\n return Object.fromEntries(\n Object.entries(tripPatternGroups).map(([key, tripPatterns]) => [\n key,\n tripPatterns.map(tripPattern => {\n // check if isMyLocation is set for origin/destination\n const myLocationPlaceId = searchRequest.from?.isMyLocation\n ? searchRequest.from.id\n : searchRequest.to?.isMyLocation\n ? searchRequest.to.id\n : undefined;\n\n return {\n ...tripPattern,\n legs: tripPattern.legs?.map(leg => ({\n ...leg,\n from: { ...leg.from, isMyLocation: leg.from.id === myLocationPlaceId },\n to: { ...leg.to, isMyLocation: leg.to.id === myLocationPlaceId }\n }))\n };\n })\n ])\n );\n}\n\n/**\n * Remove duplicate trip patterns\n * @param tripPatternGroups - The trip pattern groups to remove duplicate trip patterns from\n * @returns The trip pattern groups with duplicate trip patterns removed\n */\nfunction removeDuplicateTripPatterns(tripPatternGroups: Record<string, TripPattern[]>): Record<string, TripPattern[]> {\n return Object.fromEntries(\n Object.entries(tripPatternGroups).map(([key, tripPatterns]) => [\n key,\n tripPatterns.filter((tripPattern, index, self) => index === self.findIndex(t => t.id === tripPattern.id))\n ])\n );\n}\n\n/**\n * Add transfer legs between transit legs i.e. when no quay change is needed\n * @param tripPatternGroups - The trip pattern groups to add transfer legs to\n * @returns The trip pattern groups with transfer legs added\n */\nfunction addTransferLegs(tripPatternGroups: Record<string, TripPattern[]>): Record<string, TripPattern[]> {\n return Object.fromEntries(\n Object.entries(tripPatternGroups).map(([key, tripPatterns]) => [\n key,\n tripPatterns.map(tripPattern => ({\n ...tripPattern,\n legs: tripPattern.legs?.reduce<LegDto[]>((acc, leg, i, arr) => {\n // if leg is a transit leg, check if the previous leg is also a transit leg\n if (i > 0 && !isTransfer(leg) && isTransitMode(leg.tripMode)) {\n const previousLeg = arr[i - 1];\n\n // if previous leg is also a transit leg, add a transfer leg\n if (isTransitMode(previousLeg.tripMode)) {\n const points = encode([\n [previousLeg.to.coordinates.latitude, previousLeg.to.coordinates.longitude],\n [leg.from.coordinates.latitude, leg.from.coordinates.longitude]\n ]);\n const transferLeg = {\n id: `${previousLeg.id}_${leg.id}`,\n from: previousLeg.to,\n to: leg.from,\n tripMode: TripMode.Foot,\n distance: 0,\n duration: 0,\n aimedStartTime: previousLeg.aimedEndTime,\n expectedStartTime: previousLeg.expectedEndTime,\n aimedEndTime: leg.aimedStartTime,\n expectedEndTime: leg.expectedStartTime,\n intermediateEstimatedCalls: [],\n notificationMessages: [],\n isHidden: false,\n isOperatedByKolumbus: leg.isOperatedByKolumbus,\n pointsOnLink: [\n {\n points,\n length: points.length\n }\n ]\n } satisfies LegDto;\n\n return [...acc, transferLeg, leg];\n }\n }\n\n return [...acc, leg];\n }, [])\n }))\n ])\n );\n}\nexport default useTripSearchStore;\n","import { useUserStore } from '@geta/kolumbus-frontend/features/authentication';\nimport { useMainStore } from '@/features/common/stores';\nimport { useDeparturesSearchStore } from '@/features/departures/stores';\nimport { useTripSearchStore } from '@/features/trips/stores';\nimport { useContainer } from '@/plugins/inversify';\nimport { IBookingService, IBookingServiceId } from '@/services';\nimport { BookingDto, BookingStatus, CreateBookingDto, StopOrderDto } from '@/types/webapi';\nimport { isAxiosError } from 'axios';\nimport { defineStore } from 'pinia';\nimport { computed, nextTick, ref, toValue } from 'vue';\nimport { UserInfo } from '../models';\nimport { isAfter, isBefore, isDate, addDays, isSameDay } from 'date-fns';\nimport { BookingParams, createBookingParams } from '../functions';\nimport { BookingError } from '@/features/common/models';\n\nexport const defaultUserInfo = (): UserInfo => ({\n phone: {\n countryCode: '+47',\n number: ''\n }\n});\n\nexport const useBookingStore = defineStore('bookingStore', () => {\n const userStore = useUserStore();\n const mainStore = useMainStore();\n const tripSearchStore = useTripSearchStore();\n const departureSearchStore = useDeparturesSearchStore();\n\n const container = useContainer();\n const bookingService = container.get<IBookingService>(IBookingServiceId);\n\n const bookingIsEnabled = computed(() => mainStore.config.bookingConfig?.enabled);\n const maxBookingExceeded = ref(false);\n const isLoading = ref(false);\n const isBooking = ref(false);\n const bookings = ref<BookingDto[]>([]);\n const selectedBooking = ref<BookingDto>();\n const stopOrders = ref<StopOrderDto[]>([]);\n const createBookingProps = computed<BookingParams | undefined>(() => {\n if (!bookingIsEnabled.value) return undefined;\n\n if (departureSearchStore.selectedDeparture) {\n return createBookingParams(departureSearchStore.selectedDeparture);\n }\n\n if (tripSearchStore.selectedTripPattern) {\n // generate params from first leg where onlineBookingIsAvailable=true\n return createBookingParams(tripSearchStore.selectedTripPattern.legs?.find(x => x.bookingMetadata?.onlineBookingIsAvailable));\n }\n\n return undefined;\n });\n const onlineBookingIsAvailable = computed(() => !!createBookingProps.value);\n const bookingDeadlineExceeded = computed(\n () =>\n isDate(createBookingProps.value?.bookingLimitDateTime) &&\n isAfter(mainStore.currentTime, createBookingProps.value.bookingLimitDateTime)\n );\n const bookingTooFarAhead = computed(\n () =>\n isDate(createBookingProps.value?.aimedDepartureDateTime) &&\n isAfter(createBookingProps.value.aimedDepartureDateTime, addDays(mainStore.currentTime, 7))\n );\n const canBook = computed(\n () => !!createBookingProps.value && !bookingDeadlineExceeded.value && !selectedBooking.value && !bookingTooFarAhead.value\n );\n const canCancel = computed(\n () =>\n selectedBooking.value?.isCancellationAllowed &&\n selectedBooking.value.status !== BookingStatus.Cancelled &&\n (!isDate(selectedBooking.value?.bookingCancellationLimitDateTime) ||\n isBefore(mainStore.currentTime, selectedBooking.value.bookingCancellationLimitDateTime))\n );\n const userInfo = ref<UserInfo>(defaultUserInfo());\n const userInfoIsValid = computed(() => userStore.isLoggedIn || !!(userInfo.value.phone?.countryCode && userInfo.value.phone.number));\n\n let loadStopOrderAbortController: AbortController | undefined;\n let loadBookingsAbortController: AbortController | undefined;\n\n async function loadStopOrder() {\n try {\n isLoading.value = false;\n\n // abort previous request\n loadStopOrderAbortController?.abort();\n loadStopOrderAbortController = new AbortController();\n\n const { serviceJourneyRef, activeDate, stopSequence } = createBookingProps.value || {};\n\n // check if params are valid\n if (!serviceJourneyRef || !activeDate || !stopSequence) return;\n\n // load stop order, and add as booking to bookings list\n const stopOrder = await bookingService.getStopOrder(\n { serviceJourneyRef, activeDate, stopSequence },\n {\n signal: loadStopOrderAbortController.signal\n }\n );\n\n // if no stop order, do nothing\n if (!stopOrder) return;\n\n // add or update stop order\n const index = stopOrders.value.findIndex(x => x.id === stopOrder.id);\n\n if (index !== -1) {\n stopOrders.value[index] = stopOrder;\n } else {\n stopOrders.value.push(stopOrder);\n }\n } catch (e) {\n if (isAxiosError(e)) {\n // in case of AbortController being triggered, do nothing\n if (e.name === 'CanceledError') return;\n }\n\n mainStore.registerError(e);\n } finally {\n isLoading.value = false;\n }\n }\n\n async function loadBookings() {\n selectedBooking.value = undefined;\n\n // abort previous request\n loadBookingsAbortController?.abort();\n loadBookingsAbortController = new AbortController();\n\n if (!bookingIsEnabled.value || !userStore.isLoggedIn) return;\n\n try {\n isLoading.value = true;\n\n // get all user bookings\n bookings.value = await bookingService.getAllBookings({ signal: loadBookingsAbortController.signal });\n maxBookingExceeded.value = bookings.value.length >= 2;\n\n await nextTick();\n\n // set matching booking as selectedBooking\n selectedBooking.value = bookings.value.find(\n x =>\n !!createBookingProps.value &&\n isSameDay(x.activeDate, createBookingProps.value.activeDate) &&\n x.serviceJourneyRef === createBookingProps.value.serviceJourneyRef &&\n x.stopSequence === createBookingProps.value.stopSequence\n );\n\n isLoading.value = false;\n } catch (e) {\n if (isAxiosError(e)) {\n // in case of AbortController being triggered, do nothing\n if (e.name === 'CanceledError') return;\n\n if (e.response?.status !== 401) {\n mainStore.registerError(new BookingError(e.response?.data || ''));\n }\n } else {\n console.error(e);\n }\n\n isLoading.value = false;\n }\n }\n\n async function loadBooking(id: string) {\n if (!id) return;\n\n try {\n isLoading.value = true;\n\n selectedBooking.value = await bookingService.getBooking(id);\n } catch (e) {\n if (isAxiosError(e) && e.response?.status !== 404) {\n mainStore.registerError(new BookingError(e.response?.data || ''));\n } else {\n console.error(e);\n }\n } finally {\n isLoading.value = false;\n }\n }\n\n async function createBooking(recaptchaToken?: string, phoneVerificationCode?: string) {\n if (isBooking.value) return;\n\n isBooking.value = true;\n\n const _createBookingProps = toValue(createBookingProps);\n if (!_createBookingProps || !userInfoIsValid.value) return;\n\n try {\n isLoading.value = true;\n\n const { countryCode, number } = userInfo.value.phone || {};\n const params: CreateBookingDto = {\n ..._createBookingProps,\n name: userInfo.value.name,\n phoneCountryCode: countryCode,\n phoneNumber: number,\n recaptchaToken,\n phoneVerificationCode\n };\n\n selectedBooking.value = await bookingService.createBooking(params);\n } catch (e) {\n if (isAxiosError(e)) {\n // if already exists, load it up\n if (e.response?.status === 302 && e.response.data) {\n await loadBooking(e.response.data);\n return;\n }\n\n // if precondition failed, just return\n if (e.response?.status === 412) {\n if (e.response.data === 'BOOKING_LIMIT_REACHED') {\n maxBookingExceeded.value = true;\n return;\n }\n\n if (e.response.data === 'REQUEST_VALIDATION_FAILED') {\n // TODO: handle this better\n throw new BookingError('REQUEST_VALIDATION_FAILED');\n }\n }\n\n mainStore.registerError(new BookingError(e.response?.data || ''));\n } else {\n console.error(e);\n }\n } finally {\n isLoading.value = false;\n isBooking.value = false;\n }\n }\n\n async function cancelBooking() {\n if (!selectedBooking.value) return;\n\n try {\n isLoading.value = true;\n\n selectedBooking.value = await bookingService.cancelBooking(selectedBooking.value.id);\n // Remove the cancelled booking from bookings collection\n bookings.value = bookings.value.filter(booking => booking.id !== selectedBooking.value?.id);\n } catch (e) {\n if (isAxiosError(e)) {\n mainStore.registerError(new BookingError(e.response?.data || ''));\n } else {\n console.error(e);\n }\n } finally {\n isLoading.value = false;\n }\n }\n\n return {\n bookingIsEnabled,\n onlineBookingIsAvailable,\n bookings,\n selectedBooking,\n maxBookingExceeded,\n createBookingProps,\n bookingDeadlineExceeded,\n canBook,\n canCancel,\n stopOrders,\n isLoading,\n isBooking,\n userInfo,\n userInfoIsValid,\n bookingTooFarAhead,\n loadBookings,\n loadBooking,\n createBooking,\n cancelBooking,\n loadStopOrder\n };\n});\n","import { type DepartureDto } from '@/types/webapi';\n\nconst REALTIME_THRESHOLD_MINUTES = 20 * 60 * 1000; // 20 minutes in milliseconds\n\n/**\n * Sorts departure groups by time, using expectedStopTime if isCallingSoon is true\n * @param departureGroups - The departure groups to sort\n * @returns Sorted departure groups with departures ordered chronologically\n */\nexport function sortDepartureGroups(departureGroups: Record<string, DepartureDto[]>): Record<string, DepartureDto[]> {\n return Object.fromEntries(\n Object.entries(departureGroups).map(([key, departures]) => {\n const sorted = [...departures].sort((a, b) => {\n const aTime = a.isCallingSoon && a.expectedStopTime ? a.expectedStopTime : a.aimedStopTime;\n const bTime = b.isCallingSoon && b.expectedStopTime ? b.expectedStopTime : b.aimedStopTime;\n return new Date(aTime).getTime() - new Date(bTime).getTime();\n });\n return [key, sorted];\n })\n );\n}\n\n/**\n * Update the legs of the departures with time status flags\n * @param departureGroups - The departure groups to update\n * @param currentTime - The current time\n * @returns The updated departure groups\n */\nexport function updateDeparturesTimeStatusFlags(\n departureGroups: Record<string, DepartureDto[]>,\n currentTime: Date\n): Record<string, DepartureDto[]> {\n return Object.keys(departureGroups).reduce(\n (updatedGroups, groupKey) => {\n updatedGroups[groupKey] = departureGroups[groupKey].map(departure => ({\n ...departure,\n estimatedCalls:\n departure.estimatedCalls?.map(estimatedCall => {\n if (!estimatedCall.aimedStopTime) return estimatedCall;\n\n const stopTime = estimatedCall.aimedStopTime.getTime();\n const currentTimeMs = currentTime.getTime();\n\n return {\n ...estimatedCall,\n isCallingSoon: stopTime - currentTimeMs <= REALTIME_THRESHOLD_MINUTES\n };\n }) || []\n }));\n\n return updatedGroups;\n },\n {} as Record<string, DepartureDto[]>\n );\n}\n\n/**\n * Adjusts expectedStopTime to never be earlier than aimedStopTime\n * @param departureGroups - The departure groups to process\n * @returns Departure groups with corrected expectedStopTime values\n */\nexport function adjustExpectedTimesBasedOnAimed(departureGroups: Record<string, DepartureDto[]>): Record<string, DepartureDto[]> {\n return Object.keys(departureGroups).reduce(\n (adjustedGroups, groupKey) => {\n adjustedGroups[groupKey] = departureGroups[groupKey].map(departure => {\n const { expectedStopTime, aimedStopTime, estimatedCalls = [] } = departure;\n const expectedTime = expectedStopTime?.getTime();\n const aimedTime = aimedStopTime?.getTime();\n\n return {\n ...departure,\n expectedStopTime: expectedTime && expectedTime < aimedTime ? aimedStopTime : expectedStopTime,\n // Adjust the expectedStopTime of each estimatedCall to never be earlier than the aimedStopTime\n estimatedCalls: estimatedCalls?.map(estimatedCall => {\n if (!estimatedCall.expectedStopTime || !estimatedCall.aimedStopTime) {\n return estimatedCall;\n }\n\n const { expectedStopTime, aimedStopTime } = estimatedCall;\n const expectedTime = expectedStopTime?.getTime();\n const aimedTime = aimedStopTime?.getTime();\n\n return {\n ...estimatedCall,\n expectedStopTime: expectedTime < aimedTime ? aimedStopTime : expectedStopTime\n };\n })\n };\n });\n return adjustedGroups;\n },\n {} as Record<string, DepartureDto[]>\n );\n}\n","import { DateType } from '@/features/common/models';\nimport { useMainStore } from '@/features/common/stores';\nimport { type DeparturesSearchRequest } from '@/features/departures/models';\nimport { usePlaceAutocompleteHistory } from '@/features/places/composables';\nimport { useContainer } from '@/plugins/inversify';\nimport { ISearchService, ISearchServiceId } from '@/services';\nimport { type DepartureDto, type QuayDto, type PlaceAutocompleteModelDto, PlaceType, type StopPlaceDto } from '@/types/webapi';\nimport { isDefined } from '@vueuse/core';\nimport { type AxiosError } from 'axios';\nimport { isEqual } from 'lodash-es';\nimport { defineStore, storeToRefs } from 'pinia';\nimport { computed, reactive, toRefs, watch } from 'vue';\nimport { useGtm } from 'vue-gtm';\nimport { useBookingStore } from '@/features/bookings/stores/bookingStore';\nimport { updateDepartureBookingNotifications } from '@/features/bookings/composables';\nimport { adjustExpectedTimesBasedOnAimed, sortDepartureGroups, updateDeparturesTimeStatusFlags } from '../helpers';\n\nexport interface State {\n searchRequest: DeparturesSearchRequest;\n selectedDepartureId?: string | null;\n selectedDepartureIdIsExpanded?: boolean;\n}\n\nconst defaultSearchRequest: DeparturesSearchRequest = {\n quay: null,\n dateTime: undefined,\n dateTimeType: DateType.Now,\n filters: {\n modes: [],\n quays: []\n }\n};\n\nconst defaultSearchResult = {\n errors: [] as string[],\n stopPlace: null as StopPlaceDto | null\n};\n\nexport const useDeparturesSearchStore = defineStore('departuresSearchStore', () => {\n const container = useContainer();\n const searchService = container.get<ISearchService>(ISearchServiceId);\n const { addItem } = usePlaceAutocompleteHistory<PlaceAutocompleteModelDto>('pastQuays');\n const mainStore = useMainStore();\n const { devModeConfiguration } = storeToRefs(mainStore);\n const gtm = useGtm();\n const bookingStore = useBookingStore();\n\n const state = reactive({\n isDirty: false,\n isSearching: false,\n isLoading: false,\n searchRequest: { ...defaultSearchRequest },\n selectedDepartureId: null as string | null,\n selectedDepartureIdIsExpanded: false\n });\n const searchResult = reactive({ ...defaultSearchResult });\n const canSearch = computed(() => Boolean(state.searchRequest.quay?.id));\n const hasResult = computed(() => Boolean(searchResult.stopPlace));\n const stopPlaceTransportModes = computed(() => [...(searchResult.stopPlace?.availableTransportModes ?? [])]);\n const stopPlaceQuays = computed<QuayDto[]>(\n () =>\n searchResult.stopPlace?.quays\n // remove duplicates, if any\n .filter((_, i, a) => a.findIndex(x => x.id === a[i].id) === i)\n // sort alphanumerically\n .toSorted((a, b) => a.publicCode?.localeCompare(b.publicCode || '', 'en', { numeric: true }) || 0) || []\n );\n const selectedDeparture = computed<DepartureDto | undefined>(() => {\n if (!searchResult) return undefined;\n\n for (const key in departureGroups.value) {\n const found = departureGroups.value[key].find(x => x.id === state.selectedDepartureId);\n if (found) {\n return found;\n }\n }\n\n return undefined;\n });\n\n const departureGroups = computed(\n (): Record<string, DepartureDto[]> =>\n updateDepartureBookingNotifications(\n updateDeparturesTimeStatusFlags(\n sortDepartureGroups(\n adjustExpectedTimesBasedOnAimed(removeDuplicateDepartures(searchResult.stopPlace?.departureGroups ?? {}))\n ),\n mainStore.currentTime\n ),\n bookingStore.bookings,\n bookingStore.stopOrders\n )\n );\n const departures = computed(() => Object.values(departureGroups.value).flatMap(x => x));\n\n function $reset() {\n resetResult();\n\n state.isDirty = false;\n state.searchRequest = { ...defaultSearchRequest };\n state.selectedDepartureId = null;\n state.selectedDepartureIdIsExpanded = false;\n }\n\n function resetFilters() {\n state.searchRequest.filters = {\n modes: [],\n quays: []\n };\n }\n\n function resetResult() {\n Object.assign(searchResult, { ...defaultSearchResult });\n }\n\n function isValidSearchRequest(\n request: DeparturesSearchRequest\n ): request is { quay: PlaceAutocompleteModelDto } & DeparturesSearchRequest {\n return isDefined(request.quay?.id) && request.quay.type !== PlaceType.Unknown;\n }\n\n let searchAbortController: AbortController | undefined;\n\n async function _executeSearch(searchFunc: Function, onError?: Function) {\n try {\n await searchFunc();\n } catch (e) {\n const { name } = e as AxiosError;\n // in case of AbortController being triggered, do nothing\n if (name === 'CanceledError') return;\n\n mainStore.registerError(e);\n onError?.();\n }\n }\n\n async function search() {\n // search for departures for selected quay and time\n if (!isValidSearchRequest(state.searchRequest)) return;\n\n resetResult();\n state.isDirty = true;\n state.isLoading = true;\n\n // register history\n addItem(state.searchRequest.quay);\n\n // abort previous request\n searchAbortController?.abort();\n searchAbortController = new AbortController();\n\n await _executeSearch(\n async () => {\n state.isSearching = true;\n // search for trips with selected criteria\n const result = await searchService.searchForDepartures(state.searchRequest, {\n signal: searchAbortController?.signal\n });\n\n // TODO: check for bookings against booking store\n\n if (result) {\n searchResult.stopPlace = result;\n }\n\n state.isSearching = false;\n state.isLoading = false;\n\n // track event\n gtm?.trackEvent({\n event: 'app_event',\n category: 'departures_search',\n action: 'search',\n hasDateTime: !!state.searchRequest.dateTime\n });\n },\n () => {\n state.isSearching = false;\n state.isLoading = false;\n }\n );\n }\n\n function cancelSearch() {\n searchAbortController?.abort();\n }\n\n watch(\n () => state.selectedDepartureId,\n (value, oldValue) => {\n if (value === oldValue) return;\n\n // reset expanded item\n state.selectedDepartureIdIsExpanded = false;\n }\n );\n\n // TODO: should we just reset the modes filter?\n watch(\n () => searchResult.stopPlace,\n value => {\n if (!value) return;\n\n const { availableTransportModes } = value;\n // if any selected modes are missing in availableTransportModes, remove missing items\n if (state.searchRequest.filters.modes.every(m => availableTransportModes.includes(m))) return;\n\n state.searchRequest.filters.modes = state.searchRequest.filters.modes.filter(m => availableTransportModes.includes(m));\n },\n { deep: true }\n );\n\n watch(hasResult, value => {\n // we only want to check against a valid result\n if (!value || !departures.value.length) {\n state.selectedDepartureId = null;\n state.selectedDepartureIdIsExpanded = false;\n return;\n }\n\n // check if selectedTripPatternId exists in list\n // if it doesn't, reset selected trip pattern stuff\n if (!departures.value.some(x => x.id === state.selectedDepartureId)) {\n // TODO: show error for invalid trip pattern ID?\n state.selectedDepartureId = null;\n state.selectedDepartureIdIsExpanded = false;\n }\n });\n\n // trigger search when enturEndpointType changes\n watch(devModeConfiguration, async (value, oldValue) => {\n if (isEqual(value, oldValue)) return;\n\n await search();\n });\n\n return {\n ...toRefs(state),\n searchResult,\n canSearch,\n hasResult,\n stopPlaceTransportModes,\n stopPlaceQuays,\n selectedDeparture,\n departureGroups,\n $reset,\n resetFilters,\n resetResult,\n search,\n cancelSearch\n };\n});\n\n/**\n * Remove duplicate departures\n * @param departureGroups - The departure groups to remove duplicate departures from\n * @returns The departure groups with duplicate departures removed\n */\nfunction removeDuplicateDepartures(departureGroups: Record<string, DepartureDto[]>): Record<string, DepartureDto[]> {\n return Object.fromEntries(\n Object.entries(departureGroups).map(([key, departures]) => [\n key,\n departures.filter((departure, index, self) => index === self.findIndex(d => d.id === departure.id))\n ])\n );\n}\n","import { computed, nextTick, watch } from 'vue';\nimport { SearchMode, useMainStore } from '@/features/common/stores';\nimport { RouteLocationNormalized, useRouter } from 'vue-router';\nimport { routeNames } from '@/router';\nimport { useDeparturesSearchStore } from '@/features/departures/stores';\nimport { useTripSearchStore } from '@/features/trips/stores';\nimport { PlaceType } from '@/types/webapi';\nimport { i18nRoute } from '@/i18n';\nimport { storeToRefs } from 'pinia';\n\nexport function useSearchModeToggle() {\n const router = useRouter();\n const { currentRoute } = router;\n const mainStore = useMainStore();\n const tripStore = useTripSearchStore();\n const departuresStore = useDeparturesSearchStore();\n const { searchMode } = storeToRefs(mainStore);\n const disabled = computed(() => tripStore.isLoading || departuresStore.isLoading);\n\n function setMode(value: RouteLocationNormalized) {\n searchMode.value =\n value.name === routeNames.tripSearch\n ? SearchMode.Trip\n : value.name === routeNames.departuresSearch\n ? SearchMode.Departures\n : SearchMode.None;\n }\n\n // set initial mode based on current route\n setMode(currentRoute.value);\n\n watch(searchMode, (value, oldValue) => {\n if (value == oldValue) return;\n\n if (value == SearchMode.Trip) {\n // copy over quay as from value, if set\n const { quay } = departuresStore.searchRequest;\n\n // reset store\n departuresStore.$reset();\n\n nextTick(async () => {\n // reset store\n tripStore.$reset();\n\n // navigate\n await router.push(\n i18nRoute({\n name: routeNames.tripSearch,\n query: {\n fromId: quay ? quay.id : undefined\n }\n })\n );\n });\n } else if (value == SearchMode.Departures) {\n // copy over from as quay value, if set and is quay\n const { from } = tripStore.searchRequest;\n\n // reset store\n tripStore.$reset();\n\n nextTick(async () => {\n // reset store\n departuresStore.$reset();\n\n // navigate\n await router.push(\n i18nRoute({\n name: routeNames.departuresSearch,\n query: {\n fromId: from?.type === PlaceType.TransitStation ? from.id : undefined\n }\n })\n );\n });\n }\n });\n\n watch(currentRoute, (value, oldValue) => {\n if (value.name == oldValue?.name) return;\n\n setMode(value);\n });\n\n return {\n mode: searchMode,\n disabled\n };\n}\n","import { syncRef, useSessionStorage, watchDebounced } from '@vueuse/core';\nimport { ref, toValue, watch } from 'vue';\nimport { useRouter } from 'vue-router';\nimport { useMainStore } from '../stores';\nimport { storeToRefs } from 'pinia';\nimport { DevModeConfiguration } from '../models';\nimport { isEmpty, merge } from 'lodash-es';\n\nconst MIN_THRESHOLD = 10;\n\nexport function useDevModeActivator() {\n const mainStore = useMainStore();\n const { isDevMode, devModeConfiguration, config, defaultConfig } = storeToRefs(mainStore);\n\n const devModeSessionStorage = useSessionStorage<{ enabled?: boolean } | undefined>(\n 'travelplanner__devMode',\n {},\n { writeDefaults: false }\n );\n const devModeConfigurationSessionStorage = useSessionStorage<DevModeConfiguration | undefined>(\n 'travelplanner__devModeConfig',\n {},\n { writeDefaults: false }\n );\n\n const router = useRouter();\n const { currentRoute } = router;\n const modeChangeCounter = ref(0);\n const dialogIsVisible = ref(false);\n const showDevModeNotification = ref(false);\n\n function init() {\n syncRef(devModeSessionStorage, isDevMode, {\n transform: {\n rtl: right => (right ? { enabled: true } : undefined),\n ltr: left => left?.enabled || false\n }\n });\n\n // set initial value from config\n if (config.value.devModeEnabled) {\n isDevMode.value = true;\n }\n\n if (isDevMode.value) {\n setInitialDevModeConfiguration();\n } else {\n // start activator trigger if devMode isn't already activated\n const unwatchRoute = watch(currentRoute, (value, oldValue) => {\n if (value.name === oldValue.name) return;\n\n modeChangeCounter.value += 1;\n });\n\n const unwatchDebounced = watchDebounced(modeChangeCounter, () => (modeChangeCounter.value = 0), {\n debounce: 10000,\n maxWait: 15000\n });\n\n const unwatchCounter = watch(modeChangeCounter, value => {\n if (value < MIN_THRESHOLD) return;\n\n // once enabled, we no longer need this\n unwatchCounter();\n unwatchRoute();\n unwatchDebounced();\n\n setInitialDevModeConfiguration();\n isDevMode.value = true;\n showDevModeNotification.value = true;\n });\n }\n\n syncRef(devModeConfiguration, devModeConfigurationSessionStorage, {\n transform: {\n ltr: left => (left ? { ...left } : undefined)\n },\n direction: 'ltr'\n });\n\n syncRef(devModeConfiguration, config, {\n transform: {\n ltr: left => {\n return merge({}, toValue(config), {\n bookingConfig: {\n enabled: left && isDevMode.value ? left.enableBooking : defaultConfig.value?.bookingConfig?.enabled\n },\n isDebugModeEnabled: left && isDevMode.value ? left.enableDebugMode : defaultConfig.value?.isDebugModeEnabled,\n searchConfig: {\n directSearchEnabled:\n left && isDevMode.value\n ? left.enableDirectSearchMode\n : defaultConfig.value?.searchConfig?.directSearchEnabled\n }\n });\n }\n },\n direction: 'ltr'\n });\n }\n\n function setInitialDevModeConfiguration() {\n // use sessionStorage value if available, otherwise use default config\n devModeConfiguration.value = !isEmpty(devModeConfigurationSessionStorage.value)\n ? devModeConfigurationSessionStorage.value\n : {\n enableBooking: !!defaultConfig.value?.bookingConfig?.enabled,\n enableDebugMode: !!defaultConfig.value?.isDebugModeEnabled,\n enableAiSearch: false,\n enturEndpointType: 0,\n ngEndpointType: 0,\n enableDirectSearchMode: !!defaultConfig.value?.searchConfig?.directSearchEnabled\n };\n }\n\n function resetConfig() {\n // clear sessionStorage\n devModeConfigurationSessionStorage.value = undefined;\n // reset config\n setInitialDevModeConfiguration();\n dialogIsVisible.value = false;\n }\n\n return { dialogIsVisible, showDevModeNotification, init, resetConfig };\n}\n","<template>\n <v-sheet color=\"transparent\" class=\"search-mode-toggle\" :class=\"cssClasses\">\n <div class=\"search-mode-toggle__content rounded-t-lg\">\n <search-mode-toggle-button\n data-id=\"tripSearchModeToggleBtn\"\n :model-value=\"model === SearchMode.Trip\"\n :label=\"t('trips.resources.title', 'Travel planner')\"\n rounded=\"ts-lg\"\n @click=\"model = SearchMode.Trip\"\n />\n <search-mode-toggle-button\n data-id=\"departuresSearchModeToggleBtn\"\n :model-value=\"model === SearchMode.Departures\"\n :label=\"t('departures.resources.title', 'Departures')\"\n rounded=\"te-lg\"\n @click=\"model = SearchMode.Departures\"\n />\n </div>\n </v-sheet>\n</template>\n\n<script setup lang=\"ts\">\nimport { useI18n } from 'vue-i18n';\nimport { SearchMode } from '@/features/common/stores/mainStore';\nimport { SearchModeToggleButton } from '.';\nimport { computed } from 'vue';\n\ninterface Props {\n /**\n * The currently selected search mode (Trip or Departures)\n */\n modelValue: SearchMode;\n\n /**\n * Whether the toggle buttons are disabled\n * @default false\n */\n disabled?: boolean;\n}\n\nconst props = defineProps<Props>();\nconst model = defineModel<SearchMode>('modelValue', { required: true });\nconst { t } = useI18n();\nconst cssClasses = computed(() => ({ 'search-mode-toggle--disabled': props.disabled }));\n</script>\n\n<style lang=\"scss\">\n@use '@geta/kolumbus-frontend/styles/vuetify' as *;\n@use 'sass:map';\n\n.search-mode-toggle {\n --search-mode-toggle__btn-bg-color: var(--v-color-grey-lighten-3);\n --search-mode-toggle__btn-border-color: var(--v-color-grey-lighten-2);\n --search-mode-toggle__btn-width: 50%;\n\n position: relative;\n margin-bottom: -1px;\n z-index: 1;\n transition-property: opacity;\n transition-duration: 0.2;\n transition-timing-function: ease-in-out;\n\n @media #{map.get($display-breakpoints, 'md-and-up')} {\n --search-mode-toggle__btn-width: 198px;\n }\n\n &__content {\n position: relative;\n display: flex;\n flex-direction: row;\n width: 100%;\n background-color: var(--search-mode-toggle__btn-bg-color, #f8f8f8);\n border-color: var(--search-mode-toggle__btn-border-color, #e6e6e6);\n border-style: solid;\n border-width: 0;\n\n @media #{map.get($display-breakpoints, 'md-and-up')} {\n width: calc(var(--search-mode-toggle__btn-width) * 2 + 2px);\n border-width: 1px 1px 0 1px;\n }\n }\n\n &--disabled {\n opacity: var(--v-disabled-opacity, 0.38);\n pointer-events: none;\n }\n\n .search-mode-toggle__btn {\n width: var(--search-mode-toggle__btn-width);\n }\n}\n</style>\n","<template>\n <v-navigation-drawer\n v-model=\"_modelValue\"\n :location=\"isMobile ? 'bottom' : 'left'\"\n :width=\"isMobile ? 0 : 480\"\n color=\"white\"\n elevation=\"4\"\n border=\"0\"\n :rounded=\"isMobile && !fullHeight ? 't-lg' : '0'\"\n permanent\n class=\"app-drawer\"\n :class=\"cssClasses\"\n :style=\"mainStyles\"\n >\n <div class=\"app-drawer__inner\">\n <div class=\"app-drawer__content\">\n <slot />\n </div>\n <div class=\"app-drawer__toggle d-none d-md-flex align-md-center\">\n <v-btn width=\"30\" min-width=\"30\" height=\"54\" rounded=\"s-0 e-lg\" class=\"pa-0 ma-0\" @click=\"_modelValue = !_modelValue\">\n <v-icon size=\"36\" :icon=\"_modelValue ? 'mdi-menu-left' : 'mdi-menu-right'\" />\n </v-btn>\n </div>\n </div>\n </v-navigation-drawer>\n</template>\n\n<script setup lang=\"ts\">\nimport { useVModel } from '@vueuse/core';\nimport { useDisplay } from 'vuetify';\nimport { computed } from 'vue';\nimport { useLayout } from 'vuetify';\n\ninterface Props {\n modelValue: boolean;\n fullHeight?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), { fullHeight: true });\nconst _modelValue = useVModel(props, 'modelValue');\nconst { mobile: isMobile } = useDisplay();\nconst cssClasses = computed(() => ({ 'app-drawer--full-height': props.fullHeight }));\nconst { mainStyles } = useLayout();\n</script>\n\n<style lang=\"scss\">\n@use '@geta/kolumbus-frontend/styles/vuetify' as *;\n@use 'sass:map';\n\n.app-drawer {\n height: auto;\n\n &__inner,\n &__content {\n height: 100%;\n }\n\n &__toggle {\n pointer-events: none;\n\n @media #{map.get($display-breakpoints, 'md-and-up')} {\n position: absolute;\n top: 0;\n right: -30px;\n height: 100%;\n }\n\n .v-btn {\n pointer-events: all;\n clip-path: inset(0 -5px 0 0);\n\n // this ensures the button background color matches the content background color when the search result is expanded\n .app-drawer:has(.v-window-item--active > .search-result) & {\n background-color: var(--search-result-bg-color);\n }\n }\n }\n\n &--full-height {\n @media #{map.get($display-breakpoints, 'sm-and-down')} {\n height: calc(100% - var(--v-layout-top)) !important;\n }\n }\n\n &:has(.search-result[expanded='true']) {\n .app-drawer__inner {\n height: 100%;\n }\n }\n}\n</style>\n","<template>\n <div class=\"datetime-selector\">\n <v-btn-toggle\n v-model=\"__type\"\n :disabled=\"disabled\"\n rounded=\"md\"\n color=\"primary\"\n variant=\"flat\"\n group\n mandatory\n class=\"datetime-selector__btns\"\n >\n <v-btn v-for=\"dt in _types\" :key=\"dt\" :value=\"dt\" class=\"datetime-selector__btn\">\n {{ t(`common.resources.dateTimePicker.${camelCase(DateType[dt])}`, DateType[dt]) }}\n </v-btn>\n </v-btn-toggle>\n <div v-if=\"showDateTimePicker && _modelValue\" class=\"mt-2 w-100\">\n <date-time-picker\n v-model=\"_modelValue\"\n :min-date=\"minDate\"\n :max-date=\"maxDate\"\n :disabled=\"disabled\"\n density=\"compact\"\n variant=\"outlined\"\n color=\"primary\"\n base-color=\"grey\"\n bg-color=\"white\"\n active-class=\"elevation-4\"\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { DateType } from '@/features/common/models';\nimport { DateTimePicker } from '@geta/kolumbus-frontend/components';\nimport { computed, ref } from 'vue';\nimport { useI18n } from 'vue-i18n';\nimport { startOfMinute } from 'date-fns';\nimport { camelCase } from 'lodash-es';\n\ninterface Props {\n modelValue?: Date;\n type?: DateType;\n types?: DateType[];\n minDate?: Date | number;\n maxDate?: Date | number;\n disabled?: boolean;\n}\n\nconst { t } = useI18n();\nconst props = withDefaults(defineProps<Props>(), { type: DateType.Now });\nconst _modelValue = defineModel<Date | undefined>('modelValue');\nconst _type = defineModel<DateType>('type', { default: DateType.Now });\nconst localType = ref<DateType>(_type.value);\nconst __type = computed({\n get() {\n return _type.value || localType.value;\n },\n set(value) {\n _type.value = localType.value = value;\n\n if (value === DateType.Now) {\n _modelValue.value = undefined;\n } else if (!_modelValue.value) {\n _modelValue.value = startOfMinute(new Date());\n }\n }\n});\nconst _types = computed(() => props.types || [DateType.Now, DateType.DepartAt]);\nconst showDateTimePicker = computed(() => __type.value !== DateType.Now);\n</script>\n\n<style lang=\"scss\">\n@use '@geta/kolumbus-frontend/styles/vuetify' as *;\n\n.datetime-selector {\n &__btns {\n width: 100%;\n display: flex;\n flex-direction: row;\n\n &.v-btn-group--density-default.v-btn-group {\n height: 40px;\n }\n\n &.v-btn-group .v-btn:not(:last-child) {\n border-inline-end: 1px solid var(--v-color-grey-lighten-2);\n }\n\n &.v-btn-group .v-btn--active,\n &.v-btn-group .v-btn:has(+ .v-btn--active) {\n border-inline-end: none !important;\n }\n }\n\n &__btn {\n flex: 1 1 0;\n border: 1px solid var(--v-color-grey-lighten-2);\n font-size: calc(18px / $font-size-root) * 1rem;\n font-weight: 400;\n\n &.v-btn--active {\n font-weight: 700;\n border: 0 none;\n }\n }\n\n .datetime-picker .v-input {\n font-weight: 400;\n }\n}\n</style>\n","<template>\n <v-confirm-edit ref=\"confirmEditRef\" v-model=\"_modelValue\">\n <template #default=\"{ model: proxyModel, actions: _, isPristine }\">\n <v-card class=\"dev-mode-configurator\">\n <v-card-title class=\"px-4 pt-4 pb-2\">\n <span class=\"text-h3\">Dev Mode Configurations</span>\n </v-card-title>\n <v-divider class=\"mx-4\" />\n <v-card-text class=\"pa-4\">\n <v-sheet color=\"grey-lighten-3\" rounded class=\"pa-2 my-4\">\n <v-row dense>\n <v-col cols=\"12\" md=\"auto\" class=\"d-flex align-center\">\n <p class=\"text-h5 font-weight-regular\">Debug Mode</p>\n </v-col>\n <v-spacer />\n <v-col cols=\"12\" md=\"auto\">\n <v-switch v-model=\"proxyModel.value.enableDebugMode\" hide-details inset color=\"primary\" density=\"compact\" />\n </v-col>\n </v-row>\n </v-sheet>\n <v-sheet color=\"grey-lighten-3\" rounded class=\"pa-2 my-4\">\n <v-row dense>\n <v-col cols=\"12\" md=\"auto\" class=\"d-flex align-center\">\n <p class=\"text-h5 font-weight-regular\">Direct Search Mode</p>\n </v-col>\n <v-spacer />\n <v-col cols=\"12\" md=\"auto\">\n <v-switch\n v-model=\"proxyModel.value.enableDirectSearchMode\"\n hide-details\n inset\n color=\"primary\"\n density=\"compact\"\n />\n </v-col>\n </v-row>\n </v-sheet>\n\n <p class=\"text-h5\">API Endpoints</p>\n\n <v-sheet color=\"grey-lighten-3\" rounded class=\"pa-2 my-4\">\n <v-row dense>\n <v-col cols=\"12\" md=\"auto\" class=\"d-flex align-center\">\n <p class=\"text-h5 font-weight-regular\">Entur</p>\n </v-col>\n <v-spacer />\n <v-col cols=\"12\" md=\"auto\">\n <v-btn-toggle\n v-model=\"proxyModel.value.enturEndpointType\"\n color=\"primary\"\n group\n mandatory\n density=\"compact\"\n >\n <v-btn :value=\"0\"> Default </v-btn>\n <v-btn :value=\"1\"> Dev </v-btn>\n <v-btn :value=\"2\"> Test </v-btn>\n <v-btn :value=\"3\"> Prod </v-btn>\n </v-btn-toggle>\n </v-col>\n </v-row>\n </v-sheet>\n\n <v-sheet color=\"grey-lighten-3\" rounded class=\"pa-2 my-4\">\n <v-row dense>\n <v-col cols=\"12\" md=\"auto\" class=\"d-flex align-center\">\n <p class=\"text-h5 font-weight-regular\">SanntidNG</p>\n </v-col>\n <v-spacer />\n <v-col cols=\"12\" md=\"auto\">\n <v-btn-toggle v-model=\"proxyModel.value.ngEndpointType\" color=\"primary\" group mandatory density=\"compact\">\n <v-btn :value=\"0\"> Default </v-btn>\n <v-btn :value=\"1\"> Dev </v-btn>\n <v-btn :value=\"2\"> Test </v-btn>\n <v-btn :value=\"3\"> Prod </v-btn>\n </v-btn-toggle>\n </v-col>\n <v-col cols=\"12\">\n <p class=\"text-subtitle-1\">\n <strong>NOTE:</strong> Modifying this value may cause discrepancies between bookings stored in the\n database with the ones stored on the API.\n </p>\n </v-col>\n </v-row>\n </v-sheet>\n\n <p class=\"text-h5\">Features</p>\n\n <v-sheet color=\"grey-lighten-3\" rounded class=\"pa-2 my-4\">\n <v-row dense>\n <v-col cols=\"12\" md=\"auto\" class=\"d-flex align-center\">\n <p class=\"text-h5 font-weight-regular\">Booking</p>\n </v-col>\n <v-spacer />\n <v-col cols=\"12\" md=\"auto\">\n <v-switch v-model=\"proxyModel.value.enableBooking\" hide-details inset color=\"primary\" density=\"compact\" />\n </v-col>\n </v-row>\n </v-sheet>\n <v-sheet color=\"grey-lighten-3\" rounded class=\"pa-2 my-4\">\n <v-row dense>\n <v-col cols=\"12\" md=\"auto\" class=\"d-flex align-center\">\n <p class=\"text-h5 font-weight-regular\">AI Search</p>\n </v-col>\n <v-spacer />\n <v-col cols=\"12\" md=\"auto\">\n <v-switch v-model=\"proxyModel.value.enableAiSearch\" hide-details inset color=\"primary\" density=\"compact\" />\n </v-col>\n </v-row>\n </v-sheet>\n </v-card-text>\n\n <v-divider class=\"mx-4\" />\n\n <v-card-actions class=\"px-4\">\n <v-btn @click=\"reset\">Defaults</v-btn>\n <v-spacer></v-spacer>\n\n <v-btn @click=\"cancel\">Cancel</v-btn>\n <v-btn color=\"primary\" :disabled=\"isPristine\" @click=\"save\">Save</v-btn>\n </v-card-actions>\n </v-card>\n </template>\n </v-confirm-edit>\n</template>\n\n<script setup lang=\"ts\">\nimport { useVModel } from '@vueuse/core';\nimport { ref } from 'vue';\nimport { VConfirmEdit } from 'vuetify/components';\nimport { DevModeConfiguration } from '../../models';\n\ninterface Props {\n modelValue?: DevModeConfiguration;\n}\n\ninterface Emits {\n (e: 'update:modelValue', value: DevModeConfiguration): void;\n (e: 'save'): void;\n (e: 'cancel'): void;\n (e: 'reset'): void;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n modelValue: () => ({\n enturEndpointType: 0,\n ngEndpointType: 0,\n enableAiSearch: false,\n enableBooking: false,\n enableDebugMode: false,\n enableDirectSearchMode: false\n })\n});\nconst emit = defineEmits<Emits>();\nconst _modelValue = useVModel(props, 'modelValue');\nconst confirmEditRef = ref<InstanceType<typeof VConfirmEdit>>();\n\nfunction save() {\n confirmEditRef.value?.save();\n emit('save');\n}\n\nfunction cancel() {\n confirmEditRef.value?.cancel();\n emit('cancel');\n}\n\nfunction reset() {\n emit('reset');\n}\n</script>\n\n<style lang=\"scss\">\n.dev-mode-configurator .v-switch.v-switch--inset .v-selection-control--dirty .v-switch__track {\n transition: opacity 0.2s;\n opacity: 1;\n}\n</style>\n","<template>\n <div class=\"trip-leg-list\" :class=\"themeClasses\">\n <slot />\n </div>\n</template>\n\n<script setup lang=\"ts\">\n// @ts-ignore\nimport { makeThemeProps, provideTheme } from 'vuetify/lib/composables/theme.mjs';\n\nconst props = defineProps({ ...makeThemeProps() });\nconst { themeClasses } = provideTheme(props);\n</script>\n","<template>\n <error-boundary\n v-model=\"lastKnownError\"\n :errors-to-display=\"['PlacesError', 'GeolocationError', 'BookingError', 'ProfileError']\"\n :stop-propagation=\"true\"\n @reload=\"refresh\"\n @error-captured=\"registerError\"\n >\n <v-app class=\"tp-app\" :class=\"cssClasses\">\n <v-layout v-if=\"mainStore.ready\" full-height>\n <v-dialog v-if=\"mainStore.isDevMode\" v-model=\"dialogIsVisible\" max-width=\"500\">\n <template #activator=\"{ props: activatorProps }\">\n <div class=\"position-absolute top-0 right-0 pa-2\" style=\"z-index: 1000\">\n <v-btn v-bind=\"activatorProps\" icon color=\"warning\">\n <v-icon icon=\"mdi-xml\" size=\"32\" />\n </v-btn>\n </div>\n </template>\n <dev-mode-configurator\n v-model=\"mainStore.devModeConfiguration\"\n @update:model-value=\"dialogIsVisible = false\"\n @cancel=\"dialogIsVisible = false\"\n @reset=\"resetConfig\"\n />\n </v-dialog>\n\n <site-header\n v-model:current-language=\"language\"\n :menu-items=\"menuItems\"\n :is-logged-in=\"userStore.isLoggedIn\"\n :profile-info=\"userStore.getProfile\"\n class=\"tp-app__header\"\n />\n\n <app-drawer v-model=\"showAppDrawer\" :full-height=\"drawerIsFullHeight\" class=\"tp-app__drawer\">\n <div id=\"appDrawerPrepend\" />\n <router-view :key=\"route.path\" name=\"appDrawer\" />\n </app-drawer>\n\n <v-main>\n <v-container fluid class=\"pa-0 h-100\" style=\"position: relative\">\n <router-view name=\"main\" />\n </v-container>\n </v-main>\n </v-layout>\n\n <v-overlay :model-value=\"!mainStore.ready\" scrim=\"white\" class=\"align-center justify-center\">\n <v-progress-circular data-id=\"appLoadingProgress\" color=\"primary\" indeterminate size=\"64\" />\n </v-overlay>\n <silent-login v-if=\"config.silentLoginEnabled && userLoaded && !userStore.isLoggedIn\" />\n\n <v-dialog v-model=\"showDevModeNotification\" max-width=\"500\" persistent>\n <v-card>\n <v-card-title class=\"pt-4 px-6 pt-md-6\">\n <h1 class=\"text-h3\">Developer Mode Activated</h1>\n </v-card-title>\n <v-card-text class=\"text-h6 font-weight-regular py-0\">\n <p class=\"my-2\">Developer Mode allows you to change various settings that affect how this app functions.</p>\n <p class=\"my-2\">\n All changes are persistent for the current session. To disable Developer Mode, simply open the app in a new tab.\n </p>\n </v-card-text>\n <v-card-actions class=\"px-4 pb-4 px-md-6\">\n <v-spacer />\n <v-btn color=\"primary\" @click=\"showDevModeNotification = false\">Understood</v-btn>\n </v-card-actions>\n </v-card>\n </v-dialog>\n </v-app>\n </error-boundary>\n</template>\n\n<script setup lang=\"ts\">\nimport { useRoute, useRouter } from 'vue-router';\nimport { getCurrentInstance, nextTick, onMounted, provide, ref, watch } from 'vue';\nimport { storeToRefs } from 'pinia';\nimport { useMainStore } from '@/features/common/stores';\nimport { SiteHeader, ErrorBoundary } from '@geta/kolumbus-frontend/components';\nimport { AppDrawer, DevModeConfigurator } from '@/features/common/components';\nimport { useDevModeActivator } from '@/features/common/composables';\nimport { useUserStore, SilentLogin } from '@geta/kolumbus-frontend/features/authentication';\nimport { AppProvideKey } from './injectionKeys';\nimport { createGtm } from 'vue-gtm';\nimport { useEventListener } from '@vueuse/core';\nimport { useBookingFeature } from './features/bookings/composables';\nimport { useDisplay } from 'vuetify';\nimport { useDeparturesSearchStore } from './features/departures/stores';\nimport { useTripSearchStore } from './features/trips/stores';\nimport { routeNames } from './router';\n\nuseBookingFeature();\nconst route = useRoute();\nconst router = useRouter();\nconst mainStore = useMainStore();\nconst userStore = useUserStore();\nconst tripSearchStore = useTripSearchStore();\nconst departuresSearchStore = useDeparturesSearchStore();\nconst { menuItems, language, showAppDrawer, config, lastKnownError } = storeToRefs(mainStore);\nconst { mobile: isMobile } = useDisplay();\nconst { dialogIsVisible, showDevModeNotification, init: initDevModeActivator, resetConfig } = useDevModeActivator();\n\nconst userLoaded = ref(false);\nconst cssClasses = ref<string[]>([]);\nconst currentTime = ref(new Date());\nconst drawerIsFullHeight = ref(true);\n\nfunction setDrawerFullHeight(fullHeight: boolean) {\n drawerIsFullHeight.value = fullHeight;\n}\n\nprovide(AppProvideKey, { currentTime, setDrawerFullHeight });\n\nwatch(language, async (value, oldValue) => {\n if (value !== oldValue) {\n try {\n await router.replace({ params: { locale: value }, query: route.query });\n } catch (e) {\n mainStore.registerError(e);\n router.push('/');\n }\n }\n});\n\nconst instance = getCurrentInstance();\n\nonMounted(async () => {\n // start clock\n setInterval(() => (currentTime.value = new Date()), 1000);\n\n // init store\n await mainStore.init();\n initDevModeActivator();\n\n // add event listener to add/remove focused class whenever an input field is focused\n useEventListener(\n document,\n ['focus', 'blur'],\n e => {\n if ((e.target as Element).nodeName !== 'INPUT') return;\n\n if (e.type === 'focus') {\n cssClasses.value.push('tp-app--has-focused');\n } else if (e.type === 'blur') {\n cssClasses.value = cssClasses.value.filter(x => x !== 'tp-app--has-focused');\n }\n },\n true\n );\n\n // load user\n if (config.value?.silentLoginEnabled) {\n try {\n await userStore.loadUserSilent();\n await userStore.loadUser();\n await userStore.loadProfile(menuItems.value?.loginLink);\n\n userLoaded.value = true;\n } catch {\n // we should not stop loading the app when user loading fails\n // TODO: display error?\n }\n }\n\n // set up gtm\n if (instance && config.value?.googleTagManagerConfig?.id) {\n instance.appContext.app.use(createGtm({ id: config.value.googleTagManagerConfig.id }));\n }\n\n // set up router guard to reset stores when navigating away from trip search or departures search\n router.beforeEach((to, from, next) => {\n // reset stores if navigating away from trip search or departures search\n // but not if navigating to booking details\n if (to.name !== from.name && to.name !== routeNames.bookingDetails) {\n tripSearchStore.$reset();\n departuresSearchStore.$reset();\n }\n\n next();\n });\n\n mainStore.ready = true;\n});\n\nfunction refresh() {\n location.reload();\n}\n\nfunction registerError(e: Error | undefined) {\n mainStore.registerError(e);\n}\n\n// reset app drawer when going from desktop to mobile\nwatch(\n isMobile,\n value => {\n if (!value) return;\n\n nextTick(() => (showAppDrawer.value = true));\n },\n { immediate: true }\n);\n</script>\n\n<style lang=\"scss\">\n.tp-app {\n &__header {\n z-index: 1000;\n }\n\n &__drawer {\n z-index: 900;\n }\n\n &__banner {\n position: absolute;\n right: 0;\n z-index: 1000;\n width: calc(100% - var(--v-layout-left));\n }\n}\n\n.v-main {\n z-index: 1;\n}\n</style>\n","import { createPinia } from 'pinia';\n\nconst pinia = createPinia();\n\nexport default pinia;\n","import '@mdi/font/css/materialdesignicons.css';\nimport '@geta/kolumbus-assets';\nimport 'vuetify/styles';\nimport '@geta/kolumbus-frontend/styles';\nimport '@/styles/main.scss';\nimport 'reflect-metadata';\nimport { createApp } from 'vue';\nimport { createVuetify } from 'vuetify';\nimport { createVueI18nAdapter } from 'vuetify/locale/adapters/vue-i18n';\nimport App from './App.vue';\nimport pinia from './store';\nimport router from './router';\nimport i18n from './i18n';\nimport v1 from '@geta/kolumbus-frontend/blueprints/v1';\nimport { createContainer } from '@/plugins/inversify';\nimport { useI18n } from 'vue-i18n';\nimport { useMainStore } from './features/common/stores';\nimport { VueReCaptcha } from 'vue-recaptcha-v3-esm';\n\nconst app = createApp(App)\n .use(createContainer())\n .use(router)\n .use(pinia)\n .use(i18n)\n .use(\n createVuetify({\n blueprint: v1,\n locale: {\n adapter: createVueI18nAdapter({ i18n, useI18n })\n }\n })\n );\n\nconst mainStore = useMainStore();\nmainStore.loadConfig().then(() => {\n if (mainStore.config?.googleRecaptcha?.siteKey) {\n app.use(VueReCaptcha, {\n siteKey: mainStore.config.googleRecaptcha.siteKey,\n loaderOptions: { autoHideBadge: true }\n });\n }\n\n app.mount('#app');\n});\n"],"file":"assets/index-Cp9yJHeF.js"}