{"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"}