1import{G as A}from"./main-creator-dpxee3ad.js";import{Ga as k,Ia as F,Ja as L}from"./main-creator-c1rk9aqk.js";import{ed as U}from"./main-creator-ksxphzr7.js";import{qd as w}from"./main-creator-kx8zrjk4.js";import{xe as x}from"./main-creator-hc75ac9z.js";import"./main-creator-tw5wk45r.js";import"./main-creator-9s14yt6h.js";import"./main-creator-tfqtntpa.js";import"./main-creator-tzcb6cj5.js";import"./main-creator-4gzeey0c.js";import"./main-creator-x88xb983.js";import{Ki as Y}from"./main-creator-9n9qs3hc.js";import{Zi as $}from"./main-creator-w1tv2h60.js";import"./main-creator-54g4r2mg.js";import{hj as V}from"./main-creator-pmw34qy3.js";import"./main-creator-v7qcfy0p.js";import"./main-creator-v5qyd74b.js";import"./main-creator-k74w1j6w.js";import{zj as W}from"./main-creator-hgv1jep8.js";import{Gj as h}from"./main-creator-kydzhv9p.js";class P extends A{offOpen=null;offClose=null;panelId="gifts";giftPurchasesData=null;isLoading=!1;connectedCallback(){if(super.connectedCallback(),!this.offOpen)this.offOpen=$.on("slideout:open",({panel:j})=>{if(j===this.panelId){let q=Y();if(U(q?.getTributeData()))return;this.open()}});if(!this.offClose)this.offClose=$.on("slideout:close",({panel:j}={})=>{if(!j||j===this.panelId)this.close()});$.on("goal:updated",()=>{if(this.giftPurchasesData){let j=this.querySelector("#slideout-panel > div.flex-1");if(j)j.innerHTML=this.renderContent(),this.setupSlideoutSpecificListeners()}}),$.on("tribute:updated",()=>{if(this.giftPurchasesData&&this.isOpen){let j=this.querySelector("#slideout-panel > div.flex-1");if(j)j.innerHTML=this.renderContent(),this.setupSlideoutSpecificListeners()}})}disconnectedCallback(){if(this.offOpen)this.offOpen(),this.offOpen=null;if(this.offClose)this.offClose(),this.offClose=null;super.disconnectedCallback()}getTributeUuid(){try{let j=Y();if(j){let q=j.getState();if(q.tributeId)return q.tributeId;return W.warn("GiftSlideout","Could not find tribute UUID in app state"),null}}catch(j){W.warn("GiftSlideout","Could not get tribute UUID from app state:",j)}return null}async open(){if(!this.giftPurchasesData&&!this.isLoading){this.isLoading=!0,super.open(),await this.loadGiftPurchases();let j=this.querySelector("#slideout-panel > div.flex-1");if(j)j.innerHTML=this.renderContent(),this.setupSlideoutSpecificListeners()}else super.open()}async loadGiftPurchases(){let j=this.getTributeUuid();if(!j){W.warn("GiftSlideout","No tribute UUID available"),this.giftPurchasesData=null,this.isLoading=!1;return}try{let q=await V.getGiftPurchases(j);if(q.success&&q.data){let z=q.data;this.giftPurchasesData={...z,giftcards_purchased_review_approved:z.giftcards_purchased_review_approved??void 0,giftcards_purchased:z.giftcards_purchased??void 0}}else W.error("GiftSlideout","Failed to load gift purchases:",q.error),this.giftPurchasesData=null}catch(q){W.error("GiftSlideout","Error loading gift purchases:",q),this.giftPurchasesData=null}finally{this.isLoading=!1}}getSlideoutTitle(){return"Gift Management"}getSlideoutWidth(){return"w-full md:w-1/2"}getGoalCountingGiftCards(){let j=this.giftPurchasesData?.giftcards_purchased||[];return k(j)}getCreatorListGiftCards(){let j=this.giftPurchasesData?.giftcards_purchased||[];return F(j)}shouldShowCompletedGiftTools(){let j=Y();if(!j.getTributeData()||!this.giftPurchasesData)return!1;let z=j.getCurrentView(),J=this.giftPurchasesData.tribute_checkout_paid,K=this.getGoalCountingGiftCards().length>0;return z==="completed"&&J===!0&&K}isTributeDeliversSharing(){return(Y()?.getTributeData()?.share_with||"nobody")!=="nobody"}renderContent(){if(this.isLoading)return` 2 <div class="flex items-center justify-center h-full min-h-[400px]"> 3 <div class="flex flex-col items-center justify-center gap-4"> 4 <div class="loading loading-spinner loading-lg ui-text-primary"></div> 5 <span class="ui-text-primary">Loading gift purchases...</span> 6 </div> 7 </div> 8 `;if(!this.giftPurchasesData)return` 9 <div class="space-y-4 p-6"> 10 <p class="text-sm opacity-70" style="color: var(--theme-text-color);"> 11 No gift purchases data available. 12 </p> 13 </div> 14 `;let j=this.getGoalCountingGiftCards(),q=this.getCreatorListGiftCards(),z=!this.giftPurchasesData.tribute_checkout_paid,J=this.shouldShowCompletedGiftTools(),K=this.isTributeDeliversSharing(
14),Q;try{let R=Y().getTributeData()?.metadata||{};Q=L(j,R)}catch(N){W.warn("GiftSlideout","Could not get tribute data for goal settings:",N),Q={totalAmount:j.reduce((R,M)=>{return R+parseFloat(String(M.amount||0))},0),totalGifts:j.length,goal:100,progressPercentage:0,goalEnabled:!0}}let{totalAmount:O,totalGifts:Z,goal:X,progressPercentage:I,goalEnabled:_}=Q,T=Math.max(X-O,0),E=_?`${I.toFixed(0)}% of $${X.toFixed(2)} goal`:"",S=_?`<progress class="progress progress-success w-full" value="${I}" max="100"></progress>`:"",y=_?` 15 <div class="flex items-baseline gap-2"> 16 <div class="text-xl font-semibold ui-text-primary" style="font-family: 'Montserrat', sans-serif;">$${T.toFixed(2)}</div> 17 <div class="text-sm font-normal ui-text-primary">to go</div> 18 </div> 19 `:"",H=q.length>0;return` 20 <div class="flex flex-col flex-1 space-y-6 mt-2"> 21 ${(J?K?this.renderTributeDeliversSharingSection():this.renderManualDeliverySection():"")||(z?this.renderCheckoutAlert():"")} 22 23 <!-- Fundraising Progress --> 24 <div class="space-y-2"> 25 <!-- Amount Raised --> 26 <div class="flex items-baseline justify-between gap-2"> 27 <div class="flex items-baseline gap-2"> 28 <div class="text-4xl font-semibold ui-text-primary" style="font-family: 'Montserrat', sans-serif;">$${O.toFixed(2)}</div> 29 <div class="text-base font-normal ui-text-primary">raised</div> 30 </div> 31 ${!_?` 32 <div class="flex items-center gap-2"> 33 <button id="edit-goal-btn" class="flex items-center gap-1.5 px-3 py-2 rounded transition-colors hover:opacity-80" 34 style="background-color: var(--theme-input-bg); color: var(--theme-text-color);"> 35 <span class="text-xs font-medium">Edit Goal</span> 36 <app-icon name="arrow-right" size="14" style="stroke: currentColor;"></app-icon> 37 </button> 38 </div> 39 `:""} 40 </div> 41 42 <!-- Progress Percentage and Goal --> 43 ${_?` 44 <div class="flex items-center justify-between"> 45 <div class="text-sm ui-text-secondary"> 46 ${E} 47 </div> 48 <div class="flex items-center gap-2 mb-2"> 49 <button id="edit-goal-btn" class="flex items-center gap-1.5 px-3 py-2 rounded transition-colors hover:opacity-80" 50 style="background-color: var(--theme-input-bg); color: var(--theme-text-color);"> 51 <span class="text-xs font-medium">Edit Goal</span> 52 <app-icon name="arrow-right" size="14" style="stroke: currentColor;"></app-icon> 53 </button> 54 </div> 55 </div> 56 `:""} 57 58 ${S} 59 60 <!-- Contributors and Amount to Go --> 61 <div class="flex items-center justify-between"> 62 <div class="text-sm ui-text-secondary"> 63 ${Z} ${Z===1?"contributor":"contributors"} 64 </div> 65 ${y} 66 </div> 67 </div> 68 69 <!-- Gift Cards List --> 70 <div id="gift-cards-container" class="${H?"space-y-3 mt-6":"flex-1 flex flex-col justify-center mt-6"}"> 71 ${H?this.renderGiftCards(q):this.renderEmptyState()} 72 </div> 73 74 ${this.renderMarketplaceCTA()} 75 </div> 76 `}renderManualDeliveryFormFields(){return` 77 <form id="manual-delivery-form"> 78 <div class="flex flex-col sm:flex-row gap-3 items-stretch"> 79 <div class="form-control flex-1"> 80 <label class="flex items-center px-3 py-2 rounded-lg w-full h-full" style="background-color: var(--ui-bg-subtle); border: 1px solid var(--ui-border-medium);"> 81 <input 82 type="email" 83 id="recipient-email-input" 84 name="recipient" 85 placeholder="Enter recipient's email" 86 required 87 class="flex-1 bg-transparent ui-text-primary border-none outline-none focus:outline-none focus:ring-0 focus:border-none" 88 style="border: none !important; outline: none !important; color: var(--ui-text-primary) !important;" 89 /> 90 </label> 91 </div> 92 93 <button type="submit" id="deliver-cards-btn" class="btn whitespace-nowrap h-auto" 94 style="background-color: var(--theme-primary-color); color: var(--btn-primary-text); border-color: var(--theme-primary-color);"> 95 Deliver Cards via Email 96 </button> 97 </div> 98 </form> 99 `}renderTributeDeliversSharingSection(){return` 100 <div class="alert alert-info alert-soft"> 101 <div class="flex w-full min-w-0 flex-col gap-3">
102 <span class="text-sm leading-relaxed">Because you selected for us to share the tribute with the recipient, we'll also send them instructions on how to redeem their gift.</span> 103 <details id="manual-send-details" class="group w-full border-t border-[var(--ui-border-medium)] pt-3"> 104 <summary class="cursor-pointer list-none text-sm leading-relaxed opacity-90 [&::-webkit-details-marker]:hidden"> 105 Need to send or resend gift redemption instructions? 106 <span class="font-medium underline decoration-1 underline-offset-2" style="color: var(--theme-primary-color);">Send manually</span> 107 </summary> 108 <div class="pt-4 space-y-4"> 109 <p class="text-sm leading-relaxed opacity-90"> 110 This will send an email with gift redemption instructions immediately. Make sure the recipient has already received their Tribute before sending. 111 </p> 112 ${this.renderManualDeliveryFormFields()} 113 </div> 114 </details> 115 <div id="manual-delivery-message" class="hidden w-full"></div> 116 </div> 117 </div> 118 `}renderManualDeliverySection(){return` 119 <div class="form-section p-6 rounded-lg" style="background-color: var(--ui-bg-subtle); border: 1px solid var(--ui-border-medium);"> 120 <p class="text-sm ui-text-secondary mb-4 leading-relaxed"> 121 When you're ready, send the recipient an email with instructions to redeem their gift. This sends immediately, so make sure they've already received their Tribute. 122 </p> 123 ${this.renderManualDeliveryFormFields()} 124 <div id="manual-delivery-message" class="hidden mt-4"></div> 125 </div> 126 `}renderCheckoutAlert(){return` 127 <div class="alert alert-info alert-soft"> 128 <span>Gift redemption instructions are sent to the recipient once the creator publishes their Tribute. Purchases may be briefly reviewed before delivery.</span> 129 </div> 130 `}renderMarketplaceCTA(){return` 131 <div class="mt-auto"> 132 <div class="pt-8 -mt-2"> 133 <div class="rounded-xl p-5 flex flex-col md:flex-row md:items-center gap-5" style="background-color: var(--theme-input-bg);"> 134 <div class="w-full md:w-auto md:max-w-[160px] md:flex-shrink-0"> 135 <img src="/static/images/homepage/snappy-montage.png" alt="Curated gift options" class="w-full h-auto rounded-lg" /> 136 <div class="flex items-center gap-1.5 ui-text-secondary mt-2"> 137 <span class="text-xs">Powered by</span> 138 <img src="/static/images/homepage/Snappy_Logo.png" alt="Snappy" class="h-4 w-auto brightness-0 invert" /> 139 </div> 140 </div> 141 <div class="flex-1 min-w-0"> 142 <h4 class="ui-text-primary font-semibold text-sm mb-2">How Gifting Works</h4> 143 <p class="text-sm ui-text-secondary leading-relaxed"> 144 Friends and family can contribute toward one group gift the recipient will love. Those contributions unlock our partner Snappy's curated catalog at that gift levelâthink redemption tier, not a wallet to spend down. The recipient picks one gift from the catalog; the amount isn't split across items. Catalog prices are redemption values (product plus fulfillment and shipping), not the same as everyday retail. 145 </p> 146 </div> 147 </div> 148 </div> 149 </div> 150 `}renderGiftCards(j){return j.map((q,z)=>this.renderGiftCard(q,z,j.length)).join("")}renderGiftCard(j,q,z){let J=String(j.purchaser_email||j.purchaser_name||""),K=typeof j.purchaser_avatar_url==="string"?j.purchaser_avatar_url:null,Q=this.formatDate(j.date_created),Z=String(j.purchaser_name??"").trim()||String(j.purchaser_email??"").trim()||"â",X=String(j.gift_card_title||"â"),I=parseFloat(String(j.amount||0)).toFixed(2);return` 151 <div class="flex items-center justify-between gap-4 ${q===z-1?"":"border-b"} !mt-1 pt-3 pb-4 first:pt-0" 152 style="background-color: transparent; border-color: var(--ui-border-medium);"> 153 <!-- Left Section: Avatar and Info --> 154 <div class="flex items-center gap-3 flex-1 min-w-0"> 155 ${w(J,"w-8 h-8",K)} 156 <div class="ui-text-secondary text-sm truncate">
157 <span class="font-semibold ui-text-primary">${Z}</span> purchased <span class="ui-text-secondary">${X}</span> on <span class="ui-text-secondary">${Q}</span> 158 </div> 159 </div> 160 161 <!-- Right Section: Status badge + price (fixed width on tablet+ so badges align) --> 162 <div class="flex items-center gap-3 flex-shrink-0"> 163 ${this.renderStatusBadge(j.status?Number(j.status):-1)} 164 <span class="ui-text-primary font-semibold whitespace-nowrap md:w-[72px] md:text-right">$${I}</span> 165 </div> 166 </div> 167 `}formatDate(j){if(!j)return"â";try{let q=new Date(j),J=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"][q.getMonth()],K=q.getDate();return`${J} ${K}`}catch(q){return"â"}}renderStatusBadge(j){switch(j){case 1:return'<span class="badge badge-soft badge-success badge-sm">Delivered</span>';case 6:return'<span class="badge badge-soft badge-accent badge-sm">Recipient notified</span>';case 7:case 9:return'<span class="badge badge-soft badge-success badge-sm">Redeemed</span>';case 8:return'<span class="badge badge-soft badge-warning badge-sm">Refunded</span>';case 5:return"";default:return""}}renderEmptyState(){return` 168 <div class="empty-state flex flex-col items-center justify-center text-center px-6"> 169 <img src="/static/v3/images/icons/empty.svg" alt="Empty" class="w-16 h-auto mb-4 opacity-40"> 170 <h4 class="ui-text-primary font-medium mb-2">No gifts received yet</h4> 171 <p class="ui-text-secondary text-sm">Gift cards will appear here once they've been purchased.</p> 172 </div> 173 `}setupSlideoutSpecificListeners(){let j=this.querySelector("#manual-delivery-form");if(j)this.addListener(j,"submit",async(z)=>{z.preventDefault(),await this.handleManualDelivery()});let q=this.querySelector("#edit-goal-btn");if(q)this.addListener(q,"click",async()=>{let z=Y();if(z){let K=z.getTributeData(),Q=z.getCurrentView(),O={};if(K?.uuid)O.uuid=K.uuid;if(K?.slug)O.slug=K.slug;O.view=Q,x("Edit Goal Button Clicked",O)}await import("./EditGoalModal-xnhs14f4.js");let J=document.querySelector("tribute-edit-goal-modal");if(!J)J=document.createElement("tribute-edit-goal-modal"),document.body.appendChild(J);if(J&&typeof J.open==="function")J.open();else W.error("GiftSlideout","EditGoalModal not found or missing open method")})}async handleManualDelivery(){let j=this.querySelector("#recipient-email-input"),q=this.querySelector("#deliver-cards-btn"),z=this.querySelector("#manual-delivery-message");if(!j||!q||!z)return;let J=j.value.trim();if(!J){this.openManualSendDetailsIfPresent(),this.showDeliveryMessage("Please enter a valid email address","error");return}let K=this.getTributeUuid();if(!K){this.openManualSendDetailsIfPresent(),this.showDeliveryMessage("Unable to find tribute ID","error");return}let Q=q.innerHTML;q.disabled=!0,q.innerHTML=` 174 <span class="loading loading-spinner loading-sm"></span> 175 Sending... 176 `;try{let O=await V.deliverGiftCardsManually(K,J);if(O.success){let Z=O.message||"An email has been sent to the Tribute recipient to claim their gifts.";await this.loadGiftPurchases();let X=this.querySelector("#slideout-panel > div.flex-1");if(X)X.innerHTML=this.renderContent(),this.setupSlideoutSpecificListeners();this.showDeliveryMessage(Z,"success")}else this.openManualSendDetailsIfPresent(),this.showDeliveryMessage(O.error||"Failed to deliver gift cards. Please try again.","error")}catch(O){W.error("GiftSlideout","Error delivering gift cards:",O),this.openManualSendDetailsIfPresent(),this.showDeliveryMessage("An error occurred while delivering gift cards. Please try again.","error")}finally{q.disabled=!1,q.innerHTML=Q}}openManualSendDetailsIfPresent(){let j=this.querySelector("#manual-send-details");if(j)j.open=!0}showDeliveryMessage(j,q){let z=this.querySelector("#manual-delivery-message");if(!z)return;let J=q==="success"?"alert-success":"alert-error",K=q==="success"?"check-circle":"error-circle",Q=q==="error"?"text-error shrink-0":"stroke-current shrink-0";if(z.innerHTML=` 177 <div role="alert" class="alert ${J}"> 178 <app-icon name="${K}" size="24" class="${Q}"></app-icon>
179 <span>${j}</span> 180 </div> 181 `,z.classList.remove("hidden"),q==="success")setTimeout(()=>{z.classList.add("hidden"),z.innerHTML=""},5000)}}customElements.define("tribute-gifts-slideout",P);export{P as GiftSlideout};
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.