feat: paypal client interface
This commit is contained in:
parent
83e4bd88a8
commit
b9bd9cb491
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -4,12 +4,13 @@ import tippy from 'tippy.js';
|
||||
import 'tippy.js/dist/tippy.css';
|
||||
import shave from 'shave';
|
||||
import GhostContentAPI from '@tryghost/content-api';
|
||||
/* pyv */
|
||||
import fuzzysort from 'fuzzysort';
|
||||
/* /pyv */
|
||||
import Swiper, { FreeMode, A11y } from 'swiper';
|
||||
import 'swiper/css';
|
||||
import { isRTL, formatDate, isMobile } from './helpers';
|
||||
/* pyv */
|
||||
import fuzzysort from 'fuzzysort';
|
||||
import './paypal';
|
||||
/* /pyv */
|
||||
|
||||
$(() => {
|
||||
if (isRTL()) {
|
||||
|
86
src/js/paypal.js
Normal file
86
src/js/paypal.js
Normal file
@ -0,0 +1,86 @@
|
||||
/* pyv */
|
||||
|
||||
{
|
||||
/* <div class="paypal-cart" data-id="test-cart-id"><div class="buttons"><div class="paypal-item" data-id="youth" data-cost="10"><div class="paypal-item-name">Youth</div></div><div class="paypal-item" data-id="leader" data-cost="10"><div class="paypal-item-name">Leader</div></div></div><div class="paypal-confirmation"><span>Payment successful.</span></div><noscript><p class="javascript-required">You must enable JavaScript to checkout via PayPal.</p></noscript></div> */
|
||||
}
|
||||
|
||||
const ITEM_REMOVE = `<div class="paypal-item-remove m-button primary focusable" title="-1" role="button" tabindex="0"><i class="icon-minus"></i></div>`,
|
||||
ITEM_ADD = `<div class="paypal-item-add m-button primary focusable" title="+1" role="button" tabindex="0"><i class="icon-plus"></i></div>`,
|
||||
CHECKOUT = `<div class="paypal-order">
|
||||
<div class="paypal-order-total"></div>
|
||||
<div class="paypal-order-checkout m-button primary focusable" role="button" tabindex="0"><span>Checkout with</span> <span title="PayPal" class="paypal-checkout-logo"></span></div>
|
||||
</div>`.replace(/\s+/g, ' ');
|
||||
|
||||
const createElement = (html) => {
|
||||
const tmpl = document.createElement('template');
|
||||
tmpl.innerHTML = html.trim();
|
||||
return tmpl.content.firstChild;
|
||||
},
|
||||
getDataAttrAsInt = (elem, attr) => {
|
||||
let value = parseInt(elem.dataset[attr]);
|
||||
if (isNaN(value)) value = 0;
|
||||
return value;
|
||||
},
|
||||
onClick = (elem, handler) => {
|
||||
elem.addEventListener('click', handler);
|
||||
elem.addEventListener('keydown', (event) => {
|
||||
if (['Space', 'Enter'].includes(event.code)) handler();
|
||||
});
|
||||
};
|
||||
|
||||
const hydrateCart = (cart) => {
|
||||
const { id: cartId } = cart.dataset,
|
||||
order = createElement(CHECKOUT),
|
||||
items = [...cart.querySelectorAll('.paypal-item')],
|
||||
total = order.querySelector('.paypal-order-total'),
|
||||
checkout = order.querySelector('.paypal-order-checkout'),
|
||||
confirmation = cart.querySelector('.paypal-confirmation');
|
||||
if (confirmation) confirmation.before(order);
|
||||
else cart.append(order);
|
||||
|
||||
const getCount = (item) => getDataAttrAsInt(item, 'count'),
|
||||
getCost = (item) => getDataAttrAsInt(item, 'cost'),
|
||||
getTotal = () =>
|
||||
items.reduce((charge, item) => {
|
||||
return charge + getCount(item) * getCost(item);
|
||||
}, 0);
|
||||
|
||||
const updateTotal = () => (total.innerText = `$${getTotal()}`),
|
||||
updateCount = (item, increment) => {
|
||||
item.dataset.count = Math.max(getCount(item) + increment, 0);
|
||||
updateTotal();
|
||||
};
|
||||
updateTotal();
|
||||
|
||||
const showConfirmation = () => {
|
||||
if (!confirmation) return;
|
||||
confirmation.style.setProperty('display', 'flex');
|
||||
};
|
||||
|
||||
for (const item of items) {
|
||||
const add = createElement(ITEM_ADD),
|
||||
remove = createElement(ITEM_REMOVE);
|
||||
onClick(add, () => updateCount(item, +1));
|
||||
onClick(remove, () => updateCount(item, -1));
|
||||
item.append(remove, add);
|
||||
}
|
||||
|
||||
onClick(checkout, () => {
|
||||
console.log({
|
||||
cart: cartId,
|
||||
items: items.map((item) => {
|
||||
return {
|
||||
id: item.dataset.id,
|
||||
count: getCount(item),
|
||||
};
|
||||
}),
|
||||
});
|
||||
showConfirmation();
|
||||
});
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const carts = document.querySelectorAll('.paypal-cart');
|
||||
for (const cart of carts) hydrateCart(cart);
|
||||
});
|
||||
/* /pyv */
|
@ -1,3 +1,4 @@
|
||||
html:not([data-theme]),
|
||||
[data-theme="light"] {
|
||||
--background-color: #fff;
|
||||
--primary-foreground-color: #4a4a4a;
|
||||
|
@ -27,6 +27,8 @@
|
||||
}
|
||||
.buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 24px;
|
||||
}
|
||||
}
|
||||
@ -49,20 +51,20 @@
|
||||
.columns > * > .kg-embed-card + .kg-embed-card {
|
||||
margin-top: -50px;
|
||||
}
|
||||
.buttons .kg-button-card a {
|
||||
.buttons {
|
||||
.kg-button-card a {
|
||||
width: 100%;
|
||||
}
|
||||
@media screen and (max-width: $break-large) {
|
||||
& > *:not(:last-child) {
|
||||
margin-bottom: 14px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.kg-button-card {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
/* default to white nav text + icons for contrast until theme loads */
|
||||
html:not([data-theme]) {
|
||||
--toggle-darkmode-button-display-moon: none;
|
||||
--toggle-darkmode-button-display-sun: block;
|
||||
--titles-color: white;
|
||||
}
|
||||
|
||||
/* transparent nav on homepage until scroll */
|
||||
.home-template {
|
||||
.in-mobile-topbar {
|
||||
@ -133,7 +135,7 @@ body:not(.home-template) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width: 48rem) {
|
||||
@media only screen and (max-width: $break-medium) {
|
||||
.m-nav__left .m-secondary-menu + .more {
|
||||
display: none;
|
||||
}
|
||||
@ -247,12 +249,12 @@ body:not(.home-template) {
|
||||
margin: 0 max(calc(50% - 430px), 0px);
|
||||
}
|
||||
}
|
||||
@media only screen and (min-width: 35.5rem) and (max-width: 64rem) {
|
||||
@media only screen and (min-width: $break-small) and (max-width: $break-large) {
|
||||
.l-grid > :nth-child(2n + 1 of .m-article-card):last-child {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width: 48rem) {
|
||||
@media only screen and (max-width: $break-medium) {
|
||||
.l-post-content + .l-grid.centered {
|
||||
margin-top: 40px;
|
||||
}
|
||||
@ -294,8 +296,12 @@ body:not(.home-template) {
|
||||
.icon-minus {
|
||||
mask: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLW1pbnVzIj48cGF0aCBkPSJNNSAxMmgxNCIvPjwvc3ZnPg==);
|
||||
}
|
||||
.icon-check-circle {
|
||||
mask: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGNsYXNzPSJsdWNpZGUgbHVjaWRlLWNoZWNrLWNpcmNsZSI+PHBhdGggZD0iTTIyIDExLjA4VjEyYTEwIDEwIDAgMSAxLTUuOTMtOS4xNCIvPjxwb2x5bGluZSBwb2ludHM9IjIyIDQgMTIgMTQuMDEgOSAxMS4wMSIvPjwvc3ZnPg==);
|
||||
}
|
||||
.icon-plus,
|
||||
.icon-minus {
|
||||
.icon-minus,
|
||||
.icon-check-circle {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
mask-repeat: no-repeat;
|
||||
@ -305,19 +311,45 @@ body:not(.home-template) {
|
||||
}
|
||||
|
||||
/* payment buttons */
|
||||
.paypal-item {
|
||||
.paypal-cart {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
.paypal-item,
|
||||
.paypal-confirmation {
|
||||
align-items: center;
|
||||
border-radius: 5px;
|
||||
border: 1px solid rgb(124 139 154/25%);
|
||||
display: flex;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.2px;
|
||||
line-height: 1;
|
||||
width: 100%;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
.paypal-item {
|
||||
border: 1px solid rgb(124 139 154/25%);
|
||||
margin-bottom: 14px;
|
||||
&::before {
|
||||
content: " ($" attr(data-cost) ") x " attr(data-count);
|
||||
padding: 13px 25px 13px 0;
|
||||
white-space: pre;
|
||||
order: 1;
|
||||
}
|
||||
&:is([data-count="0"], :not([data-count])) {
|
||||
/* prevent ordering <0 items */
|
||||
&::before {
|
||||
content: " ($" attr(data-cost) ") x 0";
|
||||
}
|
||||
.paypal-item-remove {
|
||||
pointer-events: none;
|
||||
cursor: default;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
.paypal-item-name {
|
||||
padding: 13px 25px;
|
||||
padding: 13px 0 13px 25px;
|
||||
order: 0;
|
||||
}
|
||||
.paypal-item-remove {
|
||||
margin-left: auto;
|
||||
@ -334,40 +366,86 @@ body:not(.home-template) {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
&[disabled],
|
||||
&[aria-disabled="true"] {
|
||||
pointer-events: none;
|
||||
opacity: 0.6;
|
||||
order: 2;
|
||||
}
|
||||
}
|
||||
.paypal-order {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 14px;
|
||||
.paypal-order-total {
|
||||
margin: 0 0 0 auto;
|
||||
@media screen and (min-width: 24rem) and (max-width: $break-small) {
|
||||
margin: 0 auto 0 0;
|
||||
}
|
||||
.paypal-checkout-btn {
|
||||
font-weight: 600;
|
||||
font-size: 2rem;
|
||||
}
|
||||
.kg-button-card a .paypal-btn {
|
||||
}
|
||||
.paypal-order-checkout {
|
||||
width: 100%;
|
||||
@media screen and (min-width: 24rem) {
|
||||
width: auto;
|
||||
}
|
||||
display: flex !important;
|
||||
align-items: normal !important;
|
||||
text-decoration: none !important;
|
||||
&,
|
||||
.paypal-checkout-logo {
|
||||
transition: all 0.25s cubic-bezier(0.02, 0.01, 0.47, 1) !important;
|
||||
}
|
||||
&:hover {
|
||||
color: $white !important;
|
||||
}
|
||||
:first-child {
|
||||
margin-right: 13px;
|
||||
}
|
||||
.paypal-checkout-logo {
|
||||
height: 42px;
|
||||
width: 115.94px;
|
||||
display: inline-block;
|
||||
padding: 11px 23px 11px 13px;
|
||||
margin: -13px -26px -15px 13px;
|
||||
background-color: #fff;
|
||||
margin: -13px -26px -15px auto;
|
||||
background-color: $white;
|
||||
background-image: url(https://www.paypalobjects.com/webstatic/en_US/i/buttons/PP_logo_h_150x38.png);
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-origin: content-box;
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
transition: all 0.25s cubic-bezier(0.02, 0.01, 0.47, 1);
|
||||
}
|
||||
.kg-button-card a:focus .paypal-btn {
|
||||
&:focus .paypal-checkout-logo {
|
||||
width: 113.94px;
|
||||
height: 38px;
|
||||
padding-top: 9px;
|
||||
padding-bottom: 9px;
|
||||
padding-right: 21px;
|
||||
margin-right: -24px;
|
||||
margin-bottom: -13px;
|
||||
margin-top: -11px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
.paypal-confirmation {
|
||||
display: none;
|
||||
color: rgba(52, 183, 67, 0.94);
|
||||
background: rgba(52, 183, 67, 0.16);
|
||||
margin-top: 14px;
|
||||
&::before {
|
||||
content: "";
|
||||
font-size: 20px;
|
||||
margin: auto 0 auto 25px;
|
||||
@extend .icon-check-circle;
|
||||
}
|
||||
span {
|
||||
padding: 13px 25px;
|
||||
}
|
||||
}
|
||||
.javascript-required {
|
||||
color: #ff4a4a;
|
||||
font-size: 1rem !important;
|
||||
}
|
||||
|
||||
/* page cover sizing & readability (inc. uncropped post covers) */
|
||||
.m-hero-title.bigger,
|
||||
|
Loading…
Reference in New Issue
Block a user