1
0
mirror of https://github.com/chinchang/web-maker.git synced 2025-07-25 07:51:12 +02:00

fix upgrade ux on extension

This commit is contained in:
Kushagra Gour
2024-05-03 17:38:00 +05:30
parent 0756b4d8a5
commit ae55cde6e1
4 changed files with 82 additions and 40 deletions

View File

@@ -15,7 +15,7 @@ const checkoutIds = {
annual: 'aae95d78-05c8-46f5-b11e-2d40ddd211d3', annual: 'aae95d78-05c8-46f5-b11e-2d40ddd211d3',
generic: 'd1d2da1a-ae8f-4222-bbaf-6e07da8954bf' //'f8c64e50-7734-438b-a122-3510156f14ed' generic: 'd1d2da1a-ae8f-4222-bbaf-6e07da8954bf' //'f8c64e50-7734-438b-a122-3510156f14ed'
}; };
export function Pro({ user, onLoginClick }) { export function Pro({ user, onLoginClick, onBuyFromExtensionClick }) {
const hasCheckoutLoaded = useCheckout(); const hasCheckoutLoaded = useCheckout();
const [isAnnual, setIsAnnual] = useState(true); const [isAnnual, setIsAnnual] = useState(true);
@@ -38,6 +38,42 @@ export function Pro({ user, onLoginClick }) {
window.LemonSqueezy.Refresh(); window.LemonSqueezy.Refresh();
} }
}, [hasCheckoutLoaded]); }, [hasCheckoutLoaded]);
let upgradeActionEl;
if (window.IS_EXTENSION) {
upgradeActionEl = (
<button
type="button"
className="btn btn--pro jc-c"
onClick={onBuyFromExtensionClick}
>
Upgrade to PRO
</button>
);
} else if (window.user) {
upgradeActionEl = (
<A
class="btn btn--pro lemonsqueezy-button d-f jc-c ai-c"
style="gap:0.2rem"
href={`https://web-maker.lemonsqueezy.com/checkout/buy/${checkoutIds.generic}?embed=1&checkout[custom][userId]=${user?.uid}`}
onClick={() => {
trackEvent('ui', 'buyBtnClick');
}}
>
Go PRO
</A>
);
} else {
upgradeActionEl = (
<button
type="button"
className="btn btn--pro jc-c"
onClick={onLoginClick}
>
Login & upgrade to PRO
</button>
);
}
return ( return (
<VStack gap={2} align="stretch"> <VStack gap={2} align="stretch">
{/* <Stack justify="center"> {/* <Stack justify="center">
@@ -66,28 +102,7 @@ export function Pro({ user, onLoginClick }) {
price={'Starting $6/mo'} price={'Starting $6/mo'}
subTitle="Annual & One-time pricing available" subTitle="Annual & One-time pricing available"
name="Pro" name="Pro"
action={ action={upgradeActionEl}
window.user ? (
<A
class="btn btn--pro lemonsqueezy-button d-f jc-c ai-c"
style="gap:0.2rem"
href={`https://web-maker.lemonsqueezy.com/checkout/buy/${checkoutIds.generic}?embed=1&checkout[custom][userId]=${user?.uid}`}
onClick={() => {
trackEvent('ui', 'buyBtnClick');
}}
>
Go PRO
</A>
) : (
<button
type="button"
className="btn btn--pro jc-c"
onClick={onLoginClick}
>
Login & upgrade to PRO
</button>
)
}
features={[ features={[
'Unlimited private creations', 'Unlimited private creations',
'Unlimited public creations', 'Unlimited public creations',

View File

@@ -0,0 +1,27 @@
import { h } from 'preact';
import Modal from './Modal';
import { Text } from './Text';
import { Stack } from './Stack';
export function ProOnAppModal({ show, closeHandler }) {
return (
<Modal extraClasses="" show={show} closeHandler={closeHandler}>
<div class="ta">
<Text appearance="primary" tag="h1" size="4" weight="700">
Upgrade on Web app
</Text>
<p className="para">
Upgrading to PRO from the extension is not available yet. You can
instead upgrade on the Web app, come back here, refresh and get all
the PRO features right here!
</p>
<Stack justify="center">
<a href="https://webmaker.app/create" className="btn btn--pro">
Upgrade on Web app
</a>
</Stack>
</div>
</Modal>
);
}

View File

@@ -77,6 +77,7 @@ import { Pro } from './Pro.jsx';
import { VStack } from './Stack.jsx'; import { VStack } from './Stack.jsx';
import { ProBadge } from './ProBadge.jsx'; import { ProBadge } from './ProBadge.jsx';
import { Text } from './Text.jsx'; import { Text } from './Text.jsx';
import { ProOnAppModal } from './ProOnAppModal.js';
if (module.hot) { if (module.hot) {
require('preact/debug'); require('preact/debug');
@@ -129,7 +130,8 @@ export default class App extends Component {
isAssetsOpen: false, isAssetsOpen: false,
isShareModalOpen: false, isShareModalOpen: false,
isProModalOpen: false, isProModalOpen: false,
isFilesLimitModalOpen: false isFilesLimitModalOpen: false,
isProOnAppModalOpen: false
}; };
this.state = { this.state = {
isSavedItemPaneOpen: false, isSavedItemPaneOpen: false,
@@ -227,8 +229,7 @@ export default class App extends Component {
// not enumerable anymore // not enumerable anymore
newUser = { newUser = {
...newUser, ...newUser,
isPro: false, isPro: false
...customUser
}; };
window.user = newUser; window.user = newUser;
this.setState({ user: newUser, prefs }, this.updateSetting); this.setState({ user: newUser, prefs }, this.updateSetting);
@@ -1803,7 +1804,6 @@ export default class App extends Component {
codeSize={this.state.codeSize} codeSize={this.state.codeSize}
/> />
</div> </div>
<SavedItemPane <SavedItemPane
itemsMap={this.state.savedItems} itemsMap={this.state.savedItems}
isOpen={this.state.isSavedItemPaneOpen} isOpen={this.state.isSavedItemPaneOpen}
@@ -1814,9 +1814,7 @@ export default class App extends Component {
onExport={this.exportBtnClickHandler.bind(this)} onExport={this.exportBtnClickHandler.bind(this)}
mergeImportedItems={this.mergeImportedItems.bind(this)} mergeImportedItems={this.mergeImportedItems.bind(this)}
/> />
<Alerts /> <Alerts />
<Modal <Modal
show={this.state.isAddLibraryModalOpen} show={this.state.isAddLibraryModalOpen}
closeHandler={() => this.setState({ isAddLibraryModalOpen: false })} closeHandler={() => this.setState({ isAddLibraryModalOpen: false })}
@@ -1835,7 +1833,6 @@ export default class App extends Component {
onChange={this.onExternalLibChange.bind(this)} onChange={this.onExternalLibChange.bind(this)}
/> />
</Modal> </Modal>
<Modal <Modal
show={this.state.isNotificationsModalOpen} show={this.state.isNotificationsModalOpen}
closeHandler={() => closeHandler={() =>
@@ -1856,7 +1853,6 @@ export default class App extends Component {
onChange={this.updateSetting.bind(this)} onChange={this.updateSetting.bind(this)}
/> />
</Modal> </Modal>
<Modal <Modal
show={this.state.isProfileModalOpen} show={this.state.isProfileModalOpen}
closeHandler={() => this.setState({ isProfileModalOpen: false })} closeHandler={() => this.setState({ isProfileModalOpen: false })}
@@ -1916,9 +1912,13 @@ export default class App extends Component {
this.closeAllOverlays(); this.closeAllOverlays();
this.loginBtnClickHandler(); this.loginBtnClickHandler();
}} }}
onBuyFromExtensionClick={() => {
console.log('open modal');
this.closeAllOverlays();
this.setState({ isProOnAppModalOpen: true });
}}
/> />
</Modal> </Modal>
{/* Login modal is intentionally kept here after assets & share modal because {/* Login modal is intentionally kept here after assets & share modal because
they trigger this modal and if order isn't maintainer, the modal overlay doesn't they trigger this modal and if order isn't maintainer, the modal overlay doesn't
show properly */} show properly */}
@@ -1929,7 +1929,6 @@ export default class App extends Component {
> >
<Login /> <Login />
</Modal> </Modal>
<HelpModal <HelpModal
show={this.state.isHelpModalOpen} show={this.state.isHelpModalOpen}
closeHandler={() => this.setState({ isHelpModalOpen: false })} closeHandler={() => this.setState({ isHelpModalOpen: false })}
@@ -1959,17 +1958,14 @@ export default class App extends Component {
)} )}
dontAskBtnClickHandler={this.dontAskToImportAnymore.bind(this)} dontAskBtnClickHandler={this.dontAskToImportAnymore.bind(this)}
/> />
<OnboardingModal <OnboardingModal
show={this.state.isOnboardModalOpen} show={this.state.isOnboardModalOpen}
closeHandler={() => this.setState({ isOnboardModalOpen: false })} closeHandler={() => this.setState({ isOnboardModalOpen: false })}
/> />
<Js13KModal <Js13KModal
show={this.state.isJs13KModalOpen} show={this.state.isJs13KModalOpen}
closeHandler={() => this.setState({ isJs13KModalOpen: false })} closeHandler={() => this.setState({ isJs13KModalOpen: false })}
/> />
<CreateNewModal <CreateNewModal
show={this.state.isCreateNewModalOpen} show={this.state.isCreateNewModalOpen}
closeHandler={() => this.setState({ isCreateNewModalOpen: false })} closeHandler={() => this.setState({ isCreateNewModalOpen: false })}
@@ -1982,7 +1978,10 @@ export default class App extends Component {
this this
)} )}
/> />
<ProOnAppModal
show={this.state.isProOnAppModalOpen}
closeHandler={() => this.setState({ isProOnAppModalOpen: false })}
/>
<Modal <Modal
extraClasses="" extraClasses=""
show={this.state.isFilesLimitModalOpen} show={this.state.isFilesLimitModalOpen}
@@ -1999,21 +1998,18 @@ export default class App extends Component {
</Text> </Text>
</VStack> </VStack>
</Modal> </Modal>
<CommandPalette <CommandPalette
show={this.state.isCommandPaletteOpen} show={this.state.isCommandPaletteOpen}
files={linearizeFiles(this.state.currentItem.files || [])} files={linearizeFiles(this.state.currentItem.files || [])}
isCommandMode={this.state.isCommandPaletteInCommandMode} isCommandMode={this.state.isCommandPaletteInCommandMode}
closeHandler={() => this.setState({ isCommandPaletteOpen: false })} closeHandler={() => this.setState({ isCommandPaletteOpen: false })}
/> />
<Portal into="#portal"> <Portal into="#portal">
<div <div
class="modal-overlay" class="modal-overlay"
onClick={this.modalOverlayClickHandler.bind(this)} onClick={this.modalOverlayClickHandler.bind(this)}
/> />
</Portal> </Portal>
<Icons /> <Icons />
<form <form
style="display:none;" style="display:none;"

View File

@@ -233,6 +233,10 @@ button {
color: #f7ae2d; color: #f7ae2d;
} }
.para {
max-width: 60ch;
}
@media screen and (max-width: 600px) { @media screen and (max-width: 600px) {
.block--mobile { .block--mobile {
display: block; display: block;