;; Events day components (defcomp ~day/entry-link (&key (href :as string) (name :as string) (time-str :as string)) (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 ~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 ~day/table (&key (list-container :as string) rows (pre-action :as string) (add-url :as string)) (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 ~day/empty-row () (tr (td :colspan "6" :class "p-3 text-stone-500" "No entries yet."))) (defcomp ~day/row-name (&key (href :as string) (pill-cls :as string) (name :as string)) (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 ~day/row-slot (&key (href :as string) (pill-cls :as string) (slot-name :as string) (time-str :as string)) (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 ~day/row-time (&key (start :as string) (end :as string)) (td :class "p-2 align-top w-1/6" (div :class "text-xs text-stone-600" (str start end)))) (defcomp ~day/row-state (&key (state-id :as string) badge) (td :class "p-2 align-top w-1/6" (div :id state-id badge))) (defcomp ~day/row-cost (&key (cost-str :as string)) (td :class "p-2 align-top w-1/6" (span :class "font-medium text-green-600" cost-str))) (defcomp ~day/row-tickets (&key (price-str :as string) (count-str :as string)) (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 ~day/row-no-tickets () (td :class "p-2 align-top w-1/6" (span :class "text-xs text-stone-400" "No tickets"))) (defcomp ~day/row-actions () (td :class "p-2 align-top w-1/6")) (defcomp ~day/row (&key (tr-cls :as string) name slot state cost tickets actions) (tr :class tr-cls name slot state cost tickets actions)) (defcomp ~day/admin-panel () (div :class "p-4 text-sm text-stone-500" "Admin options")) (defcomp ~day/entries-nav-oob-empty () (div :id "day-entries-nav-wrapper" :sx-swap-oob "true")) (defcomp ~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 ~day/nav-entry (&key (href :as string) (nav-btn :as string) (name :as string) (time-str :as string)) (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 ~day/table-from-data (&key (list-container :as string) (pre-action :as string) (add-url :as string) (tr-cls :as string) (pill-cls :as string) (rows :as list?)) (~day/table :list-container list-container :rows (if (empty? (or rows (list))) (~day/empty-row) (<> (map (lambda (r) (~day/row :tr-cls tr-cls :name (~day/row-name :href (get r "href") :pill-cls pill-cls :name (get r "name")) :slot (if (get r "slot-name") (~day/row-slot :href (get r "slot-href") :pill-cls pill-cls :slot-name (get r "slot-name") :time-str (get r "slot-time")) (~day/row-time :start (get r "start") :end (get r "end"))) :state (~day/row-state :state-id (get r "state-id") :badge (~entries/entry-state-badge :state (get r "state"))) :cost (~day/row-cost :cost-str (get r "cost-str")) :tickets (if (get r "has-tickets") (~day/row-tickets :price-str (get r "price-str") :count-str (get r "count-str")) (~day/row-no-tickets)) :actions (~day/row-actions))) (or rows (list))))) :pre-action pre-action :add-url add-url)) ;; Day entries nav OOB from data (defcomp ~day/entries-nav-oob-from-data (&key (nav-btn :as string) (entries :as list?)) (if (empty? (or entries (list))) (~day/entries-nav-oob-empty) (~day/entries-nav-oob :items (<> (map (lambda (e) (~day/nav-entry :href (get e "href") :nav-btn nav-btn :name (get e "name") :time-str (get e "time-str"))) entries)))))