An error occurred while processing the template.
The following has evaluated to null or missing:
==> dateHelper  [in template "86196622878935#20120#46912" at line 6, column 24]

----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----

----
FTL stack trace ("~" means nesting-related):
	- Failed at: #assign expDate = dateHelper.getForma...  [in template "86196622878935#20120#46912" at line 6, column 5]
----
1<#assign journalArticleLocalService = serviceLocator.findService("com.liferay.journal.service.JournalArticleLocalService") /> 
2<#assign articleId = .vars["reserved-article-id"].data /> 
3 
4<#if journalArticleLocalService??> 
5    <#assign article = journalArticleLocalService.fetchLatestArticle(themeDisplay.getScopeGroupId(), articleId,0) /> 
6    <#assign expDate = dateHelper.getFormattedDate(article.getExpirationDate(), "d MMM", locale)/> 
7    <#if expDate?has_content> 
8        <#assign expiryLabel = languageUtil.format(locale, "stc.offers.label.offer-expiry", expDate) /> 
9    <#else> 
10        <#assign expiryLabel = languageUtil.get(locale, "stc.offers.label.offer-expiry-never-expires") /> 
11    </#if> 
12</#if> 
13 
14<section class="offer-detailed container"> 
15    <div class="offer-detailed__left-column"> 
16        <div class="offer-detailed__top"> 
17            <div class="offer-detailed__top-container"> 
18                <#if (title.getData())??  && title.getData() != ""> 
19                    <h1 class="offer-detailed__title">${title.getData()}</h1> 
20                </#if> 
21                <#if (shortDescription.getData())??  && shortDescription.getData() != ""> 
22                    <p class="offer-detailed__description">${shortDescription.getData()}</p> 
23                </#if> 
24            </div> 
25 
26            <#if (promotionCode.getData())?? && promotionCode.getData()!= ""> 
27                <div class="offer-detailed__promo-code-container"> 
28                    <p class="offer-detailed__promo-code"> 
29                        ${promotionCode.getData()} 
30                    </p> 
31                    <span class="stc-icon-copy" role="button" tabindex="0" 
32                          aria-label="Copy promotion code"></span> 
33                </div> 
34            </#if> 
35 
36            <#if (image.getData())?? && image.getData() != ""> 
37                <div class="offer-detailed__image-container--small-screen"> 
38                    <div class="offer-detailed__image"> 
39                        <img alt="${image.getAttribute("alt")}" 
40                             data-fileentryid="${image.getAttribute("fileEntryId")}" 
41                             src="${image.getData()}"/> 
42                        <div class="offer-detailed__expiry"> 
43                            ${expiryLabel} 
44                        </div> 
45                    </div> 
46                </div> 
47            </#if> 
48 
49        </div> 
50        <div class="offer-detailed__bottom"> 
51            <#if (validCards.getSiblings()?first.validCardImg.getData())?has_content> 
52 
53                <#if (validLabel.getData())?? &&validLabel.getData() !=""> 
54                    <h3 class="offer-detailed__valid-label"> 
55                        ${validLabel.getData()}</h3> 
56                </#if> 
57 
58                <div class="offer-detailed__images-valid-cards"> 
59                    <#list validCards.getSiblings() as validCard> 
60                        <#if (validCard.validCardImg.getData())??> 
61                            <img class="offer-detailed__images-valid-cards__image" 
62                                 alt="${validCard.validCardImg.getAttribute("alt")}" 
63                                 data-fileentryid="${validCard.validCardImg.getAttribute("fileEntryId")}" 
64                                 src="${validCard.validCardImg.getData()}"/> 
65 
66                            <#if (validCard.validCardHint.getData())??> 
67                                <div class="hint">${validCard.validCardHint.getData()}</div> 
68                            </#if> 
69 
70                        </#if> 
71                    </#list> 
72                </div> 
73            </#if> 
74 
75            <#if (termsAndConditionsSectionTitle.getData())?? && termsAndConditionsSectionTitle.getData()!=""> 
76                <h3 class="offer-detailed__terms-title">${termsAndConditionsSectionTitle.getData()}</h3> 
77            </#if> 
78            <#if (termsAndConditionsRow.getData())?? && termsAndConditionsRow.getData()!=""> 
79                <div class="offer-detailed__terms-description"> 
80                    ${termsAndConditionsRow.getData()} 
81                </div> 
82            </#if> 
83 
84        </div> 
85    </div> 
86    <div class="offer-detailed__right-column"> 
87        <#if (image.getData())?? && image.getData() != ""> 
88            <div class="offer-detailed__image-container"> 
89                <div class="offer-detailed__image"> 
90                    <img alt="${image.getAttribute("alt")}" 
91                         data-fileentryid="${image.getAttribute("fileEntryId")}" 
92                         src="${image.getData()}"/> 
93                    <div class="offer-detailed__expiry"> 
94                        ${expiryLabel} 
95                    </div> 
96                </div> 
97            </div> 
98        </#if> 
99    </div> 
100 
101    <!-- Popup --> 
102    <#if (promoCodeCopiedlabel.getData())?? && promoCodeCopiedlabel.getData()!=""> 
103        <div class="promo-popup" id="promoPopup" role="alert" aria-live="assertive"> 
104            <div class="promo-popup__content"> 
105                <span class="promo-popup__done stc-icon-done-24" aria-hidden="true"></span> 
106                <p class="popup-text">${promoCodeCopiedlabel.getData()}</p> 
107            </div> 
108            <a class="stc-icon-cross-16 promo-popup__close" id="popupClose" aria-label="Close popup" 
109               tabindex="0"></a> 
110        </div> 
111    </#if> 
112     
113</section> 
114 
115<script> 
116    //Cards hover 
117    const pictures = document.querySelectorAll('.offer-detailed__images-valid-cards > picture'); 
118    pictures.forEach((pic) => { 
119        pic.setAttribute('tabindex', '0'); 
120    }); 
121 
122    if (pictures.length > 0) { 
123        const isRTL = document.documentElement.dir === 'rtl'; 
124 
125        function showHint(pic) { 
126            const hint = pic.nextElementSibling; 
127            if (pic && hint) { 
128                const containerRect = pic.parentElement.getBoundingClientRect(); 
129                const picRect = pic.getBoundingClientRect(); 
130 
131                if (containerRect && picRect) { 
132                    const offset = (picRect.width / 2); 
133                    hint.style.position = 'absolute'; 
134                    hint.style.top = (picRect.bottom - containerRect.top + 12) + 'px'; 
135                    hint.style.opacity = '1'; 
136                    hint.style.visibility = 'visible'; 
137 
138                    if (isRTL) { 
139                        const rightOffset = (containerRect.right - picRect.right) + offset; 
140                        hint.style.right = rightOffset + 'px'; 
141                        hint.style.left = 'auto'; // fontos! 
142                    } else { 
143                        const leftOffset = (picRect.left - containerRect.left) + offset; 
144                        hint.style.left = leftOffset + 'px'; 
145                        hint.style.right = 'auto'; // fontos! 
146
147
148
149
150 
151        function hideHint(pic) { 
152            const hint = pic.nextElementSibling; 
153            if (hint) { 
154                hint.style.opacity = '0'; 
155                hint.style.visibility = 'hidden'; 
156
157
158 
159        pictures.forEach(pic => { 
160            ['mouseenter', 'focus'].forEach(eventType => { 
161                pic.addEventListener(eventType, () => showHint(pic)); 
162            }); 
163            ['mouseleave', 'blur'].forEach(eventType => { 
164                pic.addEventListener(eventType, () => hideHint(pic)); 
165            }); 
166        }); 
167
168 
169 
170    // Copy promo code 
171    function copyToClipboard(promoCode) { 
172        navigator.clipboard.writeText(promoCode).then(() => { 
173        }).catch((error) => { 
174            console.error("Failed to copy promo code: ", error); 
175        }); 
176
177 
178    function showPopup() { 
179        const popup = document.getElementById('promoPopup'); 
180        if (popup) { 
181            popup.classList.add('show'); 
182            setTimeout(closePopup, 2500); 
183
184
185 
186    function closePopup() { 
187        const popup = document.getElementById('promoPopup'); 
188        if (popup) { 
189            popup.classList.remove('show'); 
190
191
192 
193    function handleCopyClick() { 
194        const promoCodeElement = document.querySelector('.offer-detailed__promo-code'); 
195        if (promoCodeElement) { 
196            const promoCode = promoCodeElement.textContent.trim(); 
197            copyToClipboard(promoCode); 
198            showPopup(); 
199 
200            const closeButton = document.getElementById('popupClose'); 
201            if (closeButton) { 
202                closeButton.addEventListener('click', closePopup); 
203                closeButton.addEventListener('keydown', (event) => { 
204                    if (event.key === 'Enter' || event.key === ' ') { 
205                        event.preventDefault(); 
206                        closePopup(); 
207
208                }); 
209
210
211
212 
213    const copyIcon = document.querySelector('.stc-icon-copy'); 
214    if (copyIcon) { 
215        copyIcon.addEventListener('click', handleCopyClick); 
216        copyIcon.addEventListener('keydown', (event) => { 
217            if (event.key === 'Enter' || event.key === ' ') { 
218                event.preventDefault(); 
219                handleCopyClick(); 
220
221        }); 
222
223</script>