mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-25 16:09:42 +01:00
feat: improve email verified screen offer ui
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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()}
|
||||
/>
|
||||
));
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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));
|
||||
}}
|
||||
|
||||
@@ -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 & attachments
|
||||
<br />
|
||||
Unlimited notebooks & tags
|
||||
<br />
|
||||
Automatic syncing & backups
|
||||
<br />
|
||||
<a href="https://notesnook.com/">AND SO MUCH MORE!</a>
|
||||
</Text> */}
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user