-
-
Save LaurenceLeech/2669a3966ce00c3747fe1858199a48a0 to your computer and use it in GitHub Desktop.
Rivo x Skio example code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<style> | |
:root { | |
/* Text color for buttons, links, and code containers; contrasts well with light backgrounds */ | |
--primary-dark: #000000; | |
/* Background color for copy button and text color for dark backgrounds; ensures legibility */ | |
--primary-light: #ffffff; | |
/* Border color for the main container and buttons; provides a subtle, defining edge */ | |
--border-color: #eaeaea; | |
/* Background color for skeleton placeholders and reward items; highlights distinct sections */ | |
--background-accent: #f0f0f0; | |
/* Text color for reward items; softer contrast than primary text color */ | |
--secondary-text: #6d7278; | |
} | |
/* Styling for the main container */ | |
.rivo-container { | |
border: 1px solid var(--border-color); | |
padding: 40px; | |
margin: 5px; | |
margin-bottom: 30px; | |
border-radius: 25px; | |
} | |
/* Styling for the button */ | |
button.rivo-redeem-points { | |
background: var(--primary-dark); | |
color: var(--primary-light); | |
padding: 10px 15px 10px 15px; | |
border: 0; | |
cursor: pointer; | |
font-weight: 600; | |
border-radius: 50px; | |
} | |
/* Styling for the skeleton placeholder */ | |
.skeleton-placeholder { | |
display: flex; | |
flex-direction: column; | |
justify-content: center; | |
align-items: center; | |
height: 200px; | |
background-color: var(--background-accent); | |
border-radius: 8px; | |
margin: 5px; | |
} | |
/* Styling for points container within the main container */ | |
.rivo-points-container { | |
margin: 10px 20px 20px 0px; | |
} | |
/* Styling for the subscription instruction copy */ | |
#subscription-instruction-msg { | |
font-size: small; | |
color: var(--primary-dark); | |
} | |
/* Styling for links within the points container */ | |
.rivo-points-container a { | |
font-size: small; | |
text-decoration: underline !important; | |
text-decoration-color: var(--primary-dark); | |
} | |
/* Styling for the rewards list */ | |
#rewards-list { | |
list-style-type: none; | |
padding: 0; | |
} | |
/* Styling for each reward item in the list */ | |
.reward-item { | |
margin-bottom: 10px; | |
padding: 10px 20px 10px 20px; | |
background: var(--background-accent); | |
border-radius: 0px; | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
} | |
/* Styling for text within each reward item */ | |
.reward-item span { | |
margin-right: 10px; | |
font-family: avenir next; | |
font-weight: 500; | |
letter-spacing: 0px; | |
width: 180px; | |
color: var(--secondary-text); | |
} | |
/* Styling for the code container in each reward item */ | |
.code-container { | |
padding: 5px; | |
display: inline-block; | |
margin-right: 10px; | |
width: 180px; | |
font-weight: bold; | |
color: var(--primary-dark); | |
font-size: 16px; | |
font-family: monospace; | |
text-align: center; | |
overflow: hidden; | |
white-space: nowrap; | |
text-overflow: ellipsis; | |
} | |
/* Styling for the copy reward button */ | |
.copy-reward-button { | |
background-color: var(--primary-light); | |
color: var(--primary-dark); | |
font-size: 12px; | |
font-family: avenir next; | |
font-weight: 500; | |
padding: 10px 15px; | |
border: 1px solid var(--border-color); | |
border-radius: 30px; | |
cursor: pointer; | |
min-width: 80px; | |
} | |
/* Styling for the copy reward button on hover */ | |
.copy-reward-button:hover { | |
opacity: 80%; | |
} | |
/* Styling for the paragraphs */ | |
.points-balance { | |
font-size: 24px; | |
font-weight: 500; | |
letter-spacing: 0px; | |
} | |
.rivo-points-balance { | |
font-weight: bold; | |
} | |
.rivo-h3 { | |
font-size: 18px; | |
font-weight: 500; | |
letter-spacing: 0px; | |
} | |
</style> | |
<!-- Skeleton Placeholder for loading state --> | |
<div class="skeleton-loader" id="skeleton-placeholder"> | |
</div> | |
<!-- Main container for loyalty program information --> | |
<div class="rivo-container" id="rivo-container" style="display: none;"> | |
<!-- Points container displaying user's points balance --> | |
<div class="rivo-points-container"> | |
<h2 class="points-balance"> | |
<span id="prefix">You have </span> | |
<span class="rivo-points-balance"></span> | |
<span id="suffix"> points</span> | |
</h2> | |
</div> | |
<hr class="SubscriptionDivider-sc-14q967r-0 iJvDbM" style="margin: 15px 0px;"> | |
<!-- Container for available rewards --> | |
<div class="rivo-rewards-container"> | |
<h3 class="rivo-h3">Available Rewards</h3> | |
<p id="no-rewards-msg" style="display: none;">You have no rewards available.</p> | |
<p id="subscription-instruction-msg" style="display: none;"> | |
Copy your code and apply it to your next subscription. | |
</p> | |
<ul id="rewards-list" style="display: none;"></ul> | |
<hr class="SubscriptionDivider-sc-14q967r-0 iJvDbM" style="margin: 15px 0px;"> | |
<a href="/pages/loyalty-program" target="_blank"> | |
<button class="rivo-redeem-points">View my Loyalty profile</button> | |
</a> | |
</div> | |
</div> | |
<script type="text/javascript"> | |
// JavaScript to handle the loyalty program functionality | |
// Check if RivoJS is already loaded | |
if (window.RivoJS) { | |
initializeLoyaltyProgram(); | |
} else { | |
// Listen for the RivoJS loaded event | |
document.addEventListener("rivo-js-loaded", function () { | |
initializeLoyaltyProgram(); | |
}); | |
} | |
// Function to initialize the loyalty program | |
function initializeLoyaltyProgram() { | |
console.log("RivoJS loaded and ready to use"); | |
// Hide the skeleton and show the main container after a delay | |
setTimeout(function () { | |
document.getElementById('skeleton-placeholder').style.display = 'none'; | |
document.getElementById('rivo-container').style.display = 'block'; | |
}, 2500); | |
// Function to format numbers with commas | |
function formatNumberWithCommas(number) { | |
if (!isNaN(number) && number !== null && number !== '') { | |
return Number(number).toLocaleString(); | |
} | |
return number; | |
} | |
// Fetch customer details and update points display or show login message | |
RivoJS.getCustomerDetails().then(function (resp) { | |
if (resp && typeof resp.points_tally !== 'undefined') { | |
let pointsSpan = document.querySelector('.rivo-points-balance'); | |
pointsSpan.textContent = formatNumberWithCommas(resp.points_tally); | |
} else { | |
const pointsBalance = document.querySelector('.points-balance'); | |
pointsBalance.style.display = 'none'; | |
pointsBalance.classList.add('hidden'); | |
const loginMessageDiv = document.createElement('div'); | |
loginMessageDiv.innerHTML = 'Log in to your <a href="/account" target="_blank">store account</a> to view your reward details'; | |
loginMessageDiv.classList.add('rivo-login-message'); // Add a class to the new div (replace 'login-message' with your actual class name) | |
document.querySelector('.rivo-points-container').appendChild(loginMessageDiv); | |
} | |
}).catch(function (error) { | |
console.error('Error fetching customer details:', error); | |
const pointsBalance = document.querySelector('.points-balance'); | |
pointsBalance.style.display = 'none'; | |
pointsBalance.classList.add('hidden'); | |
const loginMessageDiv = document.createElement('div'); | |
loginMessageDiv.innerHTML = 'Log in to your <a href="/account" target="_blank">store account</a> to view your reward details'; | |
loginMessageDiv.classList.add('rivo-login-message'); | |
document.querySelector('.rivo-points-container').appendChild(loginMessageDiv); | |
}); | |
// Fetch customer points purchases and display rewards | |
RivoJS.getCustomerPointsPurchases().then(function (resp) { | |
console.log(resp); | |
const rewards = resp.points_purchases; | |
rewards.sort((a, b) => new Date(b.applied_at) - new Date(a.applied_at)); | |
const recentRewards = rewards.slice(0, 2); | |
const rewardsList = document.getElementById('rewards-list'); | |
const noRewardsMsg = document.getElementById('no-rewards-msg'); | |
const subscriptionInstructionMsg = document.getElementById('subscription-instruction-msg'); | |
if (recentRewards.length === 0) { | |
noRewardsMsg.style.display = 'block'; | |
subscriptionInstructionMsg.style.display = 'none'; | |
} else { | |
recentRewards.forEach(reward => { | |
const listItem = document.createElement('li'); | |
listItem.classList.add('reward-item'); | |
const nameSpan = document.createElement('span'); | |
nameSpan.textContent = reward.name; | |
listItem.appendChild(nameSpan); | |
const codeContainer = document.createElement('div'); | |
codeContainer.classList.add('code-container'); | |
codeContainer.textContent = reward.code; | |
listItem.appendChild(codeContainer); | |
const copyButton = document.createElement('button'); | |
copyButton.textContent = 'Copy'; | |
copyButton.classList.add('copy-reward-button'); | |
copyButton.onclick = function () { | |
navigator.clipboard.writeText(reward.code).then(() => { | |
// Change the button text to "Copied!" and revert after 3 seconds | |
copyButton.textContent = 'Copied!'; | |
setTimeout(() => { | |
copyButton.textContent = 'Copy'; | |
}, 3000); | |
}, err => { | |
console.error('Error copying text:', err); | |
}); | |
}; | |
listItem.appendChild(copyButton); | |
rewardsList.appendChild(listItem); | |
}); | |
rewardsList.style.display = 'block'; | |
subscriptionInstructionMsg.style.display = 'block'; | |
} | |
}); | |
} | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment