From 7cfa7482692885e76075b27b6184ce358bdf182f Mon Sep 17 00:00:00 2001 From: adueck Date: Sat, 15 Oct 2022 20:37:55 +0500 Subject: [PATCH] basic subscription buttons --- account/src/routers/payment-router.ts | 14 ++-- account/views/store.ejs | 88 ------------------------ account/views/user.ejs | 27 +++----- website/src/App.tsx | 20 +++--- website/src/components/UpgradePrices.tsx | 30 ++++++++ website/src/screens/Account.tsx | 36 ++++------ website/src/screens/Wordlist.tsx | 31 ++++++++- 7 files changed, 101 insertions(+), 145 deletions(-) delete mode 100644 account/views/store.ejs create mode 100644 website/src/components/UpgradePrices.tsx diff --git a/account/src/routers/payment-router.ts b/account/src/routers/payment-router.ts index 2ef42d0..a18f161 100644 --- a/account/src/routers/payment-router.ts +++ b/account/src/routers/payment-router.ts @@ -80,6 +80,10 @@ paymentRouter.post("/create-checkout-session", async (req, res, next) => { return next("not logged in"); } try { + const source = req.query.source; + const returnUrl = source === "dictionary" + ? "https://dictionary.lingodcs.com/account" + : "https://account.lingdocs.com/user"; const price = req.body.priceId; const session = await stripe.checkout.sessions.create({ billing_address_collection: 'auto', @@ -93,13 +97,13 @@ paymentRouter.post("/create-checkout-session", async (req, res, next) => { metadata: { userId: req.user.userId, startTime: Date.now(), - cycle: price === "price_1Lt0XdJnpCQCjf9pM9qqdyt6" + cycle: price === "price_1Lt8NqJnpCQCjf9pN7CQUjjO" ? "monthly" : "yearly", }, }, mode: 'subscription', - success_url: `https://account.lingdocs.com/user`, - cancel_url: `https://account.lingdocs.com/user`, + success_url: returnUrl, + cancel_url: returnUrl, }); if (!session.url) { return next("error creating session url"); @@ -111,10 +115,6 @@ paymentRouter.post("/create-checkout-session", async (req, res, next) => { } }); -paymentRouter.get("/store", (req, res) => { - res.render("store"); -}); - paymentRouter.post('/create-portal-session', async (req, res, next) => { if (!req.user) { return next("error finding user"); diff --git a/account/views/store.ejs b/account/views/store.ejs deleted file mode 100644 index 2c0d160..0000000 --- a/account/views/store.ejs +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - Store ยท LingDocs - - - - - -
-
- - -
-

Student Account Pricing

-

Upgrade to a student account and activate a wordlist you can sync accross devices

-
-
- -
-
-
-
-
-

Monthly

-
-
-

$1/month

-
    -
  • Cancel anytime
  • -
-
- - -
-
-
-
-
-
-
-

Yearly

-
-
-

$10/year

-
    -
  • Save 20%
  • -
-
- - -
-
-
-
-
-
-
- -
-
-
- - \ No newline at end of file diff --git a/account/views/user.ejs b/account/views/user.ejs index b8ad29e..e680a0d 100644 --- a/account/views/user.ejs +++ b/account/views/user.ejs @@ -53,22 +53,17 @@
Account Level: <%= user.level.charAt(0).toUpperCase() + user.level.slice(1) %>
<% if (user.level === "basic") { %> - <% if (user.upgradeToStudentRequest === "waiting") { %> -

Wating for upgrade approval

- <% } %> - <% if (user.tester) { %> -

Upgrade to Student account for Wordlist features

-
-
- - -
-
- - -
-
- <% } %> +

Upgrade to Student account for Wordlist features

+
+
+ + +
+
+ + +
+
<% } %> <% if (user.tester && user.level === "student" && user.subscription) { %>

Current subscription: <% if (user.subscription.metadata.cycle === "monthly") { %>$1/month<% } else { %>$10/year<% } %>

diff --git a/website/src/App.tsx b/website/src/App.tsx index 6f8183c..761b47d 100644 --- a/website/src/App.tsx +++ b/website/src/App.tsx @@ -25,8 +25,7 @@ import EntryEditor from "./screens/EntryEditor"; import IsolatedEntry from "./screens/IsolatedEntry"; import PrivacyPolicy from "./screens/PrivacyPolicy"; import Wordlist from "./screens/Wordlist"; -import { wordlistEnabled } from "./lib/level-management"; -import { +import { saveOptions, readOptions, saveUser, @@ -585,14 +584,15 @@ class App extends Component { isolateEntry={this.handleIsolateEntry} /> - {wordlistEnabled(this.state.user) && + - } + {this.state.user?.level === "editor" && { - {wordlistEnabled(this.state.user) && - - } + {this.state.user?.level === "editor" && +
Subscription options
+
+ {prices.map(({ priceId, label }) =>
+
+ + +
+
)} +
+ ; +} + +export default UpgradePrices; \ No newline at end of file diff --git a/website/src/screens/Account.tsx b/website/src/screens/Account.tsx index 2c89e2b..166012e 100644 --- a/website/src/screens/Account.tsx +++ b/website/src/screens/Account.tsx @@ -7,11 +7,11 @@ import { upgradeAccount, signOut, publishDictionary, - upgradeToStudentRequest, } from "../lib/backend-calls"; import LoadingElipses from "../components/LoadingElipses"; import { Helmet } from "react-helmet"; import * as AT from "../types/account-types"; +import UpgradePrices from "../components/UpgradePrices"; const providers: ("google" | "twitter" | "github")[] = ["google", "twitter", "github"]; @@ -58,22 +58,6 @@ const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUs setUpgradePassword(""); setUpgradeError(""); } - async function handleUpgradeRequest() { - setUpgradeError(""); - setWaiting(true); - upgradeToStudentRequest().then((res) => { - setWaiting(false); - if (res.ok) { - loadUser(); - closeUpgrade(); - } else { - setUpgradeError("Error requesting upgrade"); - } - }).catch((err) => { - setWaiting(false); - setUpgradeError(err.message); - }); - } async function handleUpgrade() { setUpgradeError(""); setWaiting(true); @@ -161,9 +145,7 @@ const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUs } -
  • Account Level: {capitalize(user.level)} {user.upgradeToStudentRequest === "waiting" - ? "(Upgrade Requested)" - : ""}
  • +
  • Account Level: {capitalize(user.level)}
  • Signs in with: {(user.password && user.email) && Password @@ -206,9 +188,19 @@ const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUs Upgrade to Student Account - Enter the secret upgrade password to upgrade your account or + +

    Upgrade to a student account to enable the wordlist

    +

    Features:

    +
      +
    • Save your wordlist and sync across devices
    • +
    • Save text, audio, or visual context for words
    • +
    • Review words with Anki-style spaced repetition
    • +
    + +

    Or enter upgrade password

    +
    - + void, optionsDispatch: (action: OptionsAction) => void, + user: AT.LingdocsUser | undefined, }) { // @ts-ignore const [wordOpen, setWordOpen] = useState(undefined); @@ -253,6 +257,31 @@ function Wordlist({ options, wordlist, isolateEntry, optionsDispatch }: { />}
    } + if (!(user?.level === "student")) { + return
    + + Wordlist - LingDocs Pashto Dictionary + +
    +

    Wordlist

    +
    +
    + {!user + ?

    Sign in to upgrade and enable wordlist

    + :
    +

    Upgrade to a student account to enable the wordlist

    +

    Features:

    +
      +
    • Save your wordlist and sync across devices
    • +
    • Save text, audio, or visual context for words
    • +
    • Review words with Anki-style spaced repetition
    • +
    + +
    + } +
    +
    ; + } return
    Wordlist - LingDocs Pashto Dictionary