diff --git a/package-lock.json b/package-lock.json index d5d988c..2c93333 100644 --- a/package-lock.json +++ b/package-lock.json @@ -224,9 +224,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -244,9 +241,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -264,9 +258,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -284,9 +275,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -304,9 +292,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -324,9 +309,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -1189,9 +1171,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -1213,9 +1192,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -1237,9 +1213,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -1261,9 +1234,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ diff --git a/src/lib/JournalDetail.svelte b/src/lib/JournalDetail.svelte new file mode 100644 index 0000000..a00c0b0 --- /dev/null +++ b/src/lib/JournalDetail.svelte @@ -0,0 +1,313 @@ + + +
+ + + + {#if entry.photos.length > 0} + + {/if} + +
+
+ 📍 {entry.location.city}, {entry.location.country} + + {entry.tripType === 'solo' ? '🧍 Solo' : '👥 With Friends'} + +
+ +

{entry.title}

+ +
+
+ Date + +
+
+
+ Duration + {entry.days} {entry.days === 1 ? 'day' : 'days'} +
+
+ +
+

{entry.memo}

+
+ +
+ +
+ Soundtrack + {entry.song.title} + {entry.song.artist} +
+
+
+
+ + diff --git a/src/lib/TimelineView.svelte b/src/lib/TimelineView.svelte new file mode 100644 index 0000000..25a2e6d --- /dev/null +++ b/src/lib/TimelineView.svelte @@ -0,0 +1,349 @@ + + +{#if selected} + (selected = null)} /> +{:else} +
+ +
+
+

Travel Journal

+

My Journey

+
+
+ + +
+
+ + {#if sortedEntries.length === 0} +

No journal entries yet.

+ {:else} +
    + {#each sortedEntries as entry (entry.id)} + {@const idx = photoIdx[entry.id] ?? 0} +
  1. + +
    +
    + + · + {entry.location.city}, {entry.location.country} + · + {entry.days} {entry.days === 1 ? 'day' : 'days'} +
    +
    (selected = entry)} + onkeydown={(e) => e.key === 'Enter' && (selected = entry)}> + + {#if entry.photos.length > 0} + + {/if} + +
    +

    {entry.title}

    + {#if entry.memo} +

    {entry.memo}

    + {/if} +
    + + + + + + {entry.song.title} + · + {entry.song.artist} + + {entry.tripType === 'solo' ? 'Solo' : 'With Friends'} + +
    +
    +
    +
    +
  2. + {/each} +
+ {/if} + +
+ {sortedEntries.length} {sortedEntries.length === 1 ? 'entry' : 'entries'} +
+
+{/if} + + diff --git a/src/lib/stores/journalStore.js b/src/lib/stores/journalStore.js new file mode 100644 index 0000000..1ef37c9 --- /dev/null +++ b/src/lib/stores/journalStore.js @@ -0,0 +1,118 @@ +import { writable } from 'svelte/store'; + +/** + * @typedef {{ + * id: string, + * title: string, + * date: string, + * location: { country: string, city: string }, + * photos: string[], + * song: { title: string, artist: string }, + * tripType: 'solo' | 'friends', + * days: number, + * memo: string + * }} JournalEntry + */ + +/** @type {JournalEntry[]} */ +const mockEntries = [ + { + id: '1', + title: 'First Day in Tokyo', + date: '2024-03-15', + location: { country: 'Japan', city: 'Tokyo' }, + photos: [ + 'https://images.unsplash.com/photo-1540959733332-eab4deabeeaf?w=600&q=80', + 'https://images.unsplash.com/photo-1513407030348-c983a97b98d8?w=600&q=80', + 'https://images.unsplash.com/photo-1490806843957-31f4c9a91c65?w=600&q=80', + ], + song: { title: 'Tokyo', artist: 'Imagine Dragons' }, + tripType: 'solo', + days: 5, + memo: 'Got completely lost in Shinjuku — stumbled into a tiny ramen shop with no English menu. The chashu just melted. Worth every wrong turn.', + }, + { + id: '2', + title: 'Arashiyama Bamboo Grove', + date: '2024-03-18', + location: { country: 'Japan', city: 'Kyoto' }, + photos: [ + 'https://images.unsplash.com/photo-1528360983277-13d401cdc186?w=600&q=80', + 'https://images.unsplash.com/photo-1545569341-9eb8b30979d9?w=600&q=80', + ], + song: { title: 'Spirited Away Suite', artist: 'Joe Hisaishi' }, + tripType: 'friends', + days: 3, + memo: 'Arrived at 6am before the crowds. Just me and the wind moving through the bamboo. One of those moments you keep coming back to.', + }, + { + id: '3', + title: 'Sunset on Montmartre', + date: '2024-06-02', + location: { country: 'France', city: 'Paris' }, + photos: [ + 'https://images.unsplash.com/photo-1502602898657-3e91760cbb34?w=600&q=80', + 'https://images.unsplash.com/photo-1499856871958-5b9627545d1a?w=600&q=80', + 'https://images.unsplash.com/photo-1511739001486-6bfe10ce785f?w=600&q=80', + ], + song: { title: 'La Vie en Rose', artist: 'Édith Piaf' }, + tripType: 'solo', + days: 7, + memo: 'Watched the whole city turn orange from the steps of Sacré-Cœur. A street musician was playing La Vie en Rose. Cliché, perfect.', + }, + { + id: '4', + title: 'Inside La Sagrada Família', + date: '2024-06-10', + location: { country: 'Spain', city: 'Barcelona' }, + photos: [ + 'https://images.unsplash.com/photo-1523531294919-4bcd7c65e216?w=600&q=80', + 'https://images.unsplash.com/photo-1583422409516-2895a77efded?w=600&q=80', + ], + song: { title: 'Spain', artist: 'Chick Corea' }, + tripType: 'friends', + days: 4, + memo: 'Nothing prepares you for the light inside. The stained glass turns the whole nave into a kaleidoscope. Gaudí was building a forest.', + }, + { + id: '5', + title: 'Central Park in Fall', + date: '2023-10-20', + location: { country: 'USA', city: 'New York' }, + photos: [ + 'https://images.unsplash.com/photo-1534430480872-3498386e7856?w=600&q=80', + 'https://images.unsplash.com/photo-1485871981521-5b1fd3805345?w=600&q=80', + 'https://images.unsplash.com/photo-1522083165195-3424ed129620?w=600&q=80', + ], + song: { title: 'New York, New York', artist: 'Frank Sinatra' }, + tripType: 'friends', + days: 6, + memo: 'Peak foliage. Joggers, picnics, a guy playing saxophone near Bethesda Fountain. Hard to believe a city this big wraps around this much quiet.', + }, + { + id: '6', + title: 'Wat Pho Reclining Buddha', + date: '2024-01-08', + location: { country: 'Thailand', city: 'Bangkok' }, + photos: [ + 'https://images.unsplash.com/photo-1563492065599-3520f775eeed?w=600&q=80', + 'https://images.unsplash.com/photo-1552465011-b4e21bf6e79a?w=600&q=80', + ], + song: { title: 'Elephant', artist: 'Tame Impala' }, + tripType: 'solo', + days: 2, + memo: 'Stood in front of the 45m golden Buddha for a long time. The mother-of-pearl inlay on the soles of the feet is impossibly detailed.', + }, +]; + +export const journals = writable(mockEntries); + +/** @param {Omit} entry */ +export function addJournal(entry) { + journals.update((entries) => [...entries, { ...entry, id: crypto.randomUUID() }]); +} + +/** @param {string} id */ +export function removeJournal(id) { + journals.update((entries) => entries.filter((e) => e.id !== id)); +}