;; Shared auth components — login flow, check email, header rows ;; Used by account, orders, cart, and federation services. ;; --------------------------------------------------------------------------- ;; Auth / orders header rows — DRY extraction from per-service Python ;; --------------------------------------------------------------------------- ;; Auth section nav items (newsletters link + account_nav slot) (defcomp ~shared:auth/nav-items (&key (account-url :as string?) (select-colours :as string?) account-nav) (<> (~shared:layout/nav-link :href (str (or account-url "") "/newsletters/") :label "newsletters" :select-colours (or select-colours "")) (when account-nav account-nav))) ;; Auth header row — wraps ~shared:layout/menu-row-sx for account section (defcomp ~shared:auth/header-row (&key (account-url :as string?) (select-colours :as string?) account-nav (oob :as boolean?)) (~shared:layout/menu-row-sx :id "auth-row" :level 1 :colour "sky" :link-href (str (or account-url "") "/") :link-label "account" :icon "fa-solid fa-user" :nav (~shared:auth/nav-items :account-url account-url :select-colours select-colours :account-nav account-nav) :child-id "auth-header-child" :oob oob)) ;; Auth header row without nav (for cart service) (defcomp ~shared:auth/header-row-simple (&key (account-url :as string?) (oob :as boolean?)) (~shared:layout/menu-row-sx :id "auth-row" :level 1 :colour "sky" :link-href (str (or account-url "") "/") :link-label "account" :icon "fa-solid fa-user" :child-id "auth-header-child" :oob oob)) ;; Auto-fetching auth header — uses IO primitives, no free variables needed. ;; Expands inline (defmacro) so IO calls resolve in _aser mode. (defmacro ~auth-header-row-auto (oob) (quasiquote (~shared:auth/header-row :account-url (app-url "account" "") :select-colours (select-colours) :account-nav (account-nav-ctx) :oob (unquote oob)))) (defmacro ~auth-header-row-simple-auto (oob) (quasiquote (~shared:auth/header-row-simple :account-url (app-url "account" "") :oob (unquote oob)))) ;; Auto-fetching auth nav items — for mobile menus (defmacro ~auth-nav-items-auto () (quasiquote (~shared:auth/nav-items :account-url (app-url "account" "") :select-colours (select-colours) :account-nav (account-nav-ctx)))) ;; Orders header row (defcomp ~shared:auth/orders-header-row (&key (list-url :as string)) (~shared:layout/menu-row-sx :id "orders-row" :level 2 :colour "sky" :link-href list-url :link-label "Orders" :icon "fa fa-gbp" :child-id "orders-header-child")) ;; --------------------------------------------------------------------------- ;; Auth forms — login flow, check email ;; --------------------------------------------------------------------------- (defcomp ~shared:auth/error-banner (&key (error :as string?)) (when error (div :class "bg-red-50 border border-red-200 text-red-700 p-3 rounded mb-4" error))) (defcomp ~shared:auth/login-form (&key error (action :as string) (csrf-token :as string) (email :as string?)) (div :class "py-8 max-w-md mx-auto" (h1 :class "text-2xl font-bold mb-6" "Sign in") error (form :method "post" :action action :class "space-y-4" (input :type "hidden" :name "csrf_token" :value csrf-token) (div (label :for "email" :class "block text-sm font-medium mb-1" "Email address") (input :type "email" :name "email" :id "email" :value email :required true :autofocus true :class "w-full border border-stone-300 rounded px-3 py-2 focus:outline-none focus:ring-2 focus:ring-stone-500")) (button :type "submit" :class "w-full bg-stone-800 text-white py-2 px-4 rounded hover:bg-stone-700 transition" "Send magic link")))) (defcomp ~shared:auth/check-email-error (&key (error :as string?)) (when error (div :class "bg-yellow-50 border border-yellow-200 text-yellow-700 p-3 rounded mt-4" error))) (defcomp ~shared:auth/check-email (&key (email :as string) error) (div :class "py-8 max-w-md mx-auto text-center" (h1 :class "text-2xl font-bold mb-4" "Check your email") (p :class "text-stone-600 mb-2" "We sent a sign-in link to " (strong email) ".") (p :class "text-stone-500 text-sm" "Click the link in the email to sign in. The link expires in 15 minutes.") error))