mirror of
https://github.com/chinchang/web-maker.git
synced 2025-07-25 16:01:14 +02:00
get checkout ready
This commit is contained in:
15
package-lock.json
generated
15
package-lock.json
generated
@@ -11,6 +11,7 @@
|
||||
"dependencies": {
|
||||
"@emmetio/codemirror-plugin": "^0.5.4",
|
||||
"@lingui/react": "^2.8.3",
|
||||
"canvas-confetti": "^1.9.2",
|
||||
"code-blast-codemirror": "chinchang/code-blast-codemirror#web-maker",
|
||||
"codemirror": "^5.37.0",
|
||||
"copy-webpack-plugin": "^4.5.1",
|
||||
@@ -7095,6 +7096,15 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/canvas-confetti": {
|
||||
"version": "1.9.2",
|
||||
"resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.2.tgz",
|
||||
"integrity": "sha512-6Xi7aHHzKwxZsem4mCKoqP6YwUG3HamaHHAlz1hTNQPCqXhARFpSXnkC9TWlahHY5CG6hSL5XexNjxK8irVErg==",
|
||||
"funding": {
|
||||
"type": "donate",
|
||||
"url": "https://www.paypal.me/kirilvatev"
|
||||
}
|
||||
},
|
||||
"node_modules/capture-exit": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz",
|
||||
@@ -34038,6 +34048,11 @@
|
||||
"integrity": "sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ==",
|
||||
"dev": true
|
||||
},
|
||||
"canvas-confetti": {
|
||||
"version": "1.9.2",
|
||||
"resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.2.tgz",
|
||||
"integrity": "sha512-6Xi7aHHzKwxZsem4mCKoqP6YwUG3HamaHHAlz1hTNQPCqXhARFpSXnkC9TWlahHY5CG6hSL5XexNjxK8irVErg=="
|
||||
},
|
||||
"capture-exit": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz",
|
||||
|
@@ -71,6 +71,7 @@
|
||||
"dependencies": {
|
||||
"@emmetio/codemirror-plugin": "^0.5.4",
|
||||
"@lingui/react": "^2.8.3",
|
||||
"canvas-confetti": "^1.9.2",
|
||||
"code-blast-codemirror": "chinchang/code-blast-codemirror#web-maker",
|
||||
"codemirror": "^5.37.0",
|
||||
"copy-webpack-plugin": "^4.5.1",
|
||||
|
@@ -7,9 +7,15 @@ import { A, Button } from './common';
|
||||
import { useCheckout } from '../hooks/useCheckout';
|
||||
import { Text } from './Text';
|
||||
import { Icon } from './Icons';
|
||||
import { showConfetti } from '../utils';
|
||||
|
||||
const checkoutIds = {
|
||||
monthly: '1601bc00-9623-435b-b1de-2a70a2445c13',
|
||||
annual: 'aae95d78-05c8-46f5-b11e-2d40ddd211d3'
|
||||
};
|
||||
export function Pro({ user }) {
|
||||
const hasCheckoutLoaded = useCheckout();
|
||||
const [isAnnual, setIsAnnual] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
if (hasCheckoutLoaded) {
|
||||
@@ -17,7 +23,13 @@ export function Pro({ user }) {
|
||||
eventHandler: e => {
|
||||
console.log('eventHandler', e);
|
||||
if (e.event === 'Checkout.Success') {
|
||||
window.location.reload();
|
||||
showConfetti(2);
|
||||
alertsService.add(
|
||||
'You are now PRO! 🎉. Reloading your superpowers...'
|
||||
);
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -25,7 +37,17 @@ export function Pro({ user }) {
|
||||
}
|
||||
}, [hasCheckoutLoaded]);
|
||||
return (
|
||||
<VStack gap={4} align="stretch">
|
||||
<VStack gap={2} align="stretch">
|
||||
<Stack justify="center">
|
||||
<Switch
|
||||
labels={['Monthly', 'Annually']}
|
||||
checked={isAnnual}
|
||||
showBothLabels={true}
|
||||
onChange={e => {
|
||||
setIsAnnual(e.target.checked);
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack gap={2} align="stretch">
|
||||
<Card
|
||||
price="Free"
|
||||
@@ -38,13 +60,15 @@ export function Pro({ user }) {
|
||||
/>
|
||||
<Card
|
||||
bg="#674dad"
|
||||
price="$6/mo"
|
||||
price={!isAnnual ? '$8/mo' : '$65/yr'}
|
||||
name="Pro"
|
||||
action={
|
||||
<A
|
||||
class="btn btn--primary lemonsqueezy-button d-f jc-c ai-c"
|
||||
style="gap:0.2rem"
|
||||
href={`https://web-maker.lemonsqueezy.com/checkout/buy/1601bc00-9623-435b-b1de-2a70a2445c13?embed=1&checkout[custom][userId]=${user.uid}`}
|
||||
href={`https://web-maker.lemonsqueezy.com/checkout/buy/${
|
||||
checkoutIds[isAnnual ? 'annual' : 'monthly']
|
||||
}?embed=1&checkout[custom][userId]=${user.uid}`}
|
||||
>
|
||||
Go <ProBadge />
|
||||
</A>
|
||||
@@ -59,6 +83,11 @@ export function Pro({ user }) {
|
||||
]}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack justify="center">
|
||||
<Text tag="p" appearance="secondary">
|
||||
Prices are excluding taxes. 30 days refund policy if not satisfied.
|
||||
</Text>
|
||||
</Stack>
|
||||
</VStack>
|
||||
);
|
||||
}
|
||||
|
@@ -1,5 +1,3 @@
|
||||
import { h } from 'preact';
|
||||
|
||||
export default function Switch({
|
||||
checked,
|
||||
onChange,
|
||||
|
@@ -6,7 +6,7 @@
|
||||
--color-overlay: rgba(3, 8, 27, 0.7);
|
||||
--color-close-btn: #d12b4a;
|
||||
--code-font-size: 16px;
|
||||
--color-button: #d3a447;
|
||||
--color-button: #e3ba26;
|
||||
--color-focus-outline: #d3a447;
|
||||
--color-form-control-bg: #2c214b;
|
||||
|
||||
@@ -412,6 +412,7 @@ a > svg {
|
||||
}
|
||||
|
||||
.btn--primary {
|
||||
--black-mix: 70%;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
var(--color-button),
|
||||
@@ -419,7 +420,8 @@ a > svg {
|
||||
);
|
||||
color: black;
|
||||
font-weight: 600;
|
||||
border: 1px solid color-mix(in lch, var(--color-button), black 70%);
|
||||
border: 1px solid
|
||||
color-mix(in lch, var(--color-button), black var(--black-mix));
|
||||
box-shadow: inset 0 1px 0px 0 rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
@@ -434,8 +436,11 @@ a > svg {
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
--black-mix: 90%;
|
||||
text-decoration: none;
|
||||
box-shadow: 0 5px 5px 0 rgba(0, 0, 0, 0.25);
|
||||
box-shadow:
|
||||
rgba(0, 0, 0, 0.1) 0px 20px 25px -5px,
|
||||
rgba(0, 0, 0, 0.04) 0px 10px 10px -5px;
|
||||
}
|
||||
|
||||
*:focus {
|
||||
@@ -795,6 +800,8 @@ body > #demo-frame {
|
||||
|
||||
.btn--dark,
|
||||
.main-header__btn-wrap > button {
|
||||
--clr-1: hsl(0, 0%, 25%);
|
||||
--clr-2: hsl(0, 0%, 13%);
|
||||
box-sizing: content-box;
|
||||
/* text-transform: uppercase; */
|
||||
/* font-size: 0.875rem; */
|
||||
@@ -809,7 +816,7 @@ body > #demo-frame {
|
||||
padding: 3px 8px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.9);
|
||||
border-radius: 5px;
|
||||
background: linear-gradient(180deg, hsl(0, 0%, 25%) 0, hsl(0, 0%, 13%) 100%);
|
||||
background: linear-gradient(180deg, var(--clr-1) 0, var(--clr-2) 100%);
|
||||
box-shadow: inset 0 1px 0px 0 rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
@@ -827,12 +834,12 @@ body > #demo-frame {
|
||||
}
|
||||
|
||||
.btn--dark:hover {
|
||||
background: #9297b3;
|
||||
color: #111;
|
||||
--clr-1: #6844ad;
|
||||
/* color: #111; */
|
||||
/* border-color: rgba(146, 151, 179, 0.5); */
|
||||
}
|
||||
.btn--dark:hover > svg {
|
||||
fill: #111;
|
||||
/* fill: #111; */
|
||||
}
|
||||
.btn--dark.btn--active {
|
||||
background: linear-gradient(0deg, hsl(0, 0%, 25%) 0, hsl(0, 0%, 13%) 100%);
|
||||
@@ -2202,8 +2209,19 @@ while the theme CSS file is loading */
|
||||
background-position: bottom right;
|
||||
}
|
||||
.plan-card {
|
||||
background: rgb(255 255 255 / 10%);
|
||||
border-radius: 0.4rem;
|
||||
padding: 1rem;
|
||||
--shadow-color: 253deg 47% 15%;
|
||||
--shadow-elevation-low: 0.3px 0.5px 0.7px hsl(var(--shadow-color) / 0.34),
|
||||
0.4px 0.8px 1px -1.2px hsl(var(--shadow-color) / 0.34),
|
||||
1px 2px 2.5px -2.5px hsl(var(--shadow-color) / 0.34);
|
||||
--shadow-elevation-medium: 0.3px 0.5px 0.7px hsl(var(--shadow-color) / 0.36),
|
||||
0.8px 1.6px 2px -0.8px hsl(var(--shadow-color) / 0.36),
|
||||
2.1px 4.1px 5.2px -1.7px hsl(var(--shadow-color) / 0.36),
|
||||
5px 10px 12.6px -2.5px hsl(var(--shadow-color) / 0.36);
|
||||
|
||||
box-shadow: var(--shadow-elevation-low);
|
||||
}
|
||||
@media screen and (max-width: 600px) {
|
||||
body {
|
||||
|
34
src/utils.js
34
src/utils.js
@@ -1,9 +1,9 @@
|
||||
import { trackEvent } from './analytics';
|
||||
|
||||
import { computeHtml, computeCss, computeJs } from './computes';
|
||||
import { modes, HtmlModes, CssModes, JsModes } from './codeModes';
|
||||
import { deferred } from './deferred';
|
||||
import { getExtensionFromFileName } from './fileUtils';
|
||||
import confetti from 'canvas-confetti';
|
||||
const esprima = require('esprima');
|
||||
|
||||
window.DEBUG = document.cookie.indexOf('wmdebug') > -1;
|
||||
@@ -594,3 +594,35 @@ export async function copyToClipboard(text) {
|
||||
console.error('Failed to copy text: ', err);
|
||||
}
|
||||
}
|
||||
|
||||
export function showConfetti(time = 4) {
|
||||
var end = Date.now() + time * 1000;
|
||||
|
||||
(function frame() {
|
||||
confetti({
|
||||
particleCount: 1,
|
||||
startVelocity: 0,
|
||||
ticks: 100,
|
||||
origin: {
|
||||
x: Math.random(),
|
||||
// since they fall down, start a bit higher than random
|
||||
y: Math.random() - 0.2
|
||||
},
|
||||
colors: [
|
||||
[
|
||||
'#26ccff',
|
||||
'#a25afd',
|
||||
'#ff5e7e',
|
||||
'#88ff5a',
|
||||
'#fcff42',
|
||||
'#ffa62d',
|
||||
'#ff36ff'
|
||||
][~~(Math.random() * 7)]
|
||||
]
|
||||
});
|
||||
|
||||
if (Date.now() < end) {
|
||||
requestAnimationFrame(frame);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
Reference in New Issue
Block a user