;; Blog settings panel components (features, markets, associated entries) (defcomp ~blog-features-form (&key features-url calendar-checked market-checked hs-trigger) (form :sx-put features-url :sx-target "#features-panel" :sx-swap "outerHTML" :sx-headers "{\"Content-Type\": \"application/json\"}" :sx-encoding "json" :class "space-y-3" (label :class "flex items-center gap-3 cursor-pointer" (input :type "checkbox" :name "calendar" :value "true" :checked calendar-checked :class "h-5 w-5 rounded border-stone-300 text-blue-600 focus:ring-blue-500" :_ hs-trigger) (span :class "text-sm text-stone-700" (i :class "fa fa-calendar text-blue-600 mr-1") " Calendar \u2014 enable event booking on this page")) (label :class "flex items-center gap-3 cursor-pointer" (input :type "checkbox" :name "market" :value "true" :checked market-checked :class "h-5 w-5 rounded border-stone-300 text-green-600 focus:ring-green-500" :_ hs-trigger) (span :class "text-sm text-stone-700" (i :class "fa fa-shopping-bag text-green-600 mr-1") " Market \u2014 enable product catalog on this page")))) (defcomp ~blog-sumup-connected () (span :class "ml-2 text-xs text-green-600" (i :class "fa fa-check-circle") " Connected")) (defcomp ~blog-sumup-key-hint () (p :class "text-xs text-stone-400 mt-0.5" "Key is set. Leave blank to keep current key.")) (defcomp ~blog-sumup-form (&key sumup-url merchant-code placeholder key-hint checkout-prefix connected) (div :class "mt-4 pt-4 border-t border-stone-100" (h4 :class "text-sm font-medium text-stone-700" (i :class "fa fa-credit-card text-purple-600 mr-1") " SumUp Payment") (p :class "text-xs text-stone-400 mt-1 mb-3" "Configure per-page SumUp credentials. Leave blank to use the global merchant account.") (form :sx-put sumup-url :sx-target "#features-panel" :sx-swap "outerHTML" :class "space-y-3" (div (label :class "block text-xs font-medium text-stone-600 mb-1" "Merchant Code") (input :type "text" :name "merchant_code" :value merchant-code :placeholder "e.g. ME4J6100" :class "w-full px-3 py-1.5 text-sm border border-stone-300 rounded focus:ring-purple-500 focus:border-purple-500")) (div (label :class "block text-xs font-medium text-stone-600 mb-1" "API Key") (input :type "password" :name "api_key" :value "" :placeholder placeholder :class "w-full px-3 py-1.5 text-sm border border-stone-300 rounded focus:ring-purple-500 focus:border-purple-500") key-hint) (div (label :class "block text-xs font-medium text-stone-600 mb-1" "Checkout Reference Prefix") (input :type "text" :name "checkout_prefix" :value checkout-prefix :placeholder "e.g. ROSE-" :class "w-full px-3 py-1.5 text-sm border border-stone-300 rounded focus:ring-purple-500 focus:border-purple-500")) (button :type "submit" :class "px-4 py-1.5 text-sm font-medium text-white bg-purple-600 rounded hover:bg-purple-700 focus:ring-2 focus:ring-purple-500" "Save SumUp Settings") connected))) (defcomp ~blog-features-panel (&key form sumup) (div :id "features-panel" :class "space-y-4 p-4 bg-white rounded-lg border border-stone-200" (h3 :class "text-lg font-semibold text-stone-800" "Page Features") form sumup)) ;; Markets panel (defcomp ~blog-market-item (&key name slug delete-url confirm-text) (li :class "flex items-center justify-between p-3 bg-stone-50 rounded" (div (span :class "font-medium" name) (span :class "text-stone-400 text-sm ml-2" (str "/" slug "/"))) (button :sx-delete delete-url :sx-target "#markets-panel" :sx-swap "outerHTML" :sx-confirm confirm-text :class "text-red-600 hover:text-red-800 text-sm" "Delete"))) (defcomp ~blog-markets-list (&key items) (ul :class "space-y-2 mb-4" items)) (defcomp ~blog-markets-empty () (p :class "text-stone-500 mb-4 text-sm" "No markets yet.")) (defcomp ~blog-markets-panel (&key list create-url) (div :id "markets-panel" (h3 :class "text-lg font-semibold mb-3" "Markets") list (form :sx-post create-url :sx-target "#markets-panel" :sx-swap "outerHTML" :class "flex gap-2" (input :type "text" :name "name" :placeholder "Market name" :required "" :class "flex-1 border border-stone-300 rounded px-3 py-1.5 text-sm") (button :type "submit" :class "bg-stone-800 text-white px-4 py-1.5 rounded text-sm hover:bg-stone-700" "Create")))) ;; Associated entries (defcomp ~blog-entry-image (&key src title) (if src (img :src src :alt title :class "w-8 h-8 rounded-full object-cover flex-shrink-0") (div :class "w-8 h-8 rounded-full bg-stone-200 flex-shrink-0"))) (defcomp ~blog-associated-entry (&key confirm-text toggle-url hx-headers img name date-str) (button :type "button" :class "w-full text-left p-3 rounded border bg-green-50 border-green-300 transition hover:bg-green-100" :data-confirm "" :data-confirm-title "Remove entry?" :data-confirm-text confirm-text :data-confirm-icon "warning" :data-confirm-confirm-text "Yes, remove it" :data-confirm-cancel-text "Cancel" :data-confirm-event "confirmed" :sx-post toggle-url :sx-trigger "confirmed" :sx-target "#associated-entries-list" :sx-swap "outerHTML" :sx-headers hx-headers :_ "on htmx:afterRequest trigger entryToggled on body" (div :class "flex items-center justify-between gap-3" img (div :class "flex-1" (div :class "font-medium text-sm" name) (div :class "text-xs text-stone-600 mt-1" date-str)) (i :class "fa fa-times-circle text-green-600 text-lg flex-shrink-0")))) (defcomp ~blog-associated-entries-content (&key items) (div :class "space-y-1" items)) (defcomp ~blog-associated-entries-empty () (div :class "text-sm text-stone-400" "No entries associated yet. Browse calendars below to add entries.")) (defcomp ~blog-associated-entries-panel (&key content) (div :id "associated-entries-list" :class "border rounded-lg p-4 bg-white" (h3 :class "text-lg font-semibold mb-4" "Associated Entries") content))