diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 54592bd..04dbfc3 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -21,6 +21,7 @@
       },
       "devDependencies": {
         "@tsconfig/node22": "^22.0.0",
+        "@types/lodash": "^4.17.15",
         "@types/node": "^22.13.4",
         "@vitejs/plugin-vue": "^5.2.1",
         "@vue/eslint-config-prettier": "^10.2.0",
@@ -1734,6 +1735,13 @@
       "dev": true,
       "license": "MIT"
     },
+    "node_modules/@types/lodash": {
+      "version": "4.17.15",
+      "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.15.tgz",
+      "integrity": "sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==",
+      "dev": true,
+      "license": "MIT"
+    },
     "node_modules/@types/node": {
       "version": "22.13.4",
       "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.4.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index abce684..76e0c80 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -26,6 +26,7 @@
   },
   "devDependencies": {
     "@tsconfig/node22": "^22.0.0",
+    "@types/lodash": "^4.17.15",
     "@types/node": "^22.13.4",
     "@vitejs/plugin-vue": "^5.2.1",
     "@vue/eslint-config-prettier": "^10.2.0",
diff --git a/frontend/src/components/Map.vue b/frontend/src/components/Map.vue
index c6762be..0aa855a 100644
--- a/frontend/src/components/Map.vue
+++ b/frontend/src/components/Map.vue
@@ -3,12 +3,12 @@
     <div class="loading" v-if="loading">Loading...</div>
     <div class="map-wrapper" v-else>
       <div id="map">
-        <div class="time-range" v-if="gpsPoints?.length">
+        <div class="time-range" v-if="oldestPoint && newestPoint">
           <div class="row">
             <div class="key">From</div>
             <div class="value">
               <a href="#" @click.prevent.stop="onStartDateClick">
-                {{ displayDate(oldestPoint?.timestamp) }}
+                {{ displayDate(oldestPoint.timestamp) }}
               </a>
             </div>
           </div>
@@ -16,7 +16,7 @@
             <div class="key">To</div>
             <div class="value">
               <a href="#" @click.prevent.stop="onEndDateClick">
-                {{ displayDate(newestPoint?.timestamp) }}
+                {{ displayDate(newestPoint.timestamp) }}
               </a>
             </div>
           </div>
@@ -38,7 +38,7 @@
                         :has-next-page="hasNextPage"
                         :has-prev-page="hasPrevPage"
                         @refresh="locationQuery = $event"
-                        @reset-page="locationQuery.minId = locationQuery.maxId = undefined"
+                        @reset-page="locationQuery.minId = locationQuery.maxId = null"
                         @next-page="fetchNextPage"
                         @prev-page="fetchPrevPage" />
           </div>
@@ -94,7 +94,6 @@ export default {
   data() {
     return {
       loading: false,
-      locationQuery: new LocationQuery({}),
       map: null as Nullable<Map>,
       mappedPoints: [] as Point[],
       mapView: null as Nullable<View>,
@@ -140,16 +139,19 @@ export default {
 
     createMap(gpsPoints: GPSPoint[]): Map {
       this.mappedPoints = this.toMappedPoints(gpsPoints)
-      this.pointsLayer = this.createPointsLayer(this.mappedPoints)
-      this.routesLayer = this.createRoutesLayer(this.mappedPoints)
+      this.pointsLayer = this.createPointsLayer(this.mappedPoints as Point[])
+      this.routesLayer = this.createRoutesLayer(this.mappedPoints as Point[])
       this.mapView = this.mapView || this.createMapView(gpsPoints)
       const map = new Map({
         target: 'map',
         layers: [
           this.createMapLayer(),
+          // @ts-ignore
           this.pointsLayer,
+          // @ts-ignore
           this.routesLayer,
         ],
+        // @ts-ignore
         view: this.mapView,
       })
 
@@ -194,15 +196,15 @@ export default {
     },
 
     onStartDateClick() {
-      this.locationQuery.startDate = this.oldestPoint?.timestamp
-      this.locationQuery.minId = undefined
-      this.locationQuery.maxId = undefined
+      this.locationQuery.startDate = this.oldestPoint?.timestamp || null
+      this.locationQuery.minId = null
+      this.locationQuery.maxId = null
     },
 
     onEndDateClick() {
-      this.locationQuery.endDate = this.newestPoint?.timestamp
-      this.locationQuery.minId = undefined
-      this.locationQuery.maxId = undefined
+      this.locationQuery.endDate = this.newestPoint?.timestamp || null
+      this.locationQuery.minId = null
+      this.locationQuery.maxId = null
     },
   },
 
@@ -215,8 +217,8 @@ export default {
         if (!isFirstQuery &&
           (newQuery.startDate !== oldQuery.startDate || newQuery.endDate !== oldQuery.endDate)
         ) {
-          newQuery.minId = undefined
-          newQuery.maxId = undefined
+          newQuery.minId = null
+          newQuery.maxId = null
           this.hasNextPage = true
           this.hasPrevPage = true
         }
@@ -254,8 +256,11 @@ export default {
 
         this.mappedPoints = this.toMappedPoints(this.gpsPoints)
         if (this.mapView) {
+          // @ts-ignore
           this.refreshMapView(this.mapView, this.gpsPoints)
+          // @ts-ignore
           this.refreshPointsLayer(this.pointsLayer, this.mappedPoints)
+          // @ts-ignore
           this.refreshRoutesLayer(this.routesLayer, this.mappedPoints)
         }
       },
diff --git a/frontend/src/components/filter/Form.vue b/frontend/src/components/filter/Form.vue
index 105cbe1..f0bf303 100644
--- a/frontend/src/components/filter/Form.vue
+++ b/frontend/src/components/filter/Form.vue
@@ -8,8 +8,8 @@
         <input type="datetime-local"
                id="start-date"
                name="start-date"
-               @input="newFilter.startDate = startPlusHours($event.target.value, 0)"
-               @change="newFilter.startDate = startPlusHours($event.target.value, 0)"
+               @input="newFilter.startDate = startPlusHours($event, 0)"
+               @change="newFilter.startDate = startPlusHours($event, 0)"
                :value="toLocalString(newFilter.startDate)"
                :disabled="disabled"
                :max="maxDate" />
@@ -44,8 +44,8 @@
         <input type="datetime-local"
                id="end-date"
                name="end-date"
-               @input="newFilter.endDate = endPlusHours($event.target.value, 0)"
-               @change="newFilter.endDate = endPlusHours($event.target.value, 0)"
+               @input="newFilter.endDate = endPlusHours($event, 0)"
+               @change="newFilter.endDate = endPlusHours($event, 0)"
                :value="toLocalString(newFilter.endDate)"
                :disabled="disabled"
                :max="maxDate" />
@@ -80,7 +80,7 @@
       <div class="page-button-container">
         <button type="button"
                 :disabled="disabled"
-                v-if="value.minId || value.maxId"
+                v-if="value?.minId || value?.maxId"
                 @click.stop="$emit('reset-page')">
           <font-awesome-icon icon="fas fa-undo" />
         </button>
@@ -99,8 +99,8 @@
         <input type="number"
                id="limit"
                name="limit"
-               @input="newFilter.limit = Number($event.target.value)"
-               @change="newFilter.limit = Number($event.target.value)"
+               @input="setLimit"
+               @change="setLimit"
                :value="newFilter.limit"
                :disabled="disabled"
                min="1" />
@@ -168,8 +168,8 @@ export default {
       return !_.isEqual(
         {
           ...oldValue,
-          startDate: this.normalizeDate(this.value.startDate),
-          endDate: this.normalizeDate(this.value.endDate),
+          startDate: this.normalizeDate(this.value?.startDate),
+          endDate: this.normalizeDate(this.value?.endDate),
         },
         {
           ...newValue,
@@ -179,7 +179,7 @@ export default {
       )
     },
 
-    normalizeDate(date: Date | number | string | null): Date | null {
+    normalizeDate(date: any): Date | null {
       if (!date) {
         return null
       }
@@ -203,7 +203,11 @@ export default {
       ).toISOString().slice(0, -8)
     },
 
-    startPlusHours(date: Date | number | null, hours: number): Date | null {
+    startPlusHours(date: Date | number | Event | undefined | null, hours: number): Date | null {
+      if ((date as any)?.target?.value) {
+        date = (date as any).target.value
+      }
+
       let d = this.normalizeDate(date)
       if (!d) {
         return null
@@ -219,11 +223,15 @@ export default {
       return d
     },
 
-    startPlusDays(date: Date | number | null, days: number): Date | null {
+    startPlusDays(date: Date | number | Event | undefined | null, days: number): Date | null {
       return this.startPlusHours(date, days * 24)
     },
 
-    endPlusHours(date: Date | number | null, hours: number): Date | null {
+    endPlusHours(date: Date | number | Event | undefined | null, hours: number): Date | null {
+      if ((date as any)?.target?.value) {
+        date = (date as any).target.value
+      }
+
       let d = this.normalizeDate(date)
       if (!d) {
         return null
@@ -244,13 +252,17 @@ export default {
       return d
     },
 
-    endPlusDays(date: Date | number | null, days: number): Date | null {
+    endPlusDays(date: Date | number | Event | undefined | null, days: number): Date | null {
       return this.endPlusHours(date, days * 24)
     },
 
     handleSubmit() {
       this.$emit('refresh', this.newFilter)
     },
+
+    setLimit(event: Event) {
+      this.newFilter.limit = Number((event.target as HTMLInputElement).value)
+    },
   },
 
   watch: {
diff --git a/frontend/src/mixins/Dates.vue b/frontend/src/mixins/Dates.vue
index 926d775..089b3e9 100644
--- a/frontend/src/mixins/Dates.vue
+++ b/frontend/src/mixins/Dates.vue
@@ -1,7 +1,7 @@
 <script lang="ts">
 export default {
   methods: {
-    displayDate(date: Date | number | string | null): string {
+    displayDate(date: Date | number | string | null | undefined): string {
       if (!date) {
         return '-'
       }
diff --git a/frontend/src/mixins/Paginate.vue b/frontend/src/mixins/Paginate.vue
index f1254f7..1cc62b7 100644
--- a/frontend/src/mixins/Paginate.vue
+++ b/frontend/src/mixins/Paginate.vue
@@ -8,16 +8,17 @@ export default {
       gpsPoints: [] as GPSPoint[],
       hasNextPage: true,
       hasPrevPage: true,
+      locationQuery: new LocationQuery({}),
     }
   },
 
   computed: {
-    newestPoint(): GPSPoint | undefined {
-      return this.gpsPoints[this.gpsPoints.length - 1] || undefined
+    newestPoint(): GPSPoint | null {
+      return this.gpsPoints[this.gpsPoints.length - 1] || null
     },
 
-    oldestPoint(): GPSPoint | undefined {
-      return this.gpsPoints[0] || undefined
+    oldestPoint(): GPSPoint | null {
+      return this.gpsPoints[0] || null
     },
   },
 
diff --git a/frontend/src/mixins/Points.vue b/frontend/src/mixins/Points.vue
index e10b2a4..9a0c0a6 100644
--- a/frontend/src/mixins/Points.vue
+++ b/frontend/src/mixins/Points.vue
@@ -83,6 +83,10 @@ export default {
 
     refreshPointsLayer(layer: VectorLayer, points: Point[]) {
       const source = layer.getSource()
+      if (!source) {
+        return
+      }
+
       source.clear()
       source.addFeatures(points.map((point: Point) => new Feature(point)))
       source.changed()
diff --git a/frontend/src/mixins/Routes.vue b/frontend/src/mixins/Routes.vue
index 0e0e90f..e7b8cc7 100644
--- a/frontend/src/mixins/Routes.vue
+++ b/frontend/src/mixins/Routes.vue
@@ -27,13 +27,17 @@ export default {
     refreshRoutesLayer(layer: VectorLayer, points: Point[]) {
       const routeFeatures = this.extractRouteFeatures(points)
       const source = layer.getSource()
+      if (!source) {
+        return
+      }
+
       source.clear()
       source.addFeatures(routeFeatures)
       source.changed()
     },
 
     extractRouteFeatures(points: Point[]): Feature[] {
-      const routeFeatures = []
+      const routeFeatures: Feature[] = []
       points.forEach((point: Point, index: number) => {
         if (index === 0) {
           return
diff --git a/frontend/src/mixins/URLQueryHandler.vue b/frontend/src/mixins/URLQueryHandler.vue
index dde2fb6..c4f3aa9 100644
--- a/frontend/src/mixins/URLQueryHandler.vue
+++ b/frontend/src/mixins/URLQueryHandler.vue
@@ -11,7 +11,7 @@ function isDate(key: string, value: string): boolean {
   )
 }
 
-function parseValue(key: string, value: string | null): string | number | boolean | Date {
+function parseValue(key: string, value: string | null): string | number | boolean | Date | undefined {
   value = decodeURI(value?.trim() || '')
   if (!value.length) {
     return undefined