;; Events container-nav fragment handler ;; returns: sx ;; ;; Renders calendar entry nav items + calendar link nav items ;; for the scrollable navigation panel on blog post pages. ;; ;; Params (from request.args): ;; container_type — "page" (default) ;; container_id — int ;; post_slug — string ;; paginate_url — base URL for infinite scroll ;; page — current page (default 1) ;; exclude — comma-separated exclusion prefixes ;; current_calendar — currently selected calendar slug (defhandler container-nav (&key container_type container_id post_slug paginate_url page exclude current_calendar) (let ((ct (or container_type "page")) (cid (parse-int (or container_id "0"))) (slug (or post_slug "")) (purl (or paginate_url "")) (pg (parse-int (or page "1"))) (excl-raw (or exclude "")) (cur-cal (or current_calendar "")) (excludes (filter (fn (e) (not (empty? e))) (map trim (split excl-raw ",")))) (has-cal-excl (not (empty? (filter (fn (e) (starts-with? e "calendar")) excludes)))) (styles (or (jinja-global "styles") (dict))) (nav-class (or (get styles "nav_button") "")) (sel-colours (or (jinja-global "select_colours") ""))) ;; Only render if no calendar-* exclusion (when (not has-cal-excl) (let ((result (service "calendar" "associated-entries" :content-type ct :content-id cid :page pg)) (entries (first result)) (has-more (nth result 1)) (calendars (service "calendar" "calendars-for-container" :container-type ct :container-id cid))) (<> ;; Calendar entry nav items (map (fn (entry) (let ((entry-path (str "/" slug "/" (get entry "calendar_slug") "/" (get entry "start_at_year") "/" (get entry "start_at_month") "/" (get entry "start_at_day") "/entries/" (get entry "id") "/")) (date-str (str (format-date (get entry "start_at") "%b %d, %Y at %H:%M") (if (get entry "end_at") (str " – " (format-date (get entry "end_at") "%H:%M")) "")))) (~calendar-entry-nav :href (app-url "events" entry-path) :name (get entry "name") :date-str date-str :nav-class nav-class))) entries) ;; Infinite scroll sentinel (when (and has-more (not (empty? purl))) (~htmx-sentinel :id (str "entries-load-sentinel-" pg) :hx-get (str purl "?page=" (+ pg 1)) :hx-trigger "intersect once" :hx-swap "beforebegin" :class "flex-shrink-0 w-1")) ;; Calendar link nav items (map (fn (cal) (let ((href (app-url "events" (str "/" slug "/" (get cal "slug") "/"))) (is-selected (if (not (empty? cur-cal)) (= (get cal "slug") cur-cal) false))) (~calendar-link-nav :href href :name (get cal "name") :nav-class nav-class :is-selected is-selected :select-colours sel-colours))) calendars))))))