2026-06-17 01:15:43 +09:00
2026-06-17 01:15:43 +09:00
2026-06-01 15:43:40 +09:00
2026-06-16 22:31:17 +09:00
2026-06-17 01:15:43 +09:00
2026-06-16 23:18:20 +09:00
2026-06-17 00:31:56 +09:00
2026-06-17 01:04:45 +09:00
2026-06-09 15:56:01 +09:00
2026-06-17 00:31:56 +09:00
2026-06-17 00:31:56 +09:00
2026-06-17 00:32:23 +09:00
2026-06-16 23:18:20 +09:00
2026-06-01 15:43:40 +09:00
2026-06-15 19:50:13 +09:00

Map Journal

Author: [Your Name]
Student ID: [Your ID]
Email: [Your Email]

Repository: https://git.prototyping.id/20256426/Map-Jurnal.git
Video Demo: [YouTube URL]


Overview

Map Journal is a single-page web application for documenting and visualizing travel experiences. Users log trips by country, pinning cities, dates, transport modes, and photos, and then explore their journey on an interactive world map or a timeline view.

How It Works

  1. Sign in with a Google account.
  2. Select your home country — it is automatically marked as visited on the map.
  3. Add journal entries via a multi-step form:
    • Step 1 — Choose country, cities, arrival date, days stayed, trip type (solo/friends/family), and transport (flight/train/bus/car/ship/walk).
    • Step 2 — Upload photos (stored in Firebase Storage).
    • Step 3 — Answer three random reflective questions about the trip (e.g., "What was the most unexpected thing that happened?").
  4. Edit entries through the same form, pre-filled with existing data.
  5. View your journey on a D3-powered world map where visited countries are highlighted and animated flight paths connect entries in chronological order.
  6. Browse a timeline sorted by date, country, or recency.
  7. Share a generated summary card to show off your stats.

Code Organization

src/
├── App.svelte              Root component — mode switching & replay button
├── main.js                 Vite entry point
├── app.css                 Global CSS variables and resets
├── assets/                 14 static images (transport icons, profile, defaults)
│
└── lib/
    ├── firebase.js         Firebase init (auth, Firestore, Storage)
    │
    ├── auth/
    │   ├── LoginOverlay.svelte    Google sign-in dialog
    │   ├── CountryPicker.svelte   Home-country selection step
    │   └── userStore.svelte.js    Auth state & user profile store
    │
    ├── layout/
    │   ├── Layout.svelte          App shell (auth guard + sidebar)
    │   ├── TopBar.svelte          Segmented nav (Map / Journal)
    │   └── selection.svelte.js    Reactive set of visited countries
    │
    ├── stores/
    │   └── entriesStore.svelte.js  Firestore CRUD & reactive list
    │
    ├── shared/
    │   ├── cities.js              Country→cities map
    │   ├── countries.js           Country names, IDs, flag emoji helpers
    │   ├── SearchInput.svelte     Autocomplete text input
    │   └── types.js               JSDoc type definitions
    │
    ├── world-map/
    │   ├── WorldMap.svelte        D3 globe — visited countries, home marker, tooltips
    │   ├── JourneyView.svelte     Animated flight-path overlay + stats
    │   ├── StatsPanel.svelte      Trip statistics panel
    │   └── continents.js          Continent classification data
    │
    └── timeline/
        ├── detail/
        │   ├── NewEntryForm.svelte     Multi-step entry creation (3 steps)
        │   ├── EditForm.svelte         Multi-step entry editing (3 steps)
        │   ├── StepNavbar.svelte       Shared step-navigation top bar
        │   ├── TripBasicInfo.svelte    Step 1 form (country, cities, dates, transport)
        │   ├── PhotoEditor.svelte      Step 2 — upload & manage photos
        │   ├── JournalDetail.svelte    Full entry view with lightbox
        │   └── DeleteConfirm.svelte    Delete confirmation dialog
        └── view/
            ├── TimelineView.svelte     Sorted entry list with year groups
            ├── TimelineCard.svelte     Entry card thumbnail
            ├── ShareCard.svelte        Generated share image
            └── SharePreview.svelte     Share card preview modal

Architecture

Component tree (simplified):

