diff --git a/package-lock.json b/package-lock.json index b1a2cf4..f573959 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,8 +18,10 @@ "date-fns": "^4.1.0", "electron-squirrel-startup": "^1.0.1", "fuse.js": "^7.0.0", + "leaflet": "^1.9.4", "light-bolt11-decoder": "^3.2.0", "lucide-vue-next": "^0.474.0", + "ngeohash": "^0.6.3", "nostr-tools": "^2.10.4", "pinia": "^2.3.1", "qr-scanner": "^1.4.2", @@ -48,6 +50,8 @@ "@tailwindcss/forms": "^0.5.10", "@tailwindcss/typography": "^0.5.16", "@tailwindcss/vite": "^4.0.12", + "@types/leaflet": "^1.9.21", + "@types/ngeohash": "^0.6.8", "@types/node": "^22.18.1", "@types/qrcode": "^1.5.5", "@types/rollup-plugin-visualizer": "^4.2.3", @@ -5065,6 +5069,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/http-cache-semantics": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", @@ -5082,6 +5093,23 @@ "@types/node": "*" } }, + "node_modules/@types/leaflet": { + "version": "1.9.21", + "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.21.tgz", + "integrity": "sha512-TbAd9DaPGSnzp6QvtYngntMZgcRk+igFELwR2N99XZn7RXUdKgsXMR+28bUO0rPsWp8MIu/f47luLIQuSLYv/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/ngeohash": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@types/ngeohash/-/ngeohash-0.6.8.tgz", + "integrity": "sha512-A90x3HMwE1yXbWCnd0ztHzv8rAQPjwTzX2diYI/6OrWm/3oairDaehw5WPWJFgZ+8+J/OuF99IbipmMa2le6tQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "22.18.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.1.tgz", @@ -9775,6 +9803,12 @@ "json-buffer": "3.0.1" } }, + "node_modules/leaflet": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==", + "license": "BSD-2-Clause" + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -10905,6 +10939,15 @@ "node": ">= 0.6" } }, + "node_modules/ngeohash": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/ngeohash/-/ngeohash-0.6.3.tgz", + "integrity": "sha512-kltF0cOxgx1AbmVzKxYZaoB0aj7mOxZeHaerEtQV0YaqnkXNq26WWqMmJ6lTqShYxVRWZ/mwvvTrNeOwdslWiw==", + "license": "MIT", + "engines": { + "node": ">=v0.2.0" + } + }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", diff --git a/package.json b/package.json index ef5de0b..f88e2dd 100644 --- a/package.json +++ b/package.json @@ -30,8 +30,10 @@ "date-fns": "^4.1.0", "electron-squirrel-startup": "^1.0.1", "fuse.js": "^7.0.0", + "leaflet": "^1.9.4", "light-bolt11-decoder": "^3.2.0", "lucide-vue-next": "^0.474.0", + "ngeohash": "^0.6.3", "nostr-tools": "^2.10.4", "pinia": "^2.3.1", "qr-scanner": "^1.4.2", @@ -60,6 +62,8 @@ "@tailwindcss/forms": "^0.5.10", "@tailwindcss/typography": "^0.5.16", "@tailwindcss/vite": "^4.0.12", + "@types/leaflet": "^1.9.21", + "@types/ngeohash": "^0.6.8", "@types/node": "^22.18.1", "@types/qrcode": "^1.5.5", "@types/rollup-plugin-visualizer": "^4.2.3", diff --git a/src/modules/activities/components/ActivityCalendarView.vue b/src/modules/activities/components/ActivityCalendarView.vue new file mode 100644 index 0000000..7837e96 --- /dev/null +++ b/src/modules/activities/components/ActivityCalendarView.vue @@ -0,0 +1,168 @@ + + + diff --git a/src/modules/activities/components/ActivityMap.vue b/src/modules/activities/components/ActivityMap.vue new file mode 100644 index 0000000..9448bde --- /dev/null +++ b/src/modules/activities/components/ActivityMap.vue @@ -0,0 +1,124 @@ + + + diff --git a/src/modules/activities/types/activity.ts b/src/modules/activities/types/activity.ts index 7785725..24543a0 100644 --- a/src/modules/activities/types/activity.ts +++ b/src/modules/activities/types/activity.ts @@ -1,3 +1,4 @@ +import ngeohash from 'ngeohash' import type { ActivityCategory } from './category' import type { CalendarTimeEvent, CalendarDateEvent } from './nip52' @@ -82,6 +83,7 @@ export function calendarTimeEventToActivity(event: CalendarTimeEvent, organizer? endDate: event.end ? new Date(event.end * 1000) : undefined, timezone: event.startTzid, location: event.location, + coordinates: decodeGeohash(event.geohash), geohash: event.geohash, category, tags: event.hashtags, @@ -117,6 +119,7 @@ export function calendarDateEventToActivity(event: CalendarDateEvent, organizer? startDate: parseIsoDate(event.start), endDate: event.end ? parseIsoDate(event.end) : undefined, location: event.location, + coordinates: decodeGeohash(event.geohash), geohash: event.geohash, category, tags: event.hashtags, @@ -124,3 +127,13 @@ export function calendarDateEventToActivity(event: CalendarDateEvent, organizer? createdAt: new Date(event.createdAt * 1000), } } + +function decodeGeohash(geohash?: string): { lat: number; lng: number } | undefined { + if (!geohash) return undefined + try { + const { latitude, longitude } = ngeohash.decode(geohash) + return { lat: latitude, lng: longitude } + } catch { + return undefined + } +} diff --git a/src/modules/activities/views/ActivitiesCalendarPage.vue b/src/modules/activities/views/ActivitiesCalendarPage.vue index e09a719..c56b12a 100644 --- a/src/modules/activities/views/ActivitiesCalendarPage.vue +++ b/src/modules/activities/views/ActivitiesCalendarPage.vue @@ -1,13 +1,27 @@ diff --git a/src/modules/activities/views/ActivitiesMapPage.vue b/src/modules/activities/views/ActivitiesMapPage.vue index 85e053a..566146b 100644 --- a/src/modules/activities/views/ActivitiesMapPage.vue +++ b/src/modules/activities/views/ActivitiesMapPage.vue @@ -1,13 +1,44 @@