mirror of
https://github.com/chinchang/web-maker.git
synced 2025-03-25 13:09:48 +01:00
add working pro modal n checkout
This commit is contained in:
parent
e89c2348e4
commit
4c4dc1f2e0
src
@ -133,9 +133,9 @@ export default class Footer extends Component {
|
||||
</svg>
|
||||
</a>
|
||||
<Button
|
||||
onClick={this.props.getProBtnClickHandler}
|
||||
onClick={this.props.proBtnClickHandler}
|
||||
data-event-category="ui"
|
||||
data-event-action="getProFooterBtnClick"
|
||||
data-event-action="proFooterBtnClick"
|
||||
class="footer__link ml-1 hint--rounded hint--top-right hide-on-mobile support-link"
|
||||
aria-label={i18n._(
|
||||
t`Be a PRO and get some advanced superpowers!`
|
||||
|
35
src/components/Pro.jsx
Normal file
35
src/components/Pro.jsx
Normal file
@ -0,0 +1,35 @@
|
||||
import { useEffect, useState } from 'preact/hooks';
|
||||
import { ProBadge } from './ProBadge';
|
||||
import { HStack, Stack, VStack } from './Stack';
|
||||
import Switch from './Switch';
|
||||
import { alertsService } from '../notifications';
|
||||
import { A, Button } from './common';
|
||||
import { useCheckout } from '../hooks/useCheckout';
|
||||
|
||||
export function Pro({ user }) {
|
||||
const hasCheckoutLoaded = useCheckout();
|
||||
|
||||
useEffect(() => {
|
||||
if (hasCheckoutLoaded) {
|
||||
window.LemonSqueezy.Setup({
|
||||
eventHandler: e => {
|
||||
console.log('eventHandler', e);
|
||||
if (e.event === 'Checkout.Success') {
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
window.LemonSqueezy.Refresh();
|
||||
}
|
||||
}, [hasCheckoutLoaded]);
|
||||
return (
|
||||
<VStack gap={4} align="stretch">
|
||||
<A
|
||||
class="btn lemonsqueezy-button"
|
||||
href={`https://web-maker.lemonsqueezy.com/checkout/buy/1601bc00-9623-435b-b1de-2a70a2445c13?embed=1&checkout[custom][userId]=${user.uid}`}
|
||||
>
|
||||
Go <ProBadge />
|
||||
</A>
|
||||
</VStack>
|
||||
);
|
||||
}
|
@ -4,12 +4,15 @@ import { HStack, Stack, VStack } from './Stack';
|
||||
import Switch from './Switch';
|
||||
import { itemService } from '../itemService';
|
||||
import { alertsService } from '../notifications';
|
||||
import { Button } from './common';
|
||||
|
||||
const FREE_PUBLIC_ITEM_COUNT = 1;
|
||||
const BASE_URL = location.origin;
|
||||
|
||||
export function Share({ user, item, onVisibilityChange }) {
|
||||
const [publicItemCount, setPublicItemCount] = useState(0);
|
||||
useEffect(() => {
|
||||
if (!user) return;
|
||||
window.db.getPublicItemCount(user.uid).then(c => {
|
||||
setPublicItemCount(c);
|
||||
console.log(c);
|
||||
@ -25,7 +28,6 @@ export function Share({ user, item, onVisibilityChange }) {
|
||||
const res = await fetch(
|
||||
`http://127.0.0.1:5001/web-maker-app/us-central1/toggleVisibility?token=${token}&itemId=${item.id}`
|
||||
);
|
||||
console.log(res.status);
|
||||
|
||||
if (res.status >= 200 && res.status < 400) {
|
||||
setPublicItemCount(publicItemCount + 1);
|
||||
@ -41,31 +43,45 @@ export function Share({ user, item, onVisibilityChange }) {
|
||||
alertsService.add('Visiblity set to private');
|
||||
}
|
||||
};
|
||||
|
||||
const copyUrl = () => {
|
||||
navigator.clipboard.writeText(`${BASE_URL}/create/${item.id}`);
|
||||
alertsService.add('URL copied to clipboard');
|
||||
};
|
||||
return (
|
||||
<VStack gap={4} align="stretch">
|
||||
<VStack gap={1} align="stretch">
|
||||
<Switch checked={val} onChange={onChange}>
|
||||
Go public?
|
||||
<Switch
|
||||
checked={val}
|
||||
onChange={onChange}
|
||||
labels={['Private', 'Public']}
|
||||
>
|
||||
Access
|
||||
</Switch>
|
||||
{item.isPublic && (
|
||||
<p>
|
||||
Public at{' '}
|
||||
<a href={`https://webmaker.app/create/${item.id}`} target="_blank">
|
||||
https://webmaker.app/create/{item.id}
|
||||
</a>
|
||||
<a href={`${BASE_URL}/create/${item.id}`} target="_blank">
|
||||
{BASE_URL}/create/{item.id}
|
||||
</a>{' '}
|
||||
<Button class="btn btn--dark" onClick={copyUrl}>
|
||||
Copy
|
||||
</Button>
|
||||
</p>
|
||||
)}
|
||||
</VStack>
|
||||
|
||||
<VStack gap={1} align="stretch">
|
||||
<p>
|
||||
You have {FREE_PUBLIC_ITEM_COUNT - publicItemCount}/
|
||||
{FREE_PUBLIC_ITEM_COUNT} public creations left.
|
||||
</p>
|
||||
<p>
|
||||
For unlimited public creations, upgrade to <ProBadge />
|
||||
</p>
|
||||
</VStack>
|
||||
{!user?.isPro ? (
|
||||
<VStack gap={1} align="stretch">
|
||||
<p>
|
||||
You have {FREE_PUBLIC_ITEM_COUNT - publicItemCount}/
|
||||
{FREE_PUBLIC_ITEM_COUNT} public creations left.
|
||||
</p>
|
||||
<p>
|
||||
For unlimited public creations, upgrade to <ProBadge />
|
||||
</p>
|
||||
</VStack>
|
||||
) : null}
|
||||
</VStack>
|
||||
);
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ import { I18nProvider } from '@lingui/react';
|
||||
import { Assets } from './Assets.jsx';
|
||||
import { LocalStorageKeys } from '../constants.js';
|
||||
import { Share } from './Share.jsx';
|
||||
import { Pro } from './Pro.jsx';
|
||||
|
||||
if (module.hot) {
|
||||
require('preact/debug');
|
||||
@ -121,7 +122,8 @@ export default class App extends Component {
|
||||
isCreateNewModalOpen: false,
|
||||
isCommandPaletteOpen: false,
|
||||
isAssetsOpen: false,
|
||||
isShareModalOpen: false
|
||||
isShareModalOpen: false,
|
||||
isProModalOpen: false
|
||||
};
|
||||
this.state = {
|
||||
isSavedItemPaneOpen: false,
|
||||
@ -1131,6 +1133,10 @@ export default class App extends Component {
|
||||
trackEvent('ui', 'notificationButtonClick', version);
|
||||
return false;
|
||||
}
|
||||
proBtnClickHandler() {
|
||||
this.setState({ isProModalOpen: true });
|
||||
trackEvent('ui', 'proBtnClick');
|
||||
}
|
||||
codepenBtnClickHandler(e) {
|
||||
if (this.state.currentItem.cssMode === CssModes.ACSS) {
|
||||
alert(
|
||||
@ -1723,6 +1729,7 @@ export default class App extends Component {
|
||||
onJs13KDownloadBtnClick={this.js13KDownloadBtnClickHandler.bind(
|
||||
this
|
||||
)}
|
||||
proBtnClickHandler={this.proBtnClickHandler.bind(this)}
|
||||
hasUnseenChangelog={this.state.hasUnseenChangelog}
|
||||
codeSize={this.state.codeSize}
|
||||
/>
|
||||
@ -1817,6 +1824,12 @@ export default class App extends Component {
|
||||
}}
|
||||
/>
|
||||
</Modal>
|
||||
<Modal
|
||||
show={this.state.isProModalOpen}
|
||||
closeHandler={() => this.setState({ isProModalOpen: false })}
|
||||
>
|
||||
<Pro user={this.state.user} />
|
||||
</Modal>
|
||||
<HelpModal
|
||||
show={this.state.isHelpModalOpen}
|
||||
closeHandler={() => this.setState({ isHelpModalOpen: false })}
|
||||
|
@ -4,11 +4,15 @@ import { trackEvent } from '../analytics';
|
||||
class Clickable extends Component {
|
||||
handleClick(e) {
|
||||
const el = e.currentTarget;
|
||||
trackEvent(
|
||||
el.getAttribute('data-event-category'),
|
||||
el.getAttribute('data-event-action')
|
||||
);
|
||||
this.props.onClick(e);
|
||||
if (el.getAttribute('data-event-category')) {
|
||||
trackEvent(
|
||||
el.getAttribute('data-event-category'),
|
||||
el.getAttribute('data-event-action')
|
||||
);
|
||||
}
|
||||
if (this.props.onClick) {
|
||||
this.props.onClick(e);
|
||||
}
|
||||
}
|
||||
render() {
|
||||
/* eslint-disable no-unused-vars */
|
||||
|
20
src/hooks/useCheckout.js
Normal file
20
src/hooks/useCheckout.js
Normal file
@ -0,0 +1,20 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
function useCheckout() {
|
||||
const [hasVendorScriptLoaded, setHasVendorScriptLoaded] = useState();
|
||||
useEffect(() => {
|
||||
const script = document.createElement('script');
|
||||
script.src = 'https://app.lemonsqueezy.com/js/lemon.js';
|
||||
script.async = 'true';
|
||||
script.defer = 'true';
|
||||
script.addEventListener('load', () => {
|
||||
window.createLemonSqueezy();
|
||||
setHasVendorScriptLoaded(true);
|
||||
});
|
||||
document.body.appendChild(script);
|
||||
}, []);
|
||||
|
||||
return hasVendorScriptLoaded;
|
||||
}
|
||||
|
||||
export { useCheckout };
|
@ -376,6 +376,7 @@ a > svg {
|
||||
float: right;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-inline-start: 2rem;
|
||||
}
|
||||
|
||||
.btn {
|
||||
|
Loading…
x
Reference in New Issue
Block a user