App.svelte
└── Layout.svelte
    ├── LoginOverlay.svelte
    ├── TopBar.svelte
    ├── CountryPicker.svelte
    ├── WorldMap.svelte
    │   └── JourneyView.svelte
    │       └── StatsPanel.svelte
    └── TimelineView.svelte
        ├── TimelineCard.svelte
        ├── JournalDetail.svelte
        │   ├── DeleteConfirm.svelte
        │   └── EditForm.svelte
        │       ├── StepNavbar.svelte
        │       ├── TripBasicInfo.svelte
        │       └── PhotoEditor.svelte
        ├── NewEntryForm.svelte
        │   ├── StepNavbar.svelte
        │   ├── PhotoEditor.svelte
        │   └── ...
        ├── ShareCard.svelte
        └── SharePreview.svelte

Data Flow

Firebase Auth          ──→  userStore.svelte.js  ──→  Layout (auth guard)
Firebase Firestore     ──→  entriesStore.svelte.js ──→  Timeline, Map (via $state/$derived)
Firebase Storage       ──→  PhotoEditor.svelte (upload)
selection.svelte.js    ──→  visited set (derived from entries + home country)

Key Patterns

  • Svelte 5 runes$state, $derived, $effect, $bindable, $props replace the old Svelte store/reactivity model.
  • $bindable propsTripBasicInfo uses $bindable() for two-way binding with its parent form, keeping form state in the parent while delegating UI rendering.
  • Firebase listenersentriesStore uses onSnapshot for real-time Firestore sync; userStore uses onAuthStateChanged.
  • D3.jsWorldMap renders a GeoJSON world map with centered zoom via d3-geo; JourneyView animates SVG flight paths.
  • No framework router — the app uses a simple mode state variable ('map' | 'journal') in App.svelte to switch between views.

Features

Feature Details
Google sign-in Firebase Auth with GoogleAuthProvider
Interactive world map D3projected map with country highlighting, zoom, and pan
Animated journeys Flightpath arcs between entries, played sequentially
Multistep forms 3step wizard for both new and edit modes
Photo upload Firebase Storage with CORS support, error display
Random trip questions 10 curated prompts, 3 randomly chosen per entry
Share card Autogenerated trip summary image via html-to-image
Home country marker 16×16 icon placed at country centroid on map
Tooltips Country name shown on hover, offset 22px from cursor

Known Bugs & Limitations

  • Photo Editor — The .add-btn CSS class is unused (replaced by .add-cell); leftover from refactoring.
  • ShareCard — Several CSS classes (.stat-grid, .stat-box, .cont-section, etc.) are defined but unused in the template; they were intended for a statistics section that was not implemented.
  • Photo upload error — If Firebase Storage upload fails, the error is displayed but the photo grid does not automatically roll back the failed entry.
  • State_referenced_locally warningsEditForm.svelte initializes $state variables from $props() at declaration; this is intentional (onetime init on edit mode) but Svelte 5's analyzer emits warnings.
  • A11y warnings — Some form labels lack for/id associations (transport pills, triptype toggles); these are visualonly controls where the label wraps the input, which is functional but not strictly valid per WAIARIA.

Dependencies

Package Purpose
svelte ^5.55 UI framework (runes, snippets, $props)
firebase ^12 Auth, Firestore, Storage
d3 ^7 World map projection and SVG rendering
topojson-client Convert TopoJSON → GeoJSON for map data
world-atlas Country boundary data
html-to-image Generate share card PNG

Setup & Run

# Install
npm install

# Environment — create .env with your Firebase config:
#   VITE_FIREBASE_API_KEY=...
#   VITE_FIREBASE_AUTH_DOMAIN=...
#   VITE_FIREBASE_PROJECT_ID=...
#   VITE_FIREBASE_STORAGE_BUCKET=...
#   VITE_FIREBASE_MESSAGING_SENDER_ID=...
#   VITE_FIREBASE_APP_ID=...

# Dev server
npm run dev

# Production build
npm run build

Acknowledgments

  • D3.jsMike Bostock for the visualization library.
  • world-atlasTopojson world data by Mike Bostock.
  • Firebase — Google for the backend suite (Auth, Firestore, Storage).
  • SvelteSvelte team for the frontend framework.
  • html-to-imagetsayen for DOM-to-image capture.
  • Flag emoji — Country-to-flag mapping based on regional indicator symbols.
  • Cursor icon — Derived from the SVG airplane asset used in the app.

This project was developed as part of a software prototyping course.

Description
No description provided
Readme 6.1 MiB
Languages
Svelte 77.2%
JavaScript 21.2%
CSS 1.4%
HTML 0.2%