Component names now reflect filesystem location using / as path separator and : as namespace separator for shared components: ~sx-header → ~layouts/header ~layout-app-body → ~shared:layout/app-body ~blog-admin-dashboard → ~admin/dashboard 209 files, 4,941 replacements across all services. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
63 lines
2.9 KiB
Plaintext
63 lines
2.9 KiB
Plaintext
;; Newsletter management components
|
|
|
|
(defcomp ~newsletters/desc (&key (description :as string))
|
|
(when description
|
|
(p :class "text-xs text-stone-500 mt-0.5 truncate" description)))
|
|
|
|
(defcomp ~newsletters/toggle (&key (id :as string) (url :as string) (hdrs :as dict) (target :as string) (cls :as string) (checked :as string) (knob-cls :as string))
|
|
(div :id id :class "flex items-center"
|
|
(button :sx-post url :sx-headers hdrs :sx-target target :sx-swap "outerHTML"
|
|
:class cls :role "switch" :aria-checked checked
|
|
(span :class knob-cls))))
|
|
|
|
|
|
(defcomp ~newsletters/item (&key (name :as string) desc toggle)
|
|
(div :class "flex items-center justify-between py-4 first:pt-0 last:pb-0"
|
|
(div :class "min-w-0 flex-1"
|
|
(p :class "text-sm font-medium text-stone-800" name)
|
|
desc)
|
|
(div :class "ml-4 flex-shrink-0" toggle)))
|
|
|
|
(defcomp ~newsletters/list (&key items)
|
|
(div :class "divide-y divide-stone-100" items))
|
|
|
|
(defcomp ~newsletters/empty ()
|
|
(p :class "text-sm text-stone-500" "No newsletters available."))
|
|
|
|
(defcomp ~newsletters/panel (&key list)
|
|
(div :class "w-full max-w-3xl mx-auto px-4 py-6"
|
|
(div :class "bg-white/70 backdrop-blur rounded-2xl shadow border border-stone-200 p-6 sm:p-8 space-y-6"
|
|
(h1 :class "text-xl font-semibold tracking-tight" "Newsletters")
|
|
list)))
|
|
|
|
;; Assembled newsletters content — replaces Python _newsletters_panel_sx
|
|
;; Takes pre-fetched newsletter-list from page helper
|
|
(defcomp ~newsletters/content (&key (newsletter-list :as list) (account-url :as string?))
|
|
(let* ((csrf (csrf-token)))
|
|
(if (empty? newsletter-list)
|
|
(~newsletters/empty)
|
|
(~newsletters/panel
|
|
:list (~newsletters/list
|
|
:items (map (lambda (item)
|
|
(let* ((nl (get item "newsletter"))
|
|
(un (get item "un"))
|
|
(nid (get nl "id"))
|
|
(subscribed (get item "subscribed"))
|
|
(toggle-url (str (or account-url "") "/newsletter/" nid "/toggle/"))
|
|
(bg (if subscribed "bg-emerald-500" "bg-stone-300"))
|
|
(translate (if subscribed "translate-x-6" "translate-x-1"))
|
|
(checked (if subscribed "true" "false")))
|
|
(~newsletters/item
|
|
:name (get nl "name")
|
|
:desc (when (get nl "description")
|
|
(~newsletters/desc :description (get nl "description")))
|
|
:toggle (~newsletters/toggle
|
|
:id (str "nl-" nid)
|
|
:url toggle-url
|
|
:hdrs {:X-CSRFToken csrf}
|
|
:target (str "#nl-" nid)
|
|
:cls (str "relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-emerald-500 focus:ring-offset-2 " bg)
|
|
:checked checked
|
|
:knob-cls (str "inline-block h-4 w-4 rounded-full bg-white shadow transform transition-transform " translate)))))
|
|
newsletter-list))))))
|