feat: Firebase integration, 3-step new trip form, full country list, and UI polish

- Connect Firestore for journal entries and visited countries (real-time onSnapshot)
- Connect Firebase Storage for photo uploads
- Add NewEntryForm: 3-step flow (trip details → photos → reflection questions)
- Expand country list to full world-atlas dataset (~240 countries) matching the map
- Filter city suggestions by selected country in both NewEntryForm and EditForm
- Redesign StatsPanel as floating horizontal card with donut chart and progress bar
- Center timeline layout with responsive side margins
- Replace "entry" language with "trip" throughout (Add trip, Save trip, Delete trip)
- Remove footer from Layout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
haerikimmm
2026-06-15 19:15:31 +09:00
parent 40e75f30e8
commit dd7932ea4e
12 changed files with 884 additions and 544 deletions

View File

@@ -1,5 +1,5 @@
import { db } from '../firebase.js';
import { doc, onSnapshot, updateDoc, arrayUnion, arrayRemove } from 'firebase/firestore';
import { doc, onSnapshot, setDoc, updateDoc, arrayUnion, arrayRemove } from 'firebase/firestore';
let selected = $state(new Set());
let totalCountries = $state(0);
@@ -20,29 +20,39 @@ export function initSelectionListener(uid) {
});
}
const visitedRef = doc(db, 'visited', 'countries');
onSnapshot(visitedRef, (snap) => {
if (snap.exists()) {
selected = new Set(snap.data().ids ?? []);
}
});
function persist() {
setDoc(visitedRef, { ids: [...selected] });
}
export function toggle(id) {
if (!_uid) return;
const was = selected.has(id);
const next = new Set(selected);
if (was) {
next.delete(id);
} else {
next.add(id);
}
if (was) next.delete(id);
else next.add(id);
selected = next;
const userRef = doc(db, 'users', _uid);
if (was) {
updateDoc(userRef, { visitedCountries: arrayRemove(id) });
} else {
updateDoc(userRef, { visitedCountries: arrayUnion(id) });
persist();
if (_uid) {
const userRef = doc(db, 'users', _uid);
if (was) updateDoc(userRef, { visitedCountries: arrayRemove(id) });
else updateDoc(userRef, { visitedCountries: arrayUnion(id) });
}
}
export function clearAll() {
if (!_uid) return;
selected = new Set();
const userRef = doc(db, 'users', _uid);
updateDoc(userRef, { visitedCountries: [] });
persist();
if (_uid) {
const userRef = doc(db, 'users', _uid);
updateDoc(userRef, { visitedCountries: [] });
}
}
export function getSelected() {