// views.jsx — Base Camp dashboard + Project detail // Depends on globals: TopoSVG, EVEREST_DATA const { useState, useRef, useEffect, useMemo } = React; // Static fields from seed data (user identity, date display, weather). // The three context panels (schedule, inbox, news) fetch their own live data. const { WEATHER, TODAY_STR, TODAY_SHORT, DAY_OF_EXPEDITION, USER } = window.EVEREST_DATA; // ─── Shared bits ───────────────────────────────────────────────────── function Eyebrow({ children }) { return
{children}
; } function EmptyState({ title, sub, action, large }) { return (
{title}
{sub}
{action &&
{action}
}
); } // ─── Topbar ────────────────────────────────────────────────────────── function Topbar({ onHome, view, onNav, onLogout, currentUser }) { const NAV = [ { id: "dashboard", label: "Base Camp" }, { id: "notes", label: "Notes" }, { id: "receipts", label: "Receipts" }, { id: "symphony", label: "Symphony" }, ]; return (
EVEREST.
{TODAY_SHORT} {WEATHER} {DAY_OF_EXPEDITION}
{currentUser ? (currentUser.name || currentUser.email).toUpperCase() : USER.name.toUpperCase()} {currentUser ? (currentUser.name || currentUser.email).slice(0, 2).toUpperCase() : USER.initials}
); } // ─── Pinned expedition card ────────────────────────────────────────── function PinnedExpeditionCard({ project, onOpen, onMarkWorked }) { return (
onOpen(project.id)}>
{project.status}
{project.elevation}
FT · ELEV
{project.coords} {project.codename.split('·')[0].trim()}
{project.codename}

{project.name}

{project.description}
Last ascended {project.last_worked}
Summit ETA {project.end_date || "Not set"}
Progress {Math.round(project.progress * 100)}%
); } // ─── Compact expedition row ────────────────────────────────────────── function ExpeditionRow({ project, onOpen }) { return (
onOpen(project.id)}>
{project.codename.split('·')[0].trim()}
{project.name} {project.description}
{project.last_worked}
{project.elevation} ft
); } // ─── Field notes ───────────────────────────────────────────────────── function FieldNotes({ notes, onAdd, onDelete }) { const [text, setText] = useState(""); const submit = () => { const t = text.trim(); if (!t) return; onAdd(t); setText(""); }; return ( <>