diff --git a/src/lib/shared/SearchInput.svelte b/src/lib/shared/SearchInput.svelte
new file mode 100644
index 0000000..bb8e0c7
--- /dev/null
+++ b/src/lib/shared/SearchInput.svelte
@@ -0,0 +1,127 @@
+
+
+
+
open = true}
+ onblur={onBlur}
+ />
+ {#if open && filtered.length > 0}
+
+ {#each filtered as opt, i}
+ - select(opt)}
+ >{opt}
+ {/each}
+
+ {/if}
+
+
+
diff --git a/src/lib/shared/countries.js b/src/lib/shared/countries.js
new file mode 100644
index 0000000..a6401c4
--- /dev/null
+++ b/src/lib/shared/countries.js
@@ -0,0 +1,25 @@
+export const countryCodeMap = {
+ 'Argentina': 'AR', 'Australia': 'AU', 'Austria': 'AT',
+ 'Belgium': 'BE', 'Brazil': 'BR',
+ 'Canada': 'CA', 'Chile': 'CL', 'China': 'CN', 'Croatia': 'HR',
+ 'Czech Republic': 'CZ', 'Denmark': 'DK', 'Egypt': 'EG',
+ 'Finland': 'FI', 'France': 'FR', 'Germany': 'DE', 'Greece': 'GR',
+ 'Hungary': 'HU', 'India': 'IN', 'Indonesia': 'ID', 'Italy': 'IT',
+ 'Japan': 'JP', 'Kenya': 'KE',
+ 'Malaysia': 'MY', 'Mexico': 'MX', 'Morocco': 'MA',
+ 'Netherlands': 'NL', 'New Zealand': 'NZ', 'Norway': 'NO',
+ 'Peru': 'PE', 'Poland': 'PL', 'Portugal': 'PT',
+ 'Singapore': 'SG', 'South Africa': 'ZA', 'South Korea': 'KR',
+ 'Spain': 'ES', 'Sweden': 'SE', 'Switzerland': 'CH',
+ 'Taiwan': 'TW', 'Thailand': 'TH', 'Turkey': 'TR',
+ 'UK': 'GB', 'USA': 'US', 'Vietnam': 'VN',
+};
+
+export const countryNames = Object.keys(countryCodeMap).sort();
+
+/** @param {string} country */
+export function flagEmoji(country) {
+ const code = countryCodeMap[country];
+ if (!code) return '';
+ return [...code].map(c => String.fromCodePoint(0x1F1E6 - 65 + c.charCodeAt(0))).join('');
+}
diff --git a/src/lib/stores/journalStore.js b/src/lib/stores/journalStore.js
index 1ef37c9..fe2c673 100644
--- a/src/lib/stores/journalStore.js
+++ b/src/lib/stores/journalStore.js
@@ -116,3 +116,8 @@ export function addJournal(entry) {
export function removeJournal(id) {
journals.update((entries) => entries.filter((e) => e.id !== id));
}
+
+/** @param {JournalEntry} updated */
+export function updateJournal(updated) {
+ journals.update((entries) => entries.map((e) => e.id === updated.id ? updated : e));
+}
diff --git a/src/lib/timeline/DeleteConfirm.svelte b/src/lib/timeline/DeleteConfirm.svelte
new file mode 100644
index 0000000..b602869
--- /dev/null
+++ b/src/lib/timeline/DeleteConfirm.svelte
@@ -0,0 +1,88 @@
+
+
+
+
+
Delete entry?
+
+ {entry.location.city}, {entry.location.country} — {entry.date.slice(0, 4)} will be permanently removed.
+
+
+
+
+
+
+
+
+
diff --git a/src/lib/timeline/EditForm.svelte b/src/lib/timeline/EditForm.svelte
new file mode 100644
index 0000000..cd1f52f
--- /dev/null
+++ b/src/lib/timeline/EditForm.svelte
@@ -0,0 +1,268 @@
+
+
+
+
+
+
+ Edit
+
+
+
+
+
+
+
+
+
diff --git a/src/lib/timeline/JournalDetail.svelte b/src/lib/timeline/JournalDetail.svelte
index cf28b8e..6508741 100644
--- a/src/lib/timeline/JournalDetail.svelte
+++ b/src/lib/timeline/JournalDetail.svelte
@@ -1,19 +1,16 @@
+{#if showDeleteConfirm}
+ showDeleteConfirm = false} />
+{/if}
+
{#if lightboxSrc}
lightboxSrc = null} role="button" tabindex="0"
@@ -55,14 +56,14 @@
-