From aadc80b7a80f80e3c3511f8663c38a1dfc3ef4cf Mon Sep 17 00:00:00 2001 From: Haeri Kim Date: Sun, 14 Jun 2026 10:24:45 +0900 Subject: [PATCH] added firebase & changed main tab color, uyear stand out --- .claude/launch.json | 1 + .env | 6 + src/App.svelte | 5 +- src/app.css | 2 +- src/lib/layout/Layout.svelte | 11 +- src/lib/layout/TopBar.svelte | 6 +- src/lib/timeline/JournalDetail.svelte | 359 ++++++++++++------------ src/lib/timeline/JournalSummary.svelte | 305 ++++++++++---------- src/lib/timeline/TimelineCard.svelte | 2 +- src/lib/timeline/TimelineToolbar.svelte | 26 +- src/lib/timeline/TimelineView.svelte | 78 ++++- 11 files changed, 409 insertions(+), 392 deletions(-) create mode 100644 .env diff --git a/.claude/launch.json b/.claude/launch.json index f3c9817..974415a 100644 --- a/.claude/launch.json +++ b/.claude/launch.json @@ -3,6 +3,7 @@ "configurations": [ { "name": "Map-Jurnal", + "cwd": "/Users/haerikim/Desktop/Map-Jurnal", "runtimeExecutable": "npm", "runtimeArgs": ["run", "dev"], "port": 5173, diff --git a/.env b/.env new file mode 100644 index 0000000..2deacb9 --- /dev/null +++ b/.env @@ -0,0 +1,6 @@ +VITE_FIREBASE_API_KEY=AIzaSyC_hZf9TpIIb4H7y7umUeYtFKD-guN_iR0 +VITE_FIREBASE_AUTH_DOMAIN=map-jurnal.firebaseapp.com +VITE_FIREBASE_PROJECT_ID=map-jurnal +VITE_FIREBASE_STORAGE_BUCKET=map-jurnal.firebasestorage.app +VITE_FIREBASE_MESSAGING_SENDER_ID=922587077950 +VITE_FIREBASE_APP_ID=1:922587077950:web:9f140f84468e306152606f diff --git a/src/App.svelte b/src/App.svelte index 35ecae6..df020c8 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -5,9 +5,10 @@ import TimelineView from './lib/timeline/TimelineView.svelte'; let screen = $state('worldmap'); + let inDetail = $state(false); - (screen = s)}> + (screen = s)} hideTopBar={inDetail}> {#if screen === 'worldmap'}
@@ -16,7 +17,7 @@
{:else} - + (inDetail = v)} /> {/if} diff --git a/src/app.css b/src/app.css index 3af86af..72f41fe 100644 --- a/src/app.css +++ b/src/app.css @@ -1,4 +1,4 @@ -@import url('https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,200;12..96,300;12..96,400&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,300;12..96,400;12..96,500&display=swap'); /* ── Color tokens ─────────────────────────────────────────── */ :root { diff --git a/src/lib/layout/Layout.svelte b/src/lib/layout/Layout.svelte index ecff737..ea23cf4 100644 --- a/src/lib/layout/Layout.svelte +++ b/src/lib/layout/Layout.svelte @@ -2,11 +2,13 @@ import TopBar from './TopBar.svelte'; import Footer from './Footer.svelte'; - let { screen, onNavigate, children } = $props(); + let { screen, onNavigate, hideTopBar = false, children } = $props(); -
- +
+ {#if !hideTopBar} + + {/if}
{@render children()}
@@ -21,6 +23,9 @@ grid-template-rows: auto 1fr auto; overflow: hidden; } + .layout.no-topbar { + grid-template-rows: 1fr auto; + } .main { overflow: hidden; diff --git a/src/lib/layout/TopBar.svelte b/src/lib/layout/TopBar.svelte index 20dc095..fd0124b 100644 --- a/src/lib/layout/TopBar.svelte +++ b/src/lib/layout/TopBar.svelte @@ -58,8 +58,8 @@ } .nav-btn:hover { color: var(--text-h); } .nav-btn.active { - background: var(--bg); - color: var(--text-h); - box-shadow: 0 1px 4px rgba(0,0,0,0.08); + background: #7c3aed; + color: #fff; + box-shadow: 0 1px 4px rgba(124,58,237,0.25); } diff --git a/src/lib/timeline/JournalDetail.svelte b/src/lib/timeline/JournalDetail.svelte index fe43a0f..cf28b8e 100644 --- a/src/lib/timeline/JournalDetail.svelte +++ b/src/lib/timeline/JournalDetail.svelte @@ -35,149 +35,214 @@
- -
- -
- {flagEmoji(entry.location.country)} -
-

{entry.location.city}

-

{entry.location.country}

+ +
+
+ + +
+ + {flagEmoji(entry.location.country)} +
+ {entry.location.city} + {entry.location.country}
-
- {#if entry.photos.length === 0} -
No photos
- {:else} -
- {#each entry.photos as photo, i} -
1}> - lightboxSrc = photo} - onerror={(e) => e.currentTarget.parentElement.classList.add('cell-broken')} /> +
+ + +
+
+ + +
+ + +
+
+ {#if entry.photos.length === 0} +
No photos
+ {:else} +
+ {#each entry.photos as photo, i} +
1}> + lightboxSrc = photo} + onerror={(e) => e.currentTarget.parentElement.classList.add('cell-broken')} /> +
+ {/each}
- {/each} + {/if}
- {/if}
-
- -
-
+ +
+
+
+
+

When did you go?

+

{formatDate(entry.date)}

+
-
+
+

How long did you stay?

+

{entry.days} {entry.days === 1 ? 'day' : 'days'}

+
-
-

When did you go?

-

{formatDate(entry.date)}

-
+
+

Who did you go with?

+

+ {#if entry.tripType === 'solo'} + Just me — solo trip + {:else} + With friends + {/if} +

+
-
-

How long did you stay?

-

{entry.days} {entry.days === 1 ? 'day' : 'days'}

-
+
+

How was it?

+

{entry.memo}

+
-
-

Who did you go with?

-

- {#if entry.tripType === 'solo'} - Just me — solo trip - {:else} - With friends - {/if} -

-
- -
-

How was it?

-

{entry.memo}

-
- -
-

Trip soundtrack

-
-
- - - - - -
-
-

{entry.song.title}

-

{entry.song.artist}

+
+

Trip soundtrack

+
+
+ + + + + +
+
+

{entry.song.title}

+

{entry.song.artist}

+
-
+
-
- -
- -
-
diff --git a/src/lib/timeline/JournalSummary.svelte b/src/lib/timeline/JournalSummary.svelte index de0de9d..959e638 100644 --- a/src/lib/timeline/JournalSummary.svelte +++ b/src/lib/timeline/JournalSummary.svelte @@ -9,207 +9,190 @@ const countries = [...new Set(entries.map(e => e.location.country))]; const cities = [...new Set(entries.map(e => e.location.city))]; - const countryCounts = {}; - for (const e of entries) countryCounts[e.location.country] = (countryCounts[e.location.country] ?? 0) + 1; - const topCountry = Object.entries(countryCounts).sort((a, b) => b[1] - a[1])[0]; - - const soloCount = entries.filter(e => e.tripType === 'solo').length; - const soloPct = Math.round(soloCount / entries.length * 100); - - const years = entries.map(e => new Date(e.date).getFullYear()); - const minYear = Math.min(...years); - const maxYear = Math.max(...years); + const years = entries.map(e => new Date(e.date).getFullYear()); + const minYear = Math.min(...years); + const maxYear = Math.max(...years); const yearRange = minYear === maxYear ? `${minYear}` : `${minYear} – ${maxYear}`; - const latest = [...entries].sort((a, b) => b.date.localeCompare(a.date))[0]; - - return { totalDays, countries, cities, topCountry, soloCount, soloPct, yearRange, latest, tripCount: entries.length }; + return { totalDays, countries, cities, yearRange, tripCount: entries.length }; }); {#if stats} -
+
+ -

My Journey

-

{stats.yearRange}

+
+ +
+
+ + + + + + + + TRAVEL JOURNAL +
+
+

PASSPORT

+

{stats.yearRange}

+
+
-
+
- -
-
- {stats.countries.length} - Countries -
-
- {stats.cities.length} - Cities -
-
- {stats.totalDays} - Days abroad -
-
- {stats.tripCount} - Trips + +
+
+ TRIPS + {stats.tripCount} +
+
+ COUNTRIES + {stats.countries.length} +
+
+ DAYS + {stats.totalDays} +
-
- - -
- Most visited - {stats.topCountry[0]} - {stats.topCountry[1]} {stats.topCountry[1] === 1 ? 'trip' : 'trips'} + +
+ P<JNL{String(stats.tripCount).padStart(2,'0')}<<<<<<<<<<<<<<<<<<<<<<<<<<< + {stats.yearRange.replace(' – ','').replace(/\s/g,'')}{'<'.repeat(12)}{String(stats.totalDays).padStart(4,'0')}
- - -
- Latest trip - {stats.latest.location.city} - {stats.latest.location.country} -
- -
- - -
- Trip style -
-
-
-
- {stats.soloPct}% Solo - {100 - stats.soloPct}% Friends -
-
-
{/if} diff --git a/src/lib/timeline/TimelineCard.svelte b/src/lib/timeline/TimelineCard.svelte index ad4f8da..b649034 100644 --- a/src/lib/timeline/TimelineCard.svelte +++ b/src/lib/timeline/TimelineCard.svelte @@ -126,7 +126,7 @@ display: flex; gap: 14px; align-items: flex-start; - padding-bottom: 28px; + padding-bottom: 48px; position: relative; } .v-item:last-child { padding-bottom: 0; } diff --git a/src/lib/timeline/TimelineToolbar.svelte b/src/lib/timeline/TimelineToolbar.svelte index 507b12f..f930098 100644 --- a/src/lib/timeline/TimelineToolbar.svelte +++ b/src/lib/timeline/TimelineToolbar.svelte @@ -9,34 +9,12 @@ let { sortKey, onSort } = $props(); -
-

My Journey

-
- -
-
+