1import{useState,useEffect,useRef,useMemo}from"preact/hooks";import{dispatchStepEvent}from"onboarding-dispatch-event";import{html}from"htm/preact";import{useStorage}from"onboarding-use-storage";import{storeOnboardingData}from"onboarding-storage-utils";import{ONBOARDING_STORAGE_KEYS,ONBOARDING_EVENTS}from"onboarding-step-constants";export function App({sectionSettings:e,blockSettings:t,stepId:n,sectionId:r,namespace:o="onboarding"}){const i=useMemo((()=>{const e={"plan-good":[],"plan-better":[]};return t?.forEach((t=>{"cta"===t._type&&t.recommendations?.length>0&&t.recommendations.forEach((n=>{"tier"===n.field&&e[n.value]&&e[n.value].push(t._id)}))})),e}),[t]),[s]=useStorage(o,ONBOARDING_STORAGE_KEYS.STEP_DATA),[a]=useStorage(o,ONBOARDING_STORAGE_KEYS.CHECKOUT_CONTEXT_BASE),d=useRef(null),[l,c]=useState(!1),[u,p]=useState(null),[E]=useStorage(o,ONBOARDING_STORAGE_KEYS.CURRENT_STEP_STATE),_=useMemo((()=>E?.currentStepId===n),[E,n]),m=useMemo((()=>{if(!a||!a.products||!s)return null;const e=s.find((e=>"tier"===e.field));if(!e)return null;const t=a.products.find((t=>`plan-${a.tiers[t.id]}`===e.value));return t&&t.subscription_collection&&t.subscription_collection.id?t.subscription_collection.id:null}),[a,s]),S=useMemo((()=>s&&Array.isArray(s)?{bagSize:s.find((e=>"bag_size"===e.field))?.value||null,grindType:s.find((e=>"grind_type"===e.field))?.value||null}:{}),[s]),f=e=>{storeOnboardingData(o,ONBOARDING_STORAGE_KEYS.RECOMMENDATIONS_STATE,e)};return useEffect((()=>{const s=JSON.stringify(S);if(d.current===s)return;if(!S.bagSize||!S.grindType||!m)return;d.current=s,c(!0),p(null),f("requested");const a=S.grindType,l={negative_rating_history:[],purchase_history:[],bag_size:S.bagSize,taste_collection_id:m,for_first_order:!0,remove_duplicate_roasters:!0,include_product_data:!1,grind_type:a};fetch((()=>{const e=t?.find((e=>"text"===e._type&&"endpoint"===e.key));if(!e?.value)throw new Error("Endpoint configuration is missing or empty");return e.value})(),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)}).then((e=>e.json())).then((t=>{c(!1),f("received");const s="premium"===t.tier?i["plan-better"]:i["plan-good"];dispatchStepEvent({eventType:ONBOARDING_EVENTS.CTA_SELECTED,selectedBlockIds:s,stepId:n,stepDataKey:ONBOARDING_STORAGE_KEYS.STEP_DATA,sectionId:r});const a=_,d=new CustomEvent(ONBOARDING_EVENTS.API_RESPONSE_RECEIVED,{detail:{storageKey:ONBOARDING_STORAGE_KEYS.RECOMMENDATIONS_RESULT,data:t,navigateToStep:a&&e.navigate_to_step||null,namespace:o}});document.dispatchEvent(d)})).catch((e=>{p(e),c(!1),f("errored")}))}),[S,m]),l&&(()=>{const e=t?.find((e=>"boolean"===e._type&&"loadingAnimation"===e.key));return!0===e?.value})()?html` 2 <div class="flex justify-center items-center py-20"> 3 <div class="flex flex-col items-center"> 4 <div 5 class="animate-spin rounded-full h-8 w-8 border-2 border-gray-300 border-t-black mb-3" 6 ></div> 7 <p class="text-gray-600 text-sm">Loading recommendations...</p> 8 </div> 9 </div> 10 `:u?html` 11 <div class="flex justify-center items-center py-20"> 12 <div class="flex flex-col items-center text-center"> 13 <p class="text-red-600 text-sm mb-2"> 14 Failed to load recommendations 15 </p> 16 <p class="text-gray-500 text-xs">Please try again later</p> 17 </div> 18 </div> 19 `:html``}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.