Files
mono/events/sx/day.sx
giles 51ebf347ba
Some checks failed
Build and Deploy / build-and-deploy (push) Failing after 2m33s
Move events/market/blog composition from Python to .sx defcomps (Phase 9)
Continues the pattern of eliminating Python sx_call tree-building in favour
of data-driven .sx defcomps. POST/PUT/DELETE routes now pass plain data
(dicts, lists, scalars) and let .sx handle iteration, conditionals, and
layout via map/let/when/if. Single response components wrap OOB swaps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 08:17:09 +00:00

124 lines
5.4 KiB
Plaintext

;; Events day components
(defcomp ~events-day-entry-link (&key href name time-str)
(a :href href :class "flex items-center gap-2 px-3 py-2 hover:bg-stone-100 rounded transition text-sm border sm:whitespace-nowrap sm:flex-shrink-0"
(div :class "flex-1 min-w-0"
(div :class "font-medium truncate" name)
(div :class "text-xs text-stone-600 truncate" time-str))))
(defcomp ~events-day-entries-nav (&key inner)
(div :class "flex flex-col sm:flex-row sm:items-center gap-2 border-r border-stone-200 mr-2 sm:max-w-2xl"
:id "day-entries-nav-wrapper"
(div :class "flex overflow-x-auto gap-1 scrollbar-thin"
inner)))
(defcomp ~events-day-table (&key list-container rows pre-action add-url)
(section :id "day-entries" :class list-container
(table :class "w-full text-sm border table-fixed"
(thead :class "bg-stone-100"
(tr
(th :class "p-2 text-left w-2/6" "Name")
(th :class "text-left p-2 w-1/6" "Slot/Time")
(th :class "text-left p-2 w-1/6" "State")
(th :class "text-left p-2 w-1/6" "Cost")
(th :class "text-left p-2 w-1/6" "Tickets")
(th :class "text-left p-2 w-1/6" "Actions")))
(tbody rows))
(div :id "entry-add-container" :class "mt-4"
(button :type "button" :class pre-action
:sx-get add-url :sx-target "#entry-add-container" :sx-swap "innerHTML"
"+ Add entry"))))
(defcomp ~events-day-empty-row ()
(tr (td :colspan "6" :class "p-3 text-stone-500" "No entries yet.")))
(defcomp ~events-day-row-name (&key href pill-cls name)
(td :class "p-2 align-top w-2/6" (div :class "font-medium"
(a :href href :class pill-cls :sx-get href :sx-target "#main-panel" :sx-select "#main-panel"
:sx-swap "outerHTML" :sx-push-url "true" name))))
(defcomp ~events-day-row-slot (&key href pill-cls slot-name time-str)
(td :class "p-2 align-top w-1/6" (div :class "text-xs font-medium"
(a :href href :class pill-cls :sx-get href :sx-target "#main-panel" :sx-select "#main-panel"
:sx-swap "outerHTML" :sx-push-url "true" slot-name)
(span :class "text-stone-600 font-normal" time-str))))
(defcomp ~events-day-row-time (&key start end)
(td :class "p-2 align-top w-1/6" (div :class "text-xs text-stone-600" (str start end))))
(defcomp ~events-day-row-state (&key state-id badge)
(td :class "p-2 align-top w-1/6" (div :id state-id badge)))
(defcomp ~events-day-row-cost (&key cost-str)
(td :class "p-2 align-top w-1/6" (span :class "font-medium text-green-600" cost-str)))
(defcomp ~events-day-row-tickets (&key price-str count-str)
(td :class "p-2 align-top w-1/6" (div :class "text-xs space-y-1"
(div :class "font-medium text-green-600" price-str)
(div :class "text-stone-600" count-str))))
(defcomp ~events-day-row-no-tickets ()
(td :class "p-2 align-top w-1/6" (span :class "text-xs text-stone-400" "No tickets")))
(defcomp ~events-day-row-actions ()
(td :class "p-2 align-top w-1/6"))
(defcomp ~events-day-row (&key tr-cls name slot state cost tickets actions)
(tr :class tr-cls name slot state cost tickets actions))
(defcomp ~events-day-admin-panel ()
(div :class "p-4 text-sm text-stone-500" "Admin options"))
(defcomp ~events-day-entries-nav-oob-empty ()
(div :id "day-entries-nav-wrapper" :sx-swap-oob "true"))
(defcomp ~events-day-entries-nav-oob (&key items)
(div :class "flex flex-col sm:flex-row sm:items-center gap-2 border-r border-stone-200 mr-2 sm:max-w-2xl"
:id "day-entries-nav-wrapper" :sx-swap-oob "true"
(div :class "flex overflow-x-auto gap-1 scrollbar-thin" items)))
(defcomp ~events-day-nav-entry (&key href nav-btn name time-str)
(a :href href :class nav-btn
(div :class "flex-1 min-w-0"
(div :class "font-medium truncate" name)
(div :class "text-xs text-stone-600 truncate" time-str))))
;; Day table from data — all row iteration in sx
(defcomp ~events-day-table-from-data (&key list-container pre-action add-url tr-cls pill-cls rows)
(~events-day-table
:list-container list-container
:rows (if (empty? (or rows (list)))
(~events-day-empty-row)
(<> (map (lambda (r)
(~events-day-row
:tr-cls tr-cls
:name (~events-day-row-name
:href (get r "href") :pill-cls pill-cls :name (get r "name"))
:slot (if (get r "slot-name")
(~events-day-row-slot
:href (get r "slot-href") :pill-cls pill-cls
:slot-name (get r "slot-name") :time-str (get r "slot-time"))
(~events-day-row-time :start (get r "start") :end (get r "end")))
:state (~events-day-row-state
:state-id (get r "state-id")
:badge (~entry-state-badge :state (get r "state")))
:cost (~events-day-row-cost :cost-str (get r "cost-str"))
:tickets (if (get r "has-tickets")
(~events-day-row-tickets
:price-str (get r "price-str") :count-str (get r "count-str"))
(~events-day-row-no-tickets))
:actions (~events-day-row-actions)))
(or rows (list)))))
:pre-action pre-action :add-url add-url))
;; Day entries nav OOB from data
(defcomp ~events-day-entries-nav-oob-from-data (&key nav-btn entries)
(if (empty? (or entries (list)))
(~events-day-entries-nav-oob-empty)
(~events-day-entries-nav-oob
:items (<> (map (lambda (e)
(~events-day-nav-entry
:href (get e "href") :nav-btn nav-btn
:name (get e "name") :time-str (get e "time-str")))
entries)))))