feat: improve email verified screen offer ui

This commit is contained in:
thecodrr
2021-04-09 12:39:28 +05:00
parent c7f04fc0fe
commit ef149dbfe5
6 changed files with 97 additions and 42 deletions

View File

@@ -4,6 +4,7 @@
"private": true,
"main": "./build/electron.js",
"dependencies": {
"@inlightmedia/react-countdown-timer": "^1.1.2",
"@mdi/js": "^5.9.55",
"@mdi/react": "^1.4.0",
"@rebass/forms": "^4.0.6",

View File

@@ -341,9 +341,14 @@ export function showLoadingDialog(dialogData) {
));
}
export const showLogInDialog = () => {
export const showLogInDialog = (title, description, positiveText) => {
return showDialog((Dialogs, perform) => (
<Dialogs.LoginDialog onClose={() => perform()} />
<Dialogs.LoginDialog
title={title}
description={description}
positiveText={positiveText}
onClose={() => perform()}
/>
));
};

View File

@@ -25,6 +25,10 @@ async function upgrade(user, coupon) {
const { Paddle } = window;
if (!Paddle) return;
if (coupon && window.umami) {
window.umami(`[${coupon}] redeemed!`, "offers");
}
Paddle.Checkout.open({
product: PRODUCT_ID,
email: user.email,

View File

@@ -7,12 +7,10 @@ import Field from "../field";
import { Checkbox, Label } from "@rebass/forms";
import { showForgotPasswordDialog } from "../../common/dialog-controller";
import { hashNavigate } from "../../navigation";
import useHashLocation from "../../utils/use-hash-location";
const requiredValues = ["email", "password", "remember"];
function LoginDialog(props) {
const { onClose } = props;
const [, queryParams] = useHashLocation();
const { onClose, title, description, positiveText } = props;
const [error, setError] = useState();
const [credential, setCredential] = useState();
const [email, setEmail] = useState();
@@ -23,9 +21,8 @@ function LoginDialog(props) {
useEffect(() => {
if (isLoggedIn) {
onClose();
if (queryParams.redirect) hashNavigate(queryParams.redirect);
}
}, [isLoggedIn, queryParams, onClose]);
}, [isLoggedIn, onClose]);
useEffect(() => {
if (!window.PasswordCredential) return;
@@ -61,7 +58,7 @@ function LoginDialog(props) {
title={
credential?.password
? `Signing in as ${credential.id}...`
: "Sign in to Your Account"
: title || "Sign in to your account"
}
description={
<Flex alignItems="center">
@@ -71,15 +68,21 @@ function LoginDialog(props) {
</Text>
) : (
<Text as="span" fontSize="body" color="gray">
Don't have an account?{" "}
<Button
variant="anchor"
sx={{ textAlign: "left" }}
fontSize="body"
onClick={() => hashNavigate("/signup")}
>
Create an account here.
</Button>
{description ? (
description
) : (
<>
Don't have an account?{" "}
<Button
variant="anchor"
sx={{ textAlign: "left" }}
fontSize="body"
onClick={() => hashNavigate("/signup")}
>
Create an account here.
</Button>
</>
)}
</Text>
)}
</Flex>
@@ -97,7 +100,7 @@ function LoginDialog(props) {
form: "loginForm",
type: "submit",
},
text: "Sign in",
text: positiveText || "Sign in",
loading: isLoggingIn,
disabled: isLoggingIn,
}}
@@ -132,9 +135,6 @@ function LoginDialog(props) {
} else {
onClose();
}
if (queryParams.redirect) {
hashNavigate(queryParams.redirect);
}
})
.catch((e) => setError(e.message));
}}

View File

@@ -4,6 +4,11 @@ import ThemeProvider from "../components/theme-provider";
import * as Icon from "../components/icons";
import { useQueryParams } from "../navigation";
import Logo from "../assets/logo.svg";
import { upgrade } from "../common/upgrade";
import { db } from "../common/db";
import { showLogInDialog } from "../common/dialog-controller";
import { showToast } from "../utils/toast";
import CountdownTimer from "@inlightmedia/react-countdown-timer";
function EmailConfirmed() {
const [{ userId }] = useQueryParams();
@@ -43,7 +48,12 @@ function EmailConfirmed() {
<Text variant="body" mt={2}>
You can safely close this window and return to Notesnook.
</Text>
<SaleBanner discount={80} promoCode="EARLYBIRD" daysRemaining="2" />
<SaleBanner
discount={80}
coupon="EARLYBIRD"
offerEndDate="2021-04-11T00:00:00Z"
userId={userId}
/>
</Flex>
</Flex>
</ThemeProvider>
@@ -52,7 +62,8 @@ function EmailConfirmed() {
export default EmailConfirmed;
function SaleBanner(props) {
const { discount, promoCode, daysRemaining } = props;
const { discount, coupon, offerEndDate, userId } = props;
return (
<Flex
bg="shade"
@@ -81,43 +92,70 @@ function SaleBanner(props) {
{discount}% OFF
</Text>
<Text variant="body" fontSize="title" textAlign="center">
*Use code{" "}
*Use coupon{" "}
<Text as="b" color="primary">
{promoCode}
{coupon}
</Text>{" "}
at checkout to get{" "}
<Text as="b" color="primary">
{discount}% off your first month.
</Text>
</Text>
<CountdownTimer
dateTime={offerEndDate}
style={{
color: "black",
fontSize: 38,
padding: 0,
margin: 0,
fontWeight: "bold",
}}
shouldHidePrecedingZeros={true}
shouldShowTimeUnits
shouldShowSeparator={false}
/>
<Text variant="body" color="error" fontWeight="bold">
Remaining to get {discount}% off your first month
</Text>
<Button
mt={1}
fontSize="title"
width="100%"
onClick={() => {
if (window.umami)
window.umami(`Email verified offer [${promoCode}] click`, "offers");
window.location.href = `/#/login?redirect=/buy/${promoCode}`;
onClick={async () => {
if (window.umami) {
window.umami(`[Email verified] Subscribe button clicked`, "offers");
}
let user = await db.user.getUser();
if (user && user.id === userId) {
await upgrade(user, coupon);
return;
} else if (user && user.id !== userId) {
const shouldLogout = window.confirm(
"You are already logged into a different Notesnook account. Do you want to logout?"
);
if (!shouldLogout) return;
await db.user.logout(true);
}
await showLogInDialog(
`Login in to get ${discount}% off`,
`Use the coupon "${coupon}" at checkout to get ${discount}% off your first month.`,
`Get ${discount}% off`
);
user = await db.user.getUser();
if (!user) {
showToast("Could not login. Please retry.");
return;
}
await upgrade(user, coupon);
}}
>
Subscribe now before offer ends!
</Button>
<Text as="em" variant="body" mt={1} color="error">
(Only {daysRemaining} days remaining.)
</Text>
<Text variant="body" fontSize="subBody" mt={1}>
*This offer only works if you purchase through our web app.
</Text>
{/* <Text variant="body" textAlign="center">
Unlimited storage &amp; attachments
<br />
Unlimited notebooks &amp; tags
<br />
Automatic syncing &amp; backups
<br />
<a href="https://notesnook.com/">AND SO MUCH MORE!</a>
</Text> */}
</Flex>
);
}

View File

@@ -1426,6 +1426,13 @@
dependencies:
"@hapi/hoek" "^9.0.0"
"@inlightmedia/react-countdown-timer@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@inlightmedia/react-countdown-timer/-/react-countdown-timer-1.1.2.tgz#bf34d9d9b8098d8aba7117d254e2cb0ab318c25d"
integrity sha512-Ydh1Tf6f83S6a97PduDlNj/LaI2ZxTXZHpGEpiXEisfR8Afwuxd+AvZr4JUC9Mt5jLoyTHS4irShZEY+5PaAMw==
dependencies:
moment-mini "^2.24.0"
"@istanbuljs/load-nyc-config@^1.0.0":
version "1.1.0"
resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz"