UNPKG

fm-lp-factory

Version:

package created to build web ui components for FidelizarMais LP services

523 lines (455 loc) 18.7 kB
import { updateFmTemplateCss } from "../index.js"; let slideIndex = 1; let section = null; export default (component) => { css(); createCpfModal(); // Criação do modal para inserir CPF section = document.createElement("section"); section.classList.add("fm-carousel-of-awards-with-redemption", "fm-section-container", "fm-carrousel-hidden"); section.innerHTML = template .replace("%title%", component.title) .replace("%subtitle%", component.subtitle); document.querySelector("#fm-landing-page-content").appendChild(section); LoyalJS.public.services().getAllPossibleAwards() .then((listOfAwards) => { if (listOfAwards.length > 0) { section.classList.remove("fm-carrousel-hidden"); createCardImage(listOfAwards); } else throw new Error("No data for carrousel found"); }) .catch((error) => { console.log(error); }); section.querySelector('[fm-action="slidePrev"]').addEventListener("click", () => { plusSlides(-1); }); section.querySelector('[fm-action="slideNext"]').addEventListener("click", () => { plusSlides(1); }); }; const template = /*html*/ ` <div class="fm-carousel-of-awards-with-redemption-inner-container"> <div class="fm-carousel-of-awards-with-redemption-header"> <span class="fm-carousel-of-awards-with-redemption-inner-subtitle">%subtitle%</span> <span class="fm-carousel-of-awards-with-redemption-inner-title">%title%</span> </div> <div class="carousel-inner-container"> <div class="fm-carousel-control"> <span class="fm-carousel-control-btn" fm-action="slidePrev">❮</span> <span class="fm-carousel-control-btn" fm-action="slideNext">❯</span> </div> </div> </div> `; const templateCarrouselCard = /*html*/ ` <div class="fm-carousel-of-awards-with-redemption-cell fm-fade fm-carousel-hidden"> <div class="fm-carrousel-img-frame"> <img src="%cardImage"> </div> <div class="fm-carousel-of-awards-with-redemption-coupon-details"> <span title>%couponName%</span> <span couponPoints>%couponPoints%</span> </div> <div class="fm-button-container" fm-action="redeemAward" data-award='%awardData%'> <span>Resgatar</span> </div> </div> `; const createCardImage = (listOfImages) => { listOfImages.forEach((card) => { const awardData = JSON.stringify({ id: card.id, name: card.name, points: card.point, categoryAwardId: card.categoryAwardId, }); const cardTemplate = templateCarrouselCard .replace("%cardImage", card.image) .replace("%couponName%", card.name) .replace("%couponPoints%", `${card.point} pontos`) .replace("%awardData%", awardData); section.querySelector(".carousel-inner-container").insertAdjacentHTML("beforeend", cardTemplate); // Evento para abrir o modal de CPF section.querySelectorAll("[fm-action='redeemAward']").forEach((btn) => { btn.addEventListener("click", (e) => { const award = JSON.parse(e.target.closest("[fm-action='redeemAward']").dataset.award); openCpfModal(award); }); }); showSlides(slideIndex); }); }; function openCpfModal(award) { const modal = document.querySelector("#cpf-modal"); modal.style.display = "flex"; document.body.style.overflow = "hidden"; const confirmButton = modal.querySelector("#confirm-redeem"); const cpfInput = modal.querySelector("#cpf-input"); modal.querySelector("#award-name").textContent = award.name; modal.querySelector("#award-points").textContent = `${award.points} pontos`; const errorMsg = document.createElement("div"); // Para mensagens de erro errorMsg.style.color = "red"; errorMsg.style.marginTop = "5px"; cpfInput.parentNode.insertBefore(errorMsg, confirmButton); // Adiciona máscara de CPF/CNPJ cpfInput.addEventListener("input", (e) => { let value = e.target.value.replace(/\D/g, ""); // Remove tudo que não for número if (value.length <= 11) { // CPF: 000.000.000-00 value = value.replace(/^(\d{3})(\d)/, "$1.$2"); value = value.replace(/^(\d{3})\.(\d{3})(\d)/, "$1.$2.$3"); value = value.replace(/\.(\d{3})(\d)/, ".$1-$2"); } else { // CNPJ: 00.000.000/0000-00 value = value.replace(/^(\d{2})(\d)/, "$1.$2"); value = value.replace(/^(\d{2})\.(\d{3})(\d)/, "$1.$2.$3"); value = value.replace(/\.(\d{3})(\d)/, ".$1/$2"); value = value.replace(/(\d{4})(\d)/, "$1-$2"); } e.target.value = value; }); confirmButton.onclick = async () => { const cpf = cpfInput.value.replace(/\D/g, ""); // Limpa apenas números errorMsg.textContent = ""; // Limpa erros anteriores if (!cpf || (cpf.length !== 11 && cpf.length !== 14)) { errorMsg.textContent = "Por favor, insira um CPF ou CNPJ válido."; return; } confirmButton.disabled = true; confirmButton.textContent = "Aguarde..."; confirmButton.style.backgroundColor = "#ccc"; confirmButton.style.cursor = "not-allowed"; try { const response = await LoyalJS.public.services().redeemPoints({ document: cpf, awardId: award.id, cashback: false, points: award.points, categoryAwardId: award.categoryAwardId, validMember: true, type: 18, shortDescription: "Resgate", partner: window.LoyalJS.settings.partnerId, accountManager: cpf, withReturn: false, }); if (response.body.success) { modal.querySelector(".modal-content").innerHTML = ` <span id="close-modal" class="close">&times;</span> <img src="https://cdn.fidelizarmais.com/files/production/6223cfa9-54ec-4072-a27e-b500f68f40dd/landing-page/assets/imgs/icone-8.png"/> <h2>Resgate Concluído</h2> <p>${response.body.data.message}</p> <button id="copy-coupon">Copiar Cupom</button> `; const copyButton = modal.querySelector("#copy-coupon"); copyButton.addEventListener("click", () => { navigator.clipboard.writeText(response.body.data.couponCode); closeModal(); }); modal.querySelector("#close-modal").onclick = closeModal; } else { errorMsg.textContent = response.body.message || "Erro ao resgatar o prêmio."; } } catch (error) { console.error(error); errorMsg.textContent = "Erro ao realizar o resgate. Tente novamente."; } finally { confirmButton.disabled = false; confirmButton.textContent = "Confirmar"; confirmButton.style.backgroundColor = ""; confirmButton.style.cursor = "pointer"; } }; modal.querySelector("#close-modal").onclick = closeModal; } function closeModal() { const modal = document.querySelector("#cpf-modal"); modal.style.display = "none"; document.body.style.overflow = ""; // Restaura o scroll da página } function createCpfModal() { const modal = document.createElement("div"); modal.id = "cpf-modal"; modal.style.display = "none"; modal.innerHTML = ` <div class="modal-content"> <span id="close-modal" class="close">&times;</span> <img src="https://cdn.fidelizarmais.com/files/production/6223cfa9-54ec-4072-a27e-b500f68f40dd/landing-page/assets/imgs/icone-8.png"/> <h2>Confirmar Resgate</h2> <p>Ao inserir o seu <strong>CPF</strong> ou <strong>CNPJ</strong> e selecionar a opção confirmar abaixo você ira realizar o resgate do <strong>Cupom de <span id="award-name"></span></strong> por <strong><span id="award-points">.</span></strong></p> <input id="cpf-input" type="text" placeholder="CPF ou CPNJ" /> <button id="confirm-redeem">Confirmar</button> </div> `; document.body.appendChild(modal); } function plusSlides(n) { const totalSlides = document.querySelectorAll(".fm-carousel-of-awards-with-redemption-cell").length; const slidesToShow = getVisibleSlides(); // Ajusta o índice respeitando os limites if (slideIndex + n < 0) { slideIndex = 0; } else if (slideIndex + n > totalSlides - slidesToShow) { slideIndex = totalSlides - slidesToShow; } else { slideIndex += n; } showSlides(slideIndex); updateNavigationButtons(); } function showSlides(index) { const slides = document.querySelectorAll(".fm-carousel-of-awards-with-redemption-cell"); const slidesToShow = getVisibleSlides(); slides.forEach(slide => slide.classList.add("fm-carousel-hidden")); for (let i = index; i < index + slidesToShow; i++) { if (slides[i]) slides[i].classList.remove("fm-carousel-hidden"); } } function updateNavigationButtons() { const prevBtn = document.querySelector('[fm-action="slidePrev"]'); const nextBtn = document.querySelector('[fm-action="slideNext"]'); const totalSlides = document.querySelectorAll(".fm-carousel-of-awards-with-redemption-cell").length; const slidesToShow = getVisibleSlides(); prevBtn.style.opacity = slideIndex <= 0 ? "0.5" : "1"; prevBtn.style.pointerEvents = slideIndex <= 0 ? "none" : "auto"; nextBtn.style.opacity = slideIndex >= totalSlides - slidesToShow ? "0.5" : "1"; nextBtn.style.pointerEvents = slideIndex >= totalSlides - slidesToShow ? "none" : "auto"; } function getVisibleSlides() { return window.innerWidth > 1000 ? 4 : window.innerWidth > 768 ? 3 : 2; } const css = () => { updateFmTemplateCss(/*css*/ ` .fm-carousel-control-btn { opacity: 1; transition: opacity 0.3s ease; } .fm-carousel-control-btn[style*="none"] { cursor: not-allowed; } .fm-carousel-of-awards-with-redemption{ width: 100%; background: var(--fm-primary-light-color); } .fm-carousel-of-awards-with-redemption-inner-container{ padding:45px 0; } .fm-carousel-of-awards-with-redemption .fm-carousel-of-awards-with-redemption-inner-title{ font-size: 32px; margin: 0; font-weight: bold; text-align: center; } .fm-carousel-of-awards-with-redemption .fm-carousel-of-awards-with-redemption-inner-subtitle{ font-size: 1.1rem; color: var(--fm-secondary-color); } .fm-carousel-of-awards-with-redemption .fm-carousel-of-awards-with-redemption-header { display: flex; align-items: center; margin-bottom: 15px; flex-direction: column; justify-content: center; } .fm-carousel-of-awards-with-redemption .fm-carousel-of-awards-with-redemption-coupon-details{ display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 5px; margin-top: 10px; } .fm-carousel-of-awards-with-redemption-coupon-details span[title], .fm-carousel-of-awards-with-redemption-coupon-details span[couponPoints]{ margin:0 5px; } .fm-carousel-of-awards-with-redemption-coupon-details span[couponPoints]{ font-weight: bold; } .fm-carousel-of-awards-with-redemption .fm-button-container{ display: flex; justify-content: center; align-items: center; cursor: pointer; right: 0; width: 85%; background: var(--fm-primary-button-color); color: var(--fm-primary-button-text-color); border-radius: var(--fm-base-border-radius); margin: 10px auto; padding: 10px; } .fm-carousel-of-awards-with-redemption .fm-carousel-hidden, .fm-carousel-of-awards-with-redemption.fm-carrousel-hidden { display: none; } .fm-carousel-of-awards-with-redemption .carousel-inner-container { display: flex; flex-direction: row; align-items: center; justify-content: center; } @media (max-width: 768px) { .fm-carousel-of-awards-with-redemption .carousel-inner-container { overflow: hidden; width: 100%; } .fm-carousel-of-awards-with-redemption .fm-carousel-of-awards-with-redemption-inner-title { font-size: 28px; } .fm-carousel-of-awards-with-redemption .carousel-inner-container .fm-carousel-of-awards-with-redemption-cell { margin: 0 5px !important; } } .fm-carousel-of-awards-with-redemption .fm-carousel-control .fm-carousel-control-btn { padding: 2px 12px; cursor: pointer; background: var(--fm-secondary-button-color); color: var(--fm-secondary-button-text-color); border-radius: 50%; transition: all 0.6s ease; position: absolute; margin: 0 2%; } .fm-carousel-of-awards-with-redemption .fm-carousel-control .fm-carousel-control-btn[fm-action="slidePrev"] { left: 0; } .fm-carousel-of-awards-with-redemption .fm-carousel-control .fm-carousel-control-btn[fm-action="slideNext"] { right: 0; } .fm-carousel-of-awards-with-redemption .carousel-inner-container .fm-carousel-of-awards-with-redemption-cell { margin: 0 15px; padding: 15px; background: var(--fm-card-primary-background); border-radius: var(--fm-base-border-radius); } .fm-carousel-of-awards-with-redemption .carousel-inner-container .fm-carousel-of-awards-with-redemption-cell img { width: 100%; height: 100%; object-fit: cover; } .fm-carousel-of-awards-with-redemption .carousel-inner-container .fm-carousel-of-awards-with-redemption-cell .fm-carrousel-img-frame { width: 300px; height: 300px; border-radius: var(--fm-base-border-radius); transition: all .3s ease; overflow: hidden; } @media (max-width: 1100px) { .fm-carousel-of-awards-with-redemption .carousel-inner-container .fm-carousel-of-awards-with-redemption-cell .fm-carrousel-img-frame { width: 100%; height: 200px; } } @media (max-width: 768px) { .fm-carousel-of-awards-with-redemption .carousel-inner-container .fm-carousel-of-awards-with-redemption-cell .fm-carrousel-img-frame { width: 150px; } } /* Fading animation */ .fm-fade { animation-name: fm-fade-key; animation-duration: 1.5s; } @keyframes fm-fade-key { from { opacity: .4 } to { opacity: 1 } } #cpf-modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); /* Fundo semi-transparente */ display: flex; justify-content: center; align-items: center; z-index: 1000; } .modal-content { background: white; padding: 20px; border-radius: 8px; text-align: center; width: 90%; max-width: 400px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2); position: relative; animation: fadeIn 0.3s ease-in-out; } .modal-content p { text-align: justify; } @keyframes fadeIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } .close { position: absolute; top: 10px; right: 10px; font-size: 20px; cursor: pointer; color: #333; transition: color 0.2s; } .close:hover { color: #ff0000; } #cpf-input { width: calc(100% - 40px); max-width: 300px; padding: 10px; font-size: 1rem; border: 1px solid #ddd; border-radius: 5px; margin-top: 10px; } #confirm-redeem, #copy-coupon { background: #36B6FF; color: white; border: none; border-radius: 5px; padding: 12px 20px; font-size: 1rem; cursor: pointer; transition: background 0.3s; margin-top: 15px; } #confirm-redeem:hover, #copy-coupon:hover { background:rgb(40, 173, 250); } @media (max-width: 768px) { .modal-content { padding: 15px; } #cpf-input { font-size: 0.9rem; padding: 8px; } #confirm-redeem { font-size: 0.9rem; padding: 10px 15px; } } ` ); };