CRC_recomendation_tool

CrcPromotionresultstab

CrcPromotionresultstab está temporariamente indisponível.

google reCAPTCHA v2 visible demo


google reCAPTCHA v2 visible demo


Aplicações Aninhadas

Publicador de Conteúdos e Mídias

Voltar CRC_recomendation_tool

Um erro ocorreu enquanto processava o modelo.
Java method "com.sun.proxy.$Proxy1454.findCrcUser(long)" threw an exception when invoked on com.sun.proxy.$Proxy1454 object "com.elan.crc.user.service.impl.CrcUserLocalServiceImpl@59fe88ad"; see cause exception in the Java stack trace.

----
FTL stack trace ("~" means nesting-related):
	- Failed at: #assign user = crcuserLS.findCrcUser(...  [in template "10154#10192#5255368" at line 12, column 1]
----
1<#assign utilServ = (serviceLocator.findService("com.elan.crc.utilites.service.CRCRemoteServiceService"))! /> 
2<#assign portalURL = themeDisplay.getPortalURL() /> 
3<#assign oadURL_TC = 'https://online1.elancard.com/oad/terms.controller' /> 
4 
5<#if portalURL?contains("uat")> 
6    <#assign oadURL_TC = 'https://uat-online1.elancard.com/oad/terms.controller' /> 
7</#if> 
8 
9<#--  New code to find location code via client profile rather than query string params  --> 
10<#assign userId = themeDisplay.getUserId() /> 
11<#assign crcuserLS = serviceLocator.findService('com.elan.crc.user.service.CrcUserLocalService')> 
12<#assign user = crcuserLS.findCrcUser(userId?number)> 
13<#assign lc = user.getLocationCode()> 
14<#assign prefix = "00000" > 
15<#assign lcWithPrefix = prefix + lc > 
16<#assign withPrefixLength = lcWithPrefix?length > 
17<#assign startHere = withPrefixLength - 5> 
18<#assign lc = lcWithPrefix?substring(startHere)> 
19 
20<#-- using lc gets partner name, pbu, and subbu --> 
21<#assign clientProfileService = serviceLocator.findService('com.elan.crc.user.service.CrcClientProfileLocalService') > 
22<#assign clientProfileList = clientProfileService.findByLocationCode(lc)> 
23<#if clientProfileList?first?has_content> 
24  <#assign clientProfile = clientProfileList?first> 
25  <#assign partnerName = clientProfile.getMarketingNameLong()> 
26  <#assign pbu = clientProfile.getPbu()> 
27  <#assign subbu = clientProfile.getSUBBRANDBUNBR()> 
28  <#-- logoFileName path --> 
29  <#assign logoFileName = clientProfile.getLogoBFormat1()?replace(".", "-")?replace("-([^-]*)$", ".$1", "r")?lower_case> 
30 
31  <#-- gets cards for finical institution(fi) --> 
32  <#assign fiCardsData = (utilServ.makeCall('crcTier3GetPbuData','0&'+ pbu +'&'+subbu))!>  
33</#if> 
34 
35 
36<#assign cdnCardArtUrl = (propsUtil.get('rackspace.cdn.cardart.url'))!> 
37<#-- Prod cdnLogoUrl--> 
38<#assign cdnLogoUrl = (propsUtil.get('rackspace.cdn.web.url'))!> 
39 
40 
41 <#assign crcRewardsCalculatorLocalService = serviceLocator.findService('com.elan.crc.quicklink.service.CrcRewardsCalculatorLocalService') > 
42 <#assign rewardsList = 
43    crcRewardsCalculatorLocalService.getCrcRewardsCalculators(-1,-1)> 
44     
45 
46<#-- BUILD REWARDS LOOKUP MAP (offerType → reward) --> 
47 
48<#assign rewardsByOfferType = {}> 
49 
50<#if rewardsList?has_content> 
51  <#list rewardsList as reward> 
52    <#assign rewardsByOfferType = 
53      rewardsByOfferType + { 
54        reward.getOfferType()?string : reward 
55
56
57  </#list> 
58</#if> 
59 
60<#-- WEB CONTENT LOOKUP (offerType → child fields) --> 
61<#-- Parent: Numberh6rv (offerType) --> 
62 
63<#assign wcByOfferType = {}> 
64 
65<#if Numberh6rv.getSiblings()?has_content> 
66  <#list Numberh6rv.getSiblings() as wcItem> 
67 
68    <#assign offerTypeKey = wcItem.getData()?string /> 
69 
70    <#assign textTitle = "" /> 
71    <#if wcItem.Text13zu?? && wcItem.Text13zu.getData()?has_content> 
72      <#assign textTitle = wcItem.Text13zu.getData() /> 
73    </#if> 
74 
75    <#assign childTextHtml = "" /> 
76     <#if wcItem.HTMLbl7t?? && wcItem.HTMLbl7t.getData()?has_content> 
77      <#assign childTextHtml = wcItem.HTMLbl7t.getData() /> 
78    </#if> 
79     
80    <#assign childText = "" /> 
81     <#if wcItem.annualFeeText?? && wcItem.annualFeeText.getData()?has_content> 
82      <#assign childText = wcItem.annualFeeText.getData() /> 
83    </#if> 
84     
85    <#assign wcByOfferType = wcByOfferType + {  
86      offerTypeKey : {  
87        "text" : textTitle,  
88        "textHtml" : childTextHtml,  
89        "childText" : childText 
90      }  
91    }> 
92 
93 
94  </#list> 
95</#if> 
96 
97<#-- COMBINED LIST --> 
98 
99<#assign combinedList = []> 
100<#if fiCardsData?has_content> 
101  <#list fiCardsData as fib> 
102    <#assign offerKey = fib.offerType?string /> 
103     <#assign offerId = fib.offerId?string /> 
104    <#assign reward = rewardsByOfferType[offerKey]! /> 
105    <#assign wcData = wcByOfferType[offerKey]! /> 
106    <#-- Include only when reward exists --> 
107    <#if reward?has_content> 
108      <#assign combinedList = combinedList + [{ 
109        "offerType" : offerKey, 
110        "offerId"   : offerId, 
111        "card"      : fib, 
112        "reward"    : reward, 
113        "wc"        : wcData    
114      }]> 
115    </#if> 
116 
117  </#list> 
118</#if> 
119 
120<#-- STEP 3: OPTIONAL SORT (BY CARD ORDER) --> 
121<#--  
122<#if combinedList?has_content> 
123  <#assign combinedList = combinedList?sort_by("card.cardOrder")> 
124</#if> 
125--> 
126 
127<div class="container re_header"> 
128    <!-- Logo Section --> 
129        <div class="header-bar"> 
130         <div class="header-left"> 
131            <#if (backArrow.getData())?? && backArrow.getData() != ""> 
132                	<img class="d-none" alt="${backArrow.getAttribute("alt")}" data-fileentryid="${backArrow.getAttribute("fileEntryId")}" src="${backArrow.getData()}" /> 
133            </#if> 
134            <img 
135                class="re_cdn_logo" src="${cdnLogoUrl!''}/${logoFileName!''}" 
136                alt="elan-logo" loading="eager"/>   
137         </div> 
138         
139          <!-- Right section --> 
140         <div class="header-right d-none card_reset_btn" id="resettext"onclick="setCardType('ALL', this)"> 
141                <#if (resetIcon.getData())?? && resetIcon.getData() != ""> 
142                	<img alt="${resetIcon.getAttribute("alt")}" data-fileentryid="${resetIcon.getAttribute("fileEntryId")}" src="${resetIcon.getData()}" /> 
143                </#if> 
144            <div class="reset-text">Reset</div> 
145         </div> 
146        </div>  
147        
148            <h1 class="re_cdn_titl" id="title1"> 
149            <#if (title.getData())??> 
150            	${title.getData()} 
151            </#if> 
152            </h1> 
153            <p class="re_cdn_sub_titl" id="des1"> 
154            <#if (description.getData())??> 
155            	${description.getData()} 
156            </#if></p>  
157            <h1 class="re_cdn_titl" id="title2"> 
158            <#if (consumerCardTitle.getData())??> 
159            	${consumerCardTitle.getData()} 
160            </#if></h1> 
161            <p class="re_cdn_sub_titl" id="des2"> 
162            <#if (consumerCardDes.getData())??> 
163            	${consumerCardDes.getData()} 
164            </#if></p>  
165            <h1 class="re_cdn_titl" id="title3"> 
166            <#if (consumerCategoryTitle.getData())??> 
167            	${consumerCategoryTitle.getData()} 
168            </#if></h1> 
169            <p class="re_cdn_sub_titl" id="des3"> 
170            <#if (consumerEveryDayDes.getData())??> 
171            	${consumerEveryDayDes.getData()} 
172            </#if></p>  
173            <p class="re_cdn_sub_titl" id="des4"> 
174            <#if (consumerTravelDes.getData())??> 
175            	${consumerTravelDes.getData()} 
176            </#if></p>  
177 
178        <!-- Cards Section --> 
179     
180        <div class="row re_card_sec" id="reCardSec"> 
181     
182    	  <div class="re_card" id="re_card_cosumer" onclick="setCardType('CONSUMER', this)"> 
183    		<img class="re_card_icon" src="${consumerCardImage.getData()}" /> 
184    		<h2 class="re_card_title">Consumer Credit Cards</h2> 
185    	  </div> 
186     
187    	  <div class="re_card" id="re_card_consumer_business" onclick="setCardType('BUSINESS', this)"> 
188    		<img class="re_card_icon" src="${businessCardImage.getData()}" /> 
189    		<h2 class="re_card_title">Business Credit Cards</h2> 
190    	  </div> 
191          <div class="plus-symbol d-none" id="plussymbol"> 
192
193          </div> 
194    	  <div class="re_card d-none" id="re_card_everyday" onclick="setCardType('EVERYDAY', this)"> 
195    		<#if (consumerEveryDayImg.getData())?? && consumerEveryDayImg.getData() != ""> 
196      	    <img class="re_card_icon" alt="${consumerEveryDayImg.getAttribute("alt")}" data-fileentryid="${consumerEveryDayImg.getAttribute("fileEntryId")}" src="${consumerEveryDayImg.getData()}" /> 
197            </#if> 
198    		<h2 class="re_card_title">Everyday Spend</h2> 
199    	  </div> 
200    	   
201    	  <div class="re_card d-none" id="re_card_travel" onclick="setCardType('TRAVEL', this)"> 
202    		<#if (consumerTravelImg.getData())?? && consumerTravelImg.getData() != ""> 
203    	    <img class="re_card_icon" alt="${consumerTravelImg.getAttribute("alt")}" data-fileentryid="${consumerTravelImg.getAttribute("fileEntryId")}" src="${consumerTravelImg.getData()}" /> 
204            </#if> 
205    		<h2 class="re_card_title">Travel</h2> 
206    	  </div> 
207    	  
208        </div> 
209	 
210 
211</div> 
212 
213<div class="car_sec"> 
214    <div class="section-header"> 
215      <div class="section-title" id="cardCount"> 
216         All Cards (${combinedList?has_content?then(combinedList?size, 0)} Cards) 
217      </div> 
218    </div> 
219     
220    <section class="carousel-section" role="region" aria-label="Cards carousel"> 
221 
222      <!-- ADD rcarousel-inner class --> 
223      <div class="card-list rcarousel-inner" id="carouselInner"></div> 
224    </section> 
225</div> 
226 
227<div class="frame_sec d-none" id="framesec"> 
228    <div class="section-aerrow"> 
229        <div class="carousel-indicator"> 
230            <button class="indicator-arrow" id="iframePrev" 
231                    onclick="changeIframe(-1)" aria-label="Previous calculator"> 
232              &#8592; 
233            </button> 
234             
235            <div class="indicator-count" id="indicatorCount"></div> 
236             
237            <button class="indicator-arrow" id="iframeNext" 
238                    onclick="changeIframe(1)" aria-label="Next calculator"> 
239              &#8594; 
240            </button> 
241 
242        </div> 
243 
244    </div> 
245     
246    <div class="iframe-wrapper d-none" id="iframeWrapper"></div> 
247 
248 
249    
250    <div class="section-footer"> 
251      <div class="section-footer-title" id="section-footer-title" onclick="scrollToTop()"> 
252        ↑ Back to top  
253      </div> 
254    </div> 
255</div> 
256 
257<style> 
258.indicator-arrow:disabled { 
259  opacity: 0.4; 
260  cursor: not-allowed; 
261  pointer-events: none; 
262
263 
264.indicator-count { 
265  min-width: 60px; 
266  text-align: center; 
267  font-family: Arial, sans-serif; 
268  font-size: 14px; 
269  font-weight: 700; 
270  color: #ffffff; /* arrow bar is black */ 
271
272.iframe-wrapper { 
273  width: 100%; 
274  height: 100%; 
275  padding: 0 8px; 
276  background: #ffffff; 
277 
278  display: inline-flex; 
279  justify-content: center; 
280  align-items: center; 
281  gap: 8px; 
282  box-sizing: border-box; 
283
284 
285.iframe-content { 
286  flex: 1 1 0; 
287  width: 100%; 
288  max-width: 736px; 
289  height: 558.9px; 
290 
291  border: 0; 
292
293 
294/* ===== HEADER WRAPPER ===== */ 
295.header-bar { 
296  display: flex; 
297  flex-direction: row;           
298  justify-content: space-between; 
299  align-items: center; 
300  max-width: 700px; 
301  width: 100%; 
302  height: auto;                  
303  min-height: 40px; 
304  position: relative; 
305
306 
307/* ===== LEFT SECTION ===== */ 
308.header-left { 
309  width: 300px; 
310  display: flex; 
311  align-items: center; 
312  gap: 16px; 
313
314/* ===== RIGHT SECTION ===== */ 
315.header-right { 
316  display: flex; 
317  align-items: center; 
318  justify-content: center; 
319  gap: 8px; 
320
321 
322 
323/* Reset text */ 
324.card_reset_btn{ 
325  cursor: pointer; 
326
327.reset-text { 
328  color: var(--Core-Black, #000000); 
329  font-family: Arial, sans-serif; 
330  font-size: 14px; 
331  font-weight: 700; 
332  text-align: center; 
333
334 
335.re_header { 
336  max-width: 752px; 
337  width: 100%; 
338  background: #E6E6E6; 
339  padding: 24px; 
340  box-sizing: border-box; 
341
342.re_car_sec{ 
343  height: 62px; 
344  background: #000000; 
345  border-top: 1px solid #D7D7D7; 
346  box-sizing: border-box; 
347
348 
349.re_cdn_logo { 
350  width: 162px; 
351  height: 62px; 
352
353.re_cdn_logo.consumer-logo { 
354  width: 104px; 
355  height: 40px; 
356
357.reset-link { 
358  margin-left: auto;   /* pushes to right corner */ 
359  cursor: pointer; 
360  font-weight: 700; 
361  margin-right:50px; 
362
363 
364.re_cdn_titl{ 
365  font: 400 34px/52px Arial, sans-serif; 
366  color: #000; 
367
368 
369.re_cdn_sub_titl { 
370  max-width: 702px; 
371  width: 100%; 
372  font-family: Arial, sans-serif; 
373  font-weight: 400; 
374  font-size: 14px; 
375  line-height: 22px; 
376  letter-spacing: 0; 
377  color: #000000; 
378
379 
380 
381.re_card_sec{ 
382  display: flex; 
383  justify-content: center; 
384  align-items: center; 
385  gap: 16px; 
386  height: 100px; 
387
388 
389.re_card { 
390  box-sizing: border-box; 
391  display: flex; 
392  flex-direction: column; 
393  align-items: center; 
394  width: 100%; 
395  max-width: 200px; 
396  height: 100px; 
397  padding: 12px; 
398  background: #FFFFFF; 
399  border: 1px solid #969798; 
400  cursor: pointer; 
401
402 
403.plus-symbol { 
404    color: var(--Core-Elan-Dark-Blue, #084BB7); 
405    text-align: center; 
406    font-family: Arial, sans-serif; 
407    font-size: 20px; 
408    font-weight: 700; 
409    line-height: normal; 
410
411 
412.re_card.active { 
413  background: var(--Core-Elan-Dark-Blue, #084BB7); 
414 
415
416.re_card.active .re_card_title { 
417  color: #ffffff; /* or whatever color you want */ 
418
419.re_card_sec.consumer-active { 
420  gap: 8px; 
421
422.re_card.active .re_card_icon { 
423  filter: brightness(0) invert(1); 
424
425 
426.re_card_icon{ 
427  width: 32px; 
428  height: 32px; 
429  position: relative; 
430  top: 2.08px; 
431
432.re_card_title{ 
433  width: 85px; 
434  height: 32px; 
435  font-family: Arial, sans-serif; 
436  font-weight: 700; 
437  font-size: 14px; 
438  line-height: 1; 
439  text-align: center; 
440  color: #084BB7; 
441
442 
443</style> 
444 
445<style> 
446.car_sec{ 
447  max-width: 754px; 
448  width: 100%; 
449 /* min-height: 705px; */ 
450  box-sizing: border-box; 
451
452.section-header { 
453  box-sizing: border-box; 
454  width: 100%; 
455  max-width: 754px; 
456  height: 62px; 
457  background: #000000; 
458  border: 1px solid #D7D7D7; 
459  display: flex; 
460  align-items: center; 
461  padding: 0 16px; 
462
463 
464.section-title { 
465  font-family: Arial, sans-serif; 
466  font-weight: 700; 
467  font-size: 18px; 
468  line-height: 22px; 
469  color: #FFFFFF; 
470
471.section-footer{ 
472  box-sizing: border-box; 
473  width: 100%; 
474  max-width: 754px; 
475  height: 62px; 
476  background: var(--Core-Dark-Gray, #969798); 
477  border: 1px solid #D7D7D7; 
478  display: flex; 
479  align-items: center; 
480  padding: 0 16px; 
481
482.carousel-section { 
483  position: relative; 
484  overflow: hidden; 
485  max-width: 750px; 
486  width: 100%; 
487 /* min-height: 643px; */ 
488  display: flex; 
489  flex-direction: column; 
490  gap: 16px; 
491  padding: 24px 0; 
492  background: var(--Core-White, #FFFFFF); 
493  box-sizing: border-box; 
494
495 
496.card-list { 
497  display: flex !important; 
498  flex-wrap: wrap !important; 
499  justify-content: center; 
500  gap: 16px; 
501  transform: none !important; 
502  transition: none !important; 
503
504 
505.rcard { 
506  flex: 0 0 calc(33.333% - 16px); 
507  max-width: calc(33.333% - 16px); 
508  display: flex; 
509  justify-content: center; 
510
511 
512 
513.cal-card { 
514  max-width: 210px; 
515  width: 100%; 
516  border: 1px solid #FFFFFF; 
517  box-sizing: border-box; 
518  position: relative; 
519  font-family: Arial, sans-serif; 
520
521 
522/* ===== IMAGE ===== */ 
523.cal-card-image { 
524  width: 100%; 
525  display: flex; 
526  justify-content: center; 
527  position: absolute; 
528  z-index: 2; 
529
530 
531.cal-card-image img { 
532  width: 171.875px; 
533  height: 110px; 
534  object-fit: contain; 
535
536 
537 
538/* ===== BODY ===== */ 
539 
540.cal-card-body { 
541  margin-top: 83px; 
542  width: 100%; 
543  background: #CECACA; 
544  border-radius: 12px; 
545  box-sizing: border-box; 
546  padding: 16px; 
547  color:#00000; 
548
549 
550 
551/* ===== TITLE ===== */ 
552.cal-card-title { 
553  height: 44px; 
554  font-family: Arial, sans-serif; 
555  font-weight: 700; 
556  font-size: 18px; 
557  line-height: 21.6px; 
558  letter-spacing: 0; 
559  text-align: center; 
560  display: flex; 
561  align-items: center; 
562  justify-content: center; 
563
564 
565 
566/* ===== DIVIDER ===== */ 
567 
568.cal-divider, .cal-card-divider { 
569  width: 162px; 
570  margin: 16px auto; 
571  border-bottom: 1px solid #000000; 
572
573 
574/* ===== DETAILS ===== */ 
575  .cal-card-details { 
576  width: 162px; 
577  height: 75px; 
578  display: flex; 
579  flex-direction: column; 
580  gap: 12px; 
581
582 
583/* Frame */ 
584.cal-card-detail-row { 
585  width: 100%; 
586  min-height: 44px; 
587  display: flex; 
588  gap: 8px; 
589  box-sizing: border-box; 
590
591 
592.multiplier { 
593  min-width: 21px; 
594  font-family: Arial, sans-serif; 
595  font-weight: 700; 
596  font-size: 14px; 
597  line-height: 22px; 
598  white-space: nowrap; 
599
600.description { 
601  font-family: Arial, sans-serif; 
602  font-weight: 400; 
603  font-size: 14px; 
604  line-height: 22px; 
605  text-align: center; 
606
607 
608/* ===== FEE ===== */ 
609.cal-fee { 
610  font-family: Arial, sans-serif; 
611  font-weight: 400; 
612  font-size: 14px; 
613  line-height: 22px; 
614  text-decoration: underline; 
615  text-align: center; 
616  color : #000 !important; 
617
618 
619 
620/* ===== ACTIONS ===== */ 
621.cal-actions { 
622  display: flex; 
623  justify-content: center; 
624  margin-top: auto; 
625
626 
627/* ===== BUTTON ===== */ 
628.cal-btn-primary { 
629  color:var(--Core-Elan-Dark-Blue, #084BB7) !important; 
630  width: 150px; 
631  height: 44px; 
632  color: #000; 
633  cursor: pointer; 
634  display: flex; 
635  align-items: center; 
636  justify-content: center; 
637  border: 2px solid var(--Core-Elan-Dark-Blue, #084BB7) !important; 
638  background: var(--Core-White, #FFF) !important; 
639
640 
641.cal-btn-text { 
642    text-shadow: none !important; 
643    font-family: Arial, sans-serif; 
644    font-size: 14px; 
645    font-style: normal; 
646    font-weight: 700; 
647    line-height: 22.5px; 
648    text-transform: capitalize; 
649
650.frame_sec{ 
651  max-width: 754px; 
652  width: 100%; 
653  box-sizing: border-box; 
654
655 
656.frame-section-header { 
657  box-sizing: border-box; 
658  width: 100%; 
659  max-width: 754px; 
660  height: 62px; 
661  background: #000000; 
662  border: 1px solid #D7D7D7; 
663  display: flex; 
664  align-items: center; 
665  justify-content: center; 
666
667 
668.frame-title { 
669  font-family: Arial, sans-serif; 
670  font-weight: 700; 
671  font-size: 18px; 
672  line-height: 22px; 
673  color: #FFFFFF; 
674
675.section-footer-title { 
676    color: var(--Core-Black, #000000); 
677    text-align: center; 
678    font-family: Arial, sans-serif; 
679    font-size: 18px; 
680    font-style: normal; 
681    font-weight: 700; 
682    line-height: 22px; 
683    max-width: 737.203px; 
684    flex-shrink: 0; 
685	margin: auto; 
686    cursor: pointer; 
687
688 
689/* Arrows */ 
690.section-aerrow { 
691  box-sizing: border-box; 
692  width: 100%; 
693  max-width: 754px; 
694  height: 62px; 
695  background: #000000; 
696  border: 1px solid #D7D7D7; 
697  display: flex; 
698  padding: 0 16px; 
699  align-items: center; 
700  justify-content: center; 
701
702.carousel-arrow { 
703  position: absolute; 
704  top: 50%; 
705  transform: translateY(-50%); 
706  background: #ffffff; 
707  border: 1px solid #ccc; 
708  width: 36px; 
709  height: 36px; 
710  border-radius: 50%; 
711  cursor: pointer; 
712  font-size: 22px; 
713  line-height: 34px; 
714  text-align: center; 
715  z-index: 5; 
716
717 
718.carousel-arrow.left { 
719  left: 10px; 
720
721 
722.carousel-arrow.right { 
723  right: 10px; 
724
725 
726.carousel-arrow:hover { 
727  background: #084BB7; 
728  color: #fff; 
729
730.carousel-indicator { 
731  display: flex; 
732  align-items: center; 
733  gap: 14px; 
734
735 
736.indicator-arrow { 
737  border: none; 
738  font-size: 22px; 
739  cursor: pointer; 
740  background: #000 !important; 
741
742 
743.indicator-arrow:hover { 
744  color: #084BB7; 
745
746 
747.indicator-dots { 
748  display: flex; 
749  gap: 8px; 
750
751 
752.indicator-dot { 
753  width: 10px; 
754  height: 10px; 
755  border-radius: 50%; 
756  background: #d0d0d0; 
757  cursor: pointer; 
758
759 
760.indicator-dot.active { 
761  background: #084BB7; 
762
763 
764.rcard.is-focused { 
765  outline: none; 
766  box-shadow: none; 
767  border: none; 
768
769 
770.rcard.is-focused .cal-card-body { 
771  color:#fff; 
772  background:var(--Core-Elan-Dark-Blue, #084BB7) 
773
774.rcard.is-focused .cal-fee { 
775  color:#fff !important; 
776
777.rcard.is-focused .cal-divider, .rcard.is-focused .cal-card-divider { 
778 border-bottom: 1px solid var(--Core-Elan-Dark-Blue, #fff) 
779
780</style> 
781 
782<script> 
783const cardsData = [ 
784  <#if combinedList?has_content> 
785    <#list combinedList as item> 
786
787      offerType: "${item.offerType}", 
788      offerId: "${item.offerId}", 
789      title: "${item.reward.getCardName()?js_string!''}", 
790      groupName: 
791        "${item.reward.getGroupName()?upper_case?contains('BUSINESS')?then('BUSINESS','CONSUMER')}", 
792      category: 
793        "${item.reward.getCategory()?upper_case?contains('EVERYDAY')?then('EVERYDAY','TRAVEL')}", 
794      imageUrl: "${cdnCardArtUrl}/${item.card.filename}.png", 
795      wcTextHtml: "${item.wc?has_content?then(item.wc.textHtml?js_string,'')}", 
796     wcChildText: "${item.wc?has_content?then(item.wc.childText?js_string,'')}" 
797    }<#if item_has_next>,</#if> 
798    </#list> 
799  </#if> 
800]; 
801 
802 
803/* ========================================================= 
804   INIT 
805========================================================= */ 
806 
807document.addEventListener('DOMContentLoaded', () => { 
808  applyInitialCardMixUI(); 
809  renderCarousel(); 
810  autoSelectFirstCard();    
811  updateIframeCounter(); 
812  isInitialLoad = false; 
813}); 
814 
815 
816function setCardType(type, el) { 
817 
818  if ( 
819    (type === 'CONSUMER' || type === 'BUSINESS') && 
820    el.classList.contains('disabled') 
821  ) { 
822    return; 
823
824 
825    if (type === 'ALL') { 
826      resetUIToDefault(); 
827      return; 
828
829 
830  // Consumer / Business 
831  if (type === 'CONSUMER' || type === 'BUSINESS') { 
832    activeCardType = type; 
833    activeCategory = 'ALL'; 
834
835 
836  // Category only under Consumer 
837  if ( 
838    (type === 'EVERYDAY' || type === 'TRAVEL') && 
839    activeCardType === 'CONSUMER' 
840  ) { 
841    activeCategory = type; 
842
843 
844    // Active UI 
845    // Remove active only when switching main types 
846    if (type === 'CONSUMER' || type === 'BUSINESS') { 
847      document.querySelectorAll('.re_card') 
848        .forEach(card => card.classList.remove('active')); 
849
850     
851    // Always activate clicked card 
852    el.classList.add('active'); 
853     
854    // Keep CONSUMER active when selecting sub-categories 
855    if (type === 'EVERYDAY' || type === 'TRAVEL') { 
856      const consumerCard = document.getElementById('re_card_cosumer'); 
857      if (consumerCard) { 
858        consumerCard.classList.add('active'); 
859
860
861 
862 
863  // Disable logic 
864  if (type === 'CONSUMER') { 
865    handleConsumerSubCard(); 
866    el.classList.add('disabled');  
867
868 
869  if (type === 'BUSINESS') { 
870    document.getElementById('re_card_everyday')?.classList.remove('active'); 
871    document.getElementById('re_card_travel')?.classList.remove('active'); 
872    el.classList.add('disabled'); 
873
874 
875  if (type === 'EVERYDAY') handleEveryDayCard(); 
876  if (type === 'TRAVEL') handleTravelCard(); 
877   
878  currentIframeIndex = 0; 
879  currentPage = 0; 
880  renderCarousel(); 
881  autoSelectFirstCard();  
882  updateIframeCounter(); 
883   
884
885 
886 
887function handleConsumerSubCard() { 
888  $("#re_card_consumer_business").hide(); 
889  $("#re_card_everyday,#re_card_travel,#plussymbol").removeClass("d-none"); 
890 
891  $("#title2,#des2").removeClass("d-none"); 
892  $("#title1,#des1").addClass("d-none"); 
893  const cardContainer = document.querySelector('.re_card_sec'); 
894  cardContainer?.classList.add('consumer-active'); 
895   $("#resettext").removeClass("d-none"); 
896  document.querySelector('.re_cdn_logo')?.classList.add('consumer-logo'); 
897 
898
899function handleEveryDayCard() { 
900  document.getElementById('re_card_travel')?.classList.remove('active'); 
901  $("#resettext").removeClass("d-none"); 
902  $("#title3,#des3").removeClass("d-none"); 
903  $("#title2,#des2,#des4").addClass("d-none"); 
904
905function handleTravelCard() { 
906  document.getElementById('re_card_everyday')?.classList.remove('active'); 
907  $("#resettext").removeClass("d-none"); 
908  $("#title3,#des4").removeClass("d-none"); 
909  $("#title2,#des2,#des3").addClass("d-none"); 
910
911 
912 
913function applyInitialCardMixUI() { 
914 
915  const groupSet = new Set(cardsData.map(card => card.groupName)); 
916  $("#reCardSec").removeClass("d-none"); 
917  // First hide everything (safe – already hidden, no flicker) 
918  $("#title1,#title2,#title3,#des1,#des2,#des3,#des4,#framesec,#resettext") 
919    .addClass("d-none"); 
920 
921  // BOTH Consumer + Business 
922  if (groupSet.size > 1) { 
923    $("#title1,#des1").removeClass("d-none"); 
924
925 
926  // ONLY Consumer 
927  else if (groupSet.has('CONSUMER')) { 
928    activeCardType = 'CONSUMER'; 
929    activeCategory = 'ALL'; 
930    $("#title2,#des2").removeClass("d-none"); 
931	$("#re_card_everyday,#re_card_travel").removeClass("d-none"); 
932    $("#re_card_cosumer,#re_card_consumer_business").addClass("d-none"); 
933
934 
935  // ONLY Business 
936  else if (groupSet.has('BUSINESS')) { 
937    $("#title1,#des1").removeClass("d-none"); 
938    $("#reCardSec").addClass("d-none"); 
939
940
941 
942 
943 
944function resetUIToDefault() { 
945 
946  //  Reset filter logic 
947  activeCardType = 'ALL'; 
948  activeCategory = 'ALL'; 
949 
950  //  Reset card buttons 
951  document.querySelectorAll('.re_card').forEach(card => { 
952    card.classList.remove('active'); 
953    card.classList.remove('disabled'); 
954  }); 
955 
956  //  Restore card button visibility 
957  $("#re_card_consumer_business").show(); 
958  $("#re_card_everyday,#re_card_travel,#plussymbol").addClass("d-none"); 
959  document.querySelector('.re_card_sec')?.classList.remove('consumer-active'); 
960  document.querySelector('.re_cdn_logo')?.classList.remove('consumer-logo'); 
961   
962  document.querySelectorAll('.rcard') 
963  .forEach(card => card.classList.remove('is-focused')); 
964 
965   
966  currentIframeIndex = 0; 
967  //  Apply data-based hiding (ONLY what is needed) 
968  applyInitialCardMixUI(); 
969 
970  //  Reset carousel state 
971  currentPage = 0; 
972  
973 
974  // Re-render 
975  renderCarousel(); 
976  autoSelectFirstCard();  
977
978 
979 
980 
981/* ========================================================= 
982   GLOBAL STATE 
983========================================================= */ 
984const PAGE_SIZE = 3; 
985let activeCardType = 'ALL'; 
986let activeCategory = 'ALL'; 
987let currentPage = 0; 
988let isInitialLoad = true; 
989let currentIframeIndex = 0; 
990let allowAutoScroll = true; 
991 
992 
993 
994 
995 
996 
997 
998 
999 
1000/* ========================================================= 
1001   FILTER + COUNT 
1002========================================================= */ 
1003 
1004function updateCardCount(count, type) { 
1005  const el = document.getElementById('cardCount'); 
1006  if (!el) return; 
1007 
1008  let label = 'All Cards'; 
1009  if (type === 'CONSUMER') label = 'Consumer Cards'; 
1010  if (type === 'BUSINESS') label = 'Business Cards'; 
1011 
1012  // reeMarker-safe 
1013  el.textContent = `${r"${label}"} (${r"${count}"} Cards)`; 
1014
1015 
1016 
1017 
1018function getFilteredCards() { 
1019  return cardsData.filter(card => { 
1020 
1021    // Filter by Consumer / Business 
1022    if (activeCardType !== 'ALL' && card.groupName !== activeCardType) { 
1023      return false; 
1024
1025 
1026    // Category filter ONLY when Consumer is selected 
1027    if (activeCardType === 'CONSUMER' && activeCategory !== 'ALL') { 
1028      return card.category === activeCategory; 
1029
1030 
1031    // Business ignores category 
1032    return true; 
1033  }); 
1034
1035 
1036 
1037/* ========================================================= 
1038   CAROUSEL RENDER 
1039========================================================= */ 
1040function renderCarousel() { 
1041  const container = document.getElementById('carouselInner'); 
1042  if (!container) return; 
1043 
1044  const filteredCards = getFilteredCards(); 
1045 
1046 
1047   
1048  if (!filteredCards.length) { 
1049  container.innerHTML = '<p style="padding:20px">No cards available</p>'; 
1050  updateCardCount(0, activeCardType); 
1051  return; 
1052
1053 
1054 
1055  updateCardCount(filteredCards.length, activeCardType); 
1056 
1057    const start = currentPage * PAGE_SIZE; 
1058    const end = start + PAGE_SIZE; 
1059    const pageCards = filteredCards.slice(start, end); 
1060     
1061    container.innerHTML = pageCards.map(card => ` 
1062        <div class="rcard" 
1063             tabindex="0" 
1064             data-offer-type="${r"${card.offerType}"}" 
1065             onclick="showCalculator( 
1066               window.panoUrl + '/calculators/${r"${card.offerType}"}', 
1067               '${r"${card.title}"}' 
1068             )"> 
1069         
1070          <div class="cal-card"> 
1071            <div class="cal-card-image"> 
1072              <img src="${r"${card.imageUrl}"}" alt="Card Image"> 
1073            </div> 
1074         
1075            <div class="cal-card-body"> 
1076              <h3 class="cal-card-title">${r"${card.title}"}</h3> 
1077              <div class="cal-divider"></div> 
1078         
1079              <div class="cal-card-details"> 
1080                <a class="cal-fee" 
1081                   href="${oadURL_TC}?step=display&amp;offerId=${r"${card.offerId}"}&amp;locationCode=${lc}" 
1082                   target="_blank" 
1083                   onclick="event.stopPropagation();"> 
1084                   ${r"${card.wcChildText}"} 
1085                </a> 
1086              </div> 
1087            </div> 
1088          </div> 
1089        </div> 
1090    `).join(''); 
1091     
1092  
1093
1094 
1095/* ========================================================= 
1096   FILTER BUTTON HANDLER 
1097========================================================= */ 
1098 
1099 
1100 
1101 
1102/* ========================================================= 
1103   CAROUSEL CORE 
1104========================================================= */ 
1105function getCards() { 
1106  return document.querySelectorAll('.rcard'); 
1107
1108 
1109 
1110 
1111  
1112function showCalculator(url, title) { 
1113  console.log("[CAL URL]",url); 
1114  const filteredCards = getFilteredCards(); 
1115 
1116  const index = filteredCards.findIndex( 
1117    card => url.includes(card.offerType) 
1118  ); 
1119 
1120  if (index !== -1) { 
1121    currentIframeIndex = index; 
1122    highlightCard(filteredCards[index].offerType); 
1123
1124 
1125  const wrapper = document.getElementById('iframeWrapper'); 
1126  const titleEl = document.getElementById('frametitle'); 
1127 
1128  if (titleEl) { 
1129    titleEl.textContent = title + ' Rewards Calculator'; 
1130
1131 
1132  wrapper.innerHTML = ''; 
1133 
1134  const iframe = document.createElement('iframe'); 
1135  iframe.src = url; 
1136  iframe.className = 'iframe-content'; 
1137  iframe.loading = 'lazy'; 
1138 
1139  wrapper.appendChild(iframe); 
1140 
1141  $("#framesec,#iframeWrapper").removeClass("d-none"); 
1142 
1143  // scroll only when allowed 
1144  if (allowAutoScroll) { 
1145    wrapper.scrollIntoView({ behavior: 'smooth' }); 
1146
1147 
1148  updateIframeCounter(); 
1149
1150 
1151 
1152function scrollToTop() { 
1153  $('html, body').animate({ scrollTop: 0 }, 'slow'); 
1154
1155 
1156 
1157function changeIframe(direction) { 
1158  const filteredCards = getFilteredCards(); 
1159  const total = filteredCards.length; 
1160  if (!total) return; 
1161 
1162  const nextIndex = currentIframeIndex + direction; 
1163 
1164  // stop at bounds 
1165  if (nextIndex < 0 || nextIndex >= total) return; 
1166 
1167  currentIframeIndex = nextIndex; 
1168 
1169  // derive page from index 
1170  const requiredPage = Math.floor(currentIframeIndex / PAGE_SIZE); 
1171 
1172  // switch page ONLY if needed 
1173  if (requiredPage !== currentPage) { 
1174    currentPage = requiredPage; 
1175 
1176    // prevent auto-select + scroll during re-render 
1177    allowAutoScroll = false; 
1178    renderCarousel(); 
1179    allowAutoScroll = true; 
1180
1181 
1182  const card = filteredCards[currentIframeIndex]; 
1183 
1184  // highlight selected card 
1185  highlightCard(card.offerType); 
1186 
1187  // load iframe (user action → scroll allowed) 
1188  const url = window.panoUrl+'/calculators/' + card.offerType; 
1189 
1190  showCalculator(url, card.title); 
1191 
1192  updateIframeCounter(); 
1193
1194 
1195 
1196 
1197 
1198 
1199function updateIframeCounter() { 
1200  const counterEl = document.getElementById('indicatorCount'); 
1201  const prevBtn = document.getElementById('iframePrev'); 
1202  const nextBtn = document.getElementById('iframeNext'); 
1203 
1204  if (!counterEl || !prevBtn || !nextBtn) return; 
1205 
1206  const filteredCards = getFilteredCards(); 
1207  const total = filteredCards.length; 
1208 
1209  if (!total) { 
1210    counterEl.textContent = ''; 
1211    prevBtn.disabled = true; 
1212    nextBtn.disabled = true; 
1213    return; 
1214
1215 
1216  // ARD-BASED COUNT (this is what you want) 
1217  counterEl.textContent = 
1218    (currentIframeIndex + 1) + ' of ' + total; 
1219 
1220  // isable arrows at first / last card 
1221  prevBtn.disabled = currentIframeIndex === 0; 
1222  nextBtn.disabled = currentIframeIndex === total - 1; 
1223
1224 
1225 
1226 
1227function highlightCard(offerType) { 
1228  document.querySelectorAll('.rcard').forEach(card => { 
1229    if (card.dataset.offerType === offerType) { 
1230      card.classList.add('is-focused'); 
1231    } else { 
1232      card.classList.remove('is-focused'); 
1233
1234  }); 
1235
1236 
1237function autoSelectFirstCard() { 
1238  const filteredCards = getFilteredCards(); 
1239  if (!filteredCards.length) return; 
1240 
1241  const firstCard = filteredCards[0]; 
1242 
1243  currentIframeIndex = 0; 
1244 
1245  // disable scroll for auto select 
1246  allowAutoScroll = false; 
1247 
1248  highlightCard(firstCard.offerType); 
1249 
1250  const url = window.panoUrl+'/calculators/' + firstCard.offerType; 
1251 
1252  showCalculator(url, firstCard.title); 
1253 
1254  // re-enable scroll for user actions 
1255  allowAutoScroll = true; 
1256
1257 
1258</script> 

google reCAPTCHA v2 demo

google reCAPTCHA v2 visible demo


google reCAPTCHA v2 demo