Skip to content

Instantly share code, notes, and snippets.

@ronaldroe
Last active January 11, 2021 00:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ronaldroe/11d99e1fb81b40d5e54572d3545bb998 to your computer and use it in GitHub Desktop.
Save ronaldroe/11d99e1fb81b40d5e54572d3545bb998 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<title>Delivery/Event Dates | Flower Moxie</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/flatpickr/4.6.6/flatpickr.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.17.1/axios.min.js"></script>
<script type="text/javascript" src="supplies.js"></script>
<link rel="stylesheet" href="supply.css" type="text/css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/flatpickr/4.6.6/flatpickr.min.css">
<style>
.flatpickr-day.flatpickr-disabled,
.flatpickr-day.flatpickr-disabled:hover,
.flatpickr-day.prevMonthDay,
.flatpickr-day.nextMonthDay,
.flatpickr-day.notAllowed,
.flatpickr-day.notAllowed.prevMonthDay,
.flatpickr-day.notAllowed.nextMonthDay{
color: #999999;
}
.flatpickr-day{
color: #000;
font-weight: 600;
}
</style>
</head>
<body>
<img src="https://cdn.shopify.com/s/files/1/1204/3320/files/logo-03_x280.png" class="logo" />
<form>
<div class="panel shown" data-panel-num="0">
<h1>Hey, {{ first_name }}! We’re shipping your supplies and dried goodies EARLY because no one likes backorders.</h1>
<p>
Please verify a few details to ensure your floral supplies, vases, and dried flowers arrive at your current address, not your wedding day address (as many brides provide an Airbnb address for their flowers).
If these addresses happen to be the same, just re-enter the info again so we can sleep at night.
</p>
<button type="button" class="nav next">Next</button>
</div>
<div class="panel" data-panel-num="1">
<label for="fake_delivery_date"><u>Floral</u> Delivery date (Recommend 3 days prior to event):</label><br />
<input id="fake_delivery_date" class="deliverdate" type="date" />
<label for="fake_event_date">Event date:</label><br />
<input id="fake_event_date" class="evtdate" type="date" />
<input type="date" id="delivery_date" name="delivery_date" />
<input type="date" id="event_date" name="event_date" />
<button type="button" class="nav prev">Back</button>
<button type="button" class="nav next">Next</button>
</div>
<div class="panel" data-panel-num="2">
<button type="button" class="nav prev">Back</button>
<button type="button" class="nav next">Next</button>
</div>
<div class="panel" data-panel-num="3">
<button type="button" class="copy">Use My Floral Address</button>
<button type="button" class="nav prev">Back</button>
<button type="button" class="save">Save</button>
</div>
</form>
<div class="messages">
<div class="message success">Awesome! We'll get to work on it! <span class="thanks"></span></div>
<div class="message error">Oh, no! Something went wrong. If this keeps happening, <a href="https://flowermoxie.com/pages/contact-us">contact us</a> to update your dates.</div>
<div class="close">&Cross;</div>
</div>
<div class="loading"><div class="inner">&#128525;</div></div>
</body>
</html>
let order_data, panels, nav_buttons, save_button, copy_button;
(async () => {
init();
})();
async function init(){
order_data = await getOrderData();
let windowLoad = window.setInterval(() => {
if(document.readyState !== 'complete' || typeof order_data === 'undefined') return;
panels = document.querySelectorAll('.panel');
nav_buttons = document.querySelectorAll('.nav');
save_button = document.querySelector('.save');
copy_button = document.querySelector('.copy');
addNavButtonListeners();
parseShortcodes(panels);
window.clearInterval(windowLoad);
}, 50);
}
function addNavButtonListeners() {
Array.from(nav_buttons).forEach(button => {
console.log(nav_buttons);
button.addEventListener('click', e => {
console.log(button);
e.preventDefault();
if(button.classList.contains('next')){
switchPanel();
return;
}
switchPanel(-1);
});
});
}
function switchPanel(step = 1){
let currentPanel = document.querySelector('.shown');
currentPanel.classList.remove('shown');
currentPanel = parseInt(currentPanel.getAttribute('data-panel-num'));
nextPanel = (currentPanel + step) % panels.length;
nextPanel = document.querySelector(`[data-panel-num="${nextPanel}"`);
nextPanel.classList.add('shown');
}
function parseShortcodes(elems){
Array.from(elems).forEach(elem => {
if(elem.childElementCount > 0) parseShortcodes(elem.children);
elem.innerHTML = getShortcodesFromString(elem.innerHTML);
});
}
function getShortcodesFromString(str){
let matches = str.match(/{{[\s|]+(\w+)[\s|]+}}/g);
if(matches !== null && matches.length > 0) matches.forEach(match => str = str.replace(match, order_data[match.replace(/{{\s+|/, '').replace(/[\s+|]}}/, '')]));
return str;
}
async function getOrderData(){
return await fetch(`${window.location.protocol}//${window.location.hostname}:${window.location.port}/lookup`, {
method: 'POST',
headers: {'content-type': 'application/json'},
body: JSON.stringify({order_num: `#${getUrlParameter('order_num')}`})
})
.then(res => res.json())
.then(data => data);
}
function setUpDatePicker(){
/****** Date picker code ******/
const holidays = [...allFederalHolidaysForYear(new Date().getFullYear()), ...allFederalHolidaysForYear(new Date().getFullYear() + 1)];
let holidayStrings = [];
holidays.forEach(holiday => holidayStrings.push(holiday.dateString));
let deliverOpts = {
disable: [
function (date) {
return (date.getDay() === 0 || date.getDay() === 6);
},
...holidayStrings
],
minDate: formatDate(new Date().addDays(9)),
onChange: function () {
// let evtDate = formatDate(new Date(this.selectedDates).addDays(3));
// evt.set('minDate', evtDate);
let realDelDate = document.querySelector('#delivery_date');
realDelDate.value = formatDate(new Date(this.selectedDates));
},
disableMobile: true
};
const del = flatpickr('#fake_delivery_date', deliverOpts); /* global flatpickr */
let eventOpts = {
minDate: formatDate(new Date().addDays(9)),
onChange: function () {
let realEvtDate = document.querySelector('#event_date');
realEvtDate.value = formatDate(new Date(this.selectedDates));
},
disableMobile: true
};
const evt = flatpickr('#fake_event_date', eventOpts);
}
function getUrlParameter(name) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
let regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
let results = regex.exec(window.location.search);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
}
function formatDate(date) {
let month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
let dayOfMonth = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
return `${date.getFullYear()}-${month}-${dayOfMonth}`;
}
Date.prototype.addDays = function (days) {
var date = new Date(this.valueOf());
date.setDate(date.getDate() + days);
return date;
}
function getNthDayOf(n, day, month, year) {
const firstOfMonth = new Date(Date.parse(`${month}/1/${year} GMT`));
let dayOffset = firstOfMonth.getUTCDay() - day;
if (dayOffset > 0) {
dayOffset = 7 - dayOffset;
} else {
dayOffset = -dayOffset;
}
const initialDay = firstOfMonth.getUTCDate() + dayOffset;
const finalDay = initialDay + 7 * (n - 1);
return new Date(Date.parse(`${month}/${finalDay}/${year} GMT`));
}
function getLastDayOf(day, month, year) {
const firstOfDay = getNthDayOf(1, day, month, year).getUTCDate();
const daysInMonth = new Date(year, month, 0).getUTCDate() - 7;
let lastOfDay = firstOfDay;
while (lastOfDay <= daysInMonth) {
lastOfDay += 7;
}
return new Date(Date.parse(`${month}/${lastOfDay}/${year} GMT`));
}
function allFederalHolidaysForYear(year = new Date().getFullYear(), { shiftSaturdayHolidays = true, shiftSundayHolidays = true } = {}) {
const holidays = [];
// New Year's Day
holidays.push({
name: `New Year's Day`,
date: new Date(Date.parse(`1/1/${year} GMT`))
});
// Birthday of Martin Luther King, Jr.
// Third Monday of January; fun fact: actual birthday is January 15
holidays.push({
name: `Birthday of Martin Luther King, Jr.`,
date: getNthDayOf(3, 1, 1, year)
});
// Washington's Birthday
// Third Monday of February; fun fact: actual birthday is February 22
// Fun fact 2: officially "Washington's Birthday," not "President's Day"
holidays.push({
name: `Washington's Birthday`,
date: getNthDayOf(3, 1, 2, year)
});
// Memorial Day
// Last Monday of May
holidays.push({
name: `Memorial Day`,
date: getLastDayOf(1, 5, year)
});
// Independence Day
holidays.push({
name: `Independence Day`,
date: new Date(Date.parse(`7/4/${year} GMT`))
});
// Labor Day
// First Monday in September
holidays.push({
name: `Labor Day`,
date: getNthDayOf(1, 1, 9, year)
});
// Columbus Day
// Second Monday in October
holidays.push({
name: `Columbus Day`,
date: getNthDayOf(2, 1, 10, year)
});
// Thanksgiving Day
// Fourth Thursday of November
holidays.push({
name: `Thanksgiving Day`,
date: getNthDayOf(4, 4, 11, year)
});
// Christmas Day
holidays.push({
name: `Christmas Day`,
date: new Date(Date.parse(`12/25/${year} GMT`))
});
if (shiftSaturdayHolidays || shiftSundayHolidays) {
holidays.forEach(holiday => {
// Allow the holiday objects to be modified inside this loop:
/* eslint-disable no-param-reassign */
const dow = holiday.date.getUTCDay();
if (dow === 0 && shiftSundayHolidays) {
// Actual holiday falls on Sunday. Shift the observed date forward to
// Monday.
holiday.date = new Date(
Date.UTC(
holiday.date.getUTCFullYear(),
holiday.date.getUTCMonth(),
holiday.date.getUTCDate() + 1
)
);
} else if (dow === 6 && shiftSaturdayHolidays) {
// Actual holiday falls on Saturday. Shift the observed date backward
// to Friday.
holiday.date = new Date(
Date.UTC(
holiday.date.getUTCFullYear(),
holiday.date.getUTCMonth(),
holiday.date.getUTCDate() - 1
)
);
}
holiday.dateString = `${holiday.date.getUTCFullYear()}-${holiday.date.getUTCMonth() +
1}-${holiday.date.getUTCDate()}`;
});
}
return holidays;
}
@import url("https://fonts.googleapis.com/css?family=Raleway:100|400");
* {
margin: 0;
padding: 0;
box-sizing: border-box; }
body {
font-family: 'Raleway', sans-serif;
font-weight: bold; }
a {
color: #ad386e; }
h1, h3 {
padding-left: 35vw;
margin-bottom: 2vh; }
@media (orientation: portrait) {
h1, h3 {
margin-bottom: 2vw;
padding-left: 10vw; } }
h1 {
font-size: 6vh; }
@media (orientation: portrait) {
h1 {
font-size: 6vw; } }
h3 {
font-size: 4vh;
padding-right: 35vw; }
@media (orientation: portrait) {
h3 {
font-size: 4vw;
padding-right: 10vw; } }
.messages {
background-color: rgba(80, 80, 80, 0.5);
width: 100vw;
height: 100vh;
text-align: center;
position: fixed;
top: 0;
left: 0;
display: none; }
.messages .message {
background-color: #fff;
width: 30vw;
padding: 1.5vh 1vw;
position: absolute;
left: 35vw;
top: 15vh;
display: none;
border-radius: 0.5vw;
font-size: 2vh;
line-height: 1.75; }
@media (orientation: portrait) {
.messages .message {
border-radius: 0.5vh;
font-size: 4vw;
width: 80vw;
left: 10vw; } }
.messages .close {
background-color: #fff;
position: absolute;
left: calc(65vw - 1.5vh);
top: 13.5vh;
width: 3vh;
height: 3vh;
font-size: 1.5vw;
line-height: 2.5vh;
text-align: center;
color: rgba(0, 0, 0, 0.675);
border: 2px solid rgba(64, 64, 64, 0.75);
border-radius: 50%;
font-weight: bold;
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
cursor: pointer;
user-select: none; }
@media (orientation: portrait) {
.messages .close {
font-size: 1.75vh;
height: 3vw;
width: 3vw;
left: 88.5vw;
top: calc(15vh - 1.5vw);
line-height: 2.5vw; } }
.logo {
width: 30vw;
position: relative;
left: 35vw;
top: 2vh;
margin-bottom: 10vh; }
@media (orientation: portrait) {
.logo {
margin-bottom: 10vw; } }
form {
width: 30vw;
min-height: 10vh;
margin-top: 5vh;
padding: 1vh 1vw;
position: relative;
left: 35vw;
border-radius: 0.5vw;
border: 1px solid rgba(128, 128, 128, 0.5); }
@media (orientation: portrait) {
form {
width: 80vw;
left: 10vw; } }
form label {
font-size: 2.5vh;
display: block;
margin-bottom: 1vh; }
@media (orientation: portrait) {
form label {
text-align: center;
font-size: 4.5vw;
margin-bottom: 2.5vw; } }
form input {
display: block;
margin-bottom: 2vh;
font-family: 'Raleway', sans-serif;
font-size: 2vh;
position: relative;
left: 5%;
padding: 1vh;
border-radius: 0.33vw; }
@media (orientation: portrait) {
form input {
text-align: center;
width: 90%;
margin-bottom: 3.5vw;
font-size: 4vw;
padding: 2vw; } }
form button {
background-color: #ad386e;
border: none;
border-radius: 0.33vw;
box-shadow: 0.25vw 0.25vw 0 #d378a2;
font-size: 2vh;
padding: 1vh;
color: white;
transition: all 0.2s ease-in-out;
text-transform: uppercase; }
form button:active {
box-shadow: none;
transform: translate(0.25vw, 0.25vw);
transition: all 0.2s ease-in-out; }
@media (orientation: portrait) {
form button {
padding: 2vw;
font-size: 4vw;
margin-top: 1vw;
margin-bottom: 1vw;
position: relative;
left: 5%;
width: 90%; } }
.loading {
background-color: rgba(0, 0, 0, 0.65);
font-size: 8vw;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
display: none; }
.loading.shown {
display: block; }
.loading .inner {
position: absolute;
left: calc(50% - 5vw);
top: calc(50% - 5vw);
text-align: center;
animation: spin 1.75s linear infinite;
transform-origin: center center; }
@keyframes spin {
0% {
transform: rotate(0deg); }
100% {
transform: rotate(360deg); } }
#delivery_date, #event_date {
visibility: hidden;
height: 0;
width: 0; }
h1, h3 {
padding-left: 0; }
h1 {
font-size: 4vh; }
p {
font-size: 2.5vh;
margin-bottom: 2vh; }
form {
width: 80vw;
left: 10vw;
border: none; }
form .prev {
background-color: #386ead;
box-shadow: 0.25vw 0.25vw 0 #78a2d3; }
form .next {
background-color: #6ead38;
box-shadow: 0.25vw 0.25vw 0 #a2d378; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment