// Top bar, trip menu, publish panel, theme tweaks.
const { useState, useEffect, useRef, useMemo } = React;
const STATUS_ORDER = ["featured", "used", "context", "hidden"];
const STATUS_LABEL = {
featured: "Featured",
used: "Used",
context: "Context",
hidden: "Hidden",
};
const STATUS_GLYPH = {
featured: "★",
used: "●",
context: "◌",
hidden: "⊘",
};
const KIND_LABEL = { photo: "IMG", voice: "VOX", video: "VID", audio: "AUD", text: "TXT" };
const toLocalISO = (dt) => {
const y = dt.getFullYear();
const m = String(dt.getMonth() + 1).padStart(2, "0");
const d = String(dt.getDate()).padStart(2, "0");
return `${y}-${m}-${d}`;
};
const addDays = (iso, n) => {
const [y, m, d] = iso.split("-").map(Number);
return toLocalISO(new Date(y, m - 1, d + n));
};
const humanDate = (iso) => {
const [y, m, d] = iso.split("-").map(Number);
const dt = new Date(y, m - 1, d);
return dt.toLocaleDateString("en", { weekday: "long", day: "numeric", month: "long" });
};
const kicker = (iso, trip) => {
const [y, m, d] = iso.split("-").map(Number);
const dt = new Date(y, m - 1, d);
const mon = dt.toLocaleDateString("en", { month: "short" }).toLowerCase();
return `${(trip.title || trip.slug).toLowerCase()} · ${d} ${mon} ${y}`;
};
// ---------- TopBar ----------
function TopBar({
trip, trips, date, status, dirty, wordCount, inPostCount, featuredCount, contextCount, hiddenCount,
publishedAt, isDraft, onToggleDraft, onDate, onSwitchTrip, onNewTrip, onPublish,
}) {
const [tripOpen, setTripOpen] = useState(false);
const [publishOpen, setPublishOpen] = useState(false);
const brandRef = useRef();
const pubRef = useRef();
useEffect(() => {
const close = (e) => {
if (brandRef.current && !brandRef.current.contains(e.target)) setTripOpen(false);
if (pubRef.current && !pubRef.current.contains(e.target)) setPublishOpen(false);
};
document.addEventListener("click", close);
return () => document.removeEventListener("click", close);
}, []);
const publishLabel = (() => {
if (status.kind === "saving") return "Saving…";
if (isDraft) return "Unpublish";
if (status.kind === "edited") return "Publish update";
if (status.kind === "published") return "Published";
return "Publish";
})();
const publishClass =
(dirty || isDraft) && status.kind !== "saving"
? "btn btn-primary update"
: "btn btn-primary";
// dt day-index in trip (visual hint, "Day NN / MM")
const tripDays = useMemo(() => {
if (!trip || !trip.created_at) return { n: null, total: null };
return { n: null, total: null };
}, [trip]);
return (
Pull from site will remove this day's files from git entirely.
Local edits and media stay intact — toggle draft off and publish
to push it back out.
This rewrites the public day to match your current draft.
Unused and hidden items drop from the record.
Keep {humanDate(date)} as a private draft.
Publish update to {humanDate(date)}?