(defcomp ~optimistic-demo/content (&key items server-time) (div :class "space-y-8" (div :class "border-b border-stone-200 pb-6" (h1 :class "text-2xl font-bold text-stone-900" "Optimistic Updates") (p :class "mt-2 text-stone-600" "This page tests Phase 7c optimistic data mutations. Items are updated " "instantly on the client, then confirmed or reverted when the server responds.")) (div :class "rounded-lg border border-stone-200 bg-white p-6 space-y-3" (h2 :class "text-lg font-semibold text-stone-800" "Current state") (dl :class "grid grid-cols-2 gap-2 text-sm" (dt :class "font-medium text-stone-600" "Server time") (dd :class "font-mono text-stone-900" server-time) (dt :class "font-medium text-stone-600" "Item count") (dd :class "text-stone-900" (str (len items))))) (div :class "space-y-3" (h2 :class "text-lg font-semibold text-stone-800" "Items") (div :id "optimistic-items" :class "space-y-2" (map (fn (item) (div :class "flex items-center justify-between rounded border border-stone-100 bg-white p-3" (div :class "flex items-center gap-3" (span :class "flex-none rounded-full bg-violet-100 text-violet-700 w-6 h-6 flex items-center justify-center text-xs font-bold" (str (get item "id"))) (span :class "text-stone-900" (get item "label"))) (span :class "text-xs px-2 py-0.5 rounded-full" :class (case (get item "status") "confirmed" "bg-green-100 text-green-700" "pending" "bg-amber-100 text-amber-700" "reverted" "bg-red-100 text-red-700" :else "bg-stone-100 text-stone-500") (get item "status")))) items)) (div :class "pt-2" (button :class "px-4 py-2 bg-violet-500 text-white rounded hover:bg-violet-600 text-sm" :sx-post "/sx/action/add-demo-item" :sx-target "#sx-content" :sx-vals "{\"label\": \"New item\"}" "Add item (optimistic)"))) (div :class "space-y-4" (h2 :class "text-lg font-semibold text-stone-800" "How it works") (div :class "space-y-2" (map-indexed (fn (i step) (div :class "flex items-start gap-3 rounded border border-stone-100 bg-white p-3" (span :class "flex-none rounded-full bg-stone-100 text-stone-700 w-6 h-6 flex items-center justify-center text-xs font-bold" (str (+ i 1))) (div (div :class "font-medium text-stone-900" (get step "label")) (div :class "text-sm text-stone-500" (get step "detail"))))) (list (dict :label "Predict" :detail "Client applies mutator function to cached data immediately") (dict :label "Snapshot" :detail "Pre-mutation data saved in _optimistic-snapshots for rollback") (dict :label "Re-render" :detail "Page content re-evaluated and swapped with predicted data") (dict :label "Submit" :detail "Mutation sent to server via POST /sx/action/") (dict :label "Confirm or revert" :detail "Server responds — cache updated with truth, or reverted to snapshot"))))) (div :class "rounded-lg border border-amber-200 bg-amber-50 p-4 text-sm space-y-2" (p :class "font-semibold text-amber-800" "How to verify") (ol :class "list-decimal list-inside text-amber-700 space-y-1" (li "Open the browser console (F12)") (li "Navigate to this page from another isomorphism page") (li "Click \"Add item\" — item appears instantly with \"pending\" status") (li "Watch console for " (code :class "bg-amber-100 px-1 rounded" "sx:optimistic confirmed")) (li "Item status changes to \"confirmed\" when server responds")))))