PageSourceSearch

https://www.tribute.co/static/v3/dist/creator/GiftSlideout-jqgmmpkc.js

js tribute.co collected 2026-09-24 20:00:53 UTC 17,823 bytes, 181 lines download raw bytes

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.