store interface
This commit is contained in:
parent
c50b283b2d
commit
906992139b
File diff suppressed because it is too large
Load Diff
|
@ -50,6 +50,7 @@
|
||||||
"express": "^4.17.2",
|
"express": "^4.17.2",
|
||||||
"next": "^12.0.7",
|
"next": "^12.0.7",
|
||||||
"ts-node": "^10.1.0",
|
"ts-node": "^10.1.0",
|
||||||
|
"ts-node-dev": "^2.0.0",
|
||||||
"typescript": "^4.3.5"
|
"typescript": "^4.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,10 +177,7 @@ apiRouter.delete("/user", async (req, res, next) => {
|
||||||
* signs out the user signed in
|
* signs out the user signed in
|
||||||
*/
|
*/
|
||||||
apiRouter.post("/sign-out", (req, res) => {
|
apiRouter.post("/sign-out", (req, res) => {
|
||||||
req.logOut((err) => {
|
req.logOut();
|
||||||
console.error("error logging out");
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
sendResponse(res, { ok: true, message: "signed out" });
|
sendResponse(res, { ok: true, message: "signed out" });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ import * as T from "../../../website/src/types/account-types";
|
||||||
|
|
||||||
const authRouter = (passport: PassportStatic) => {
|
const authRouter = (passport: PassportStatic) => {
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
router.get("/", (req, res) => {
|
router.get("/", (req, res) => {
|
||||||
if (req.isAuthenticated()) {
|
if (req.isAuthenticated()) {
|
||||||
return res.redirect("/user");
|
return res.redirect("/user");
|
||||||
|
@ -46,7 +47,6 @@ const authRouter = (passport: PassportStatic) => {
|
||||||
user: req.user,
|
user: req.user,
|
||||||
error: null,
|
error: null,
|
||||||
removeProviderOption: canRemoveOneOutsideProvider(req.user),
|
removeProviderOption: canRemoveOneOutsideProvider(req.user),
|
||||||
upgrade: req.query.upgrade,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ const authRouter = (passport: PassportStatic) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get("/privacy", async (req, res, next) => {
|
router.get("/privacy", (req, res) => {
|
||||||
res.render("privacy");
|
res.render("privacy");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -323,10 +323,7 @@ const authRouter = (passport: PassportStatic) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
router.post("/sign-out", (req, res) => {
|
router.post("/sign-out", (req, res) => {
|
||||||
req.logOut((err) => {
|
req.logOut();
|
||||||
console.error("error logging out");
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
res.redirect("/");
|
res.redirect("/");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ paymentRouter.post("/create-checkout-session", async (req, res, next) => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mode: 'subscription',
|
mode: 'subscription',
|
||||||
success_url: `https://account.lingdocs.com/user?upgrade=success`,
|
success_url: `https://account.lingdocs.com/user`,
|
||||||
cancel_url: `https://account.lingdocs.com/user`,
|
cancel_url: `https://account.lingdocs.com/user`,
|
||||||
});
|
});
|
||||||
if (!session.url) {
|
if (!session.url) {
|
||||||
|
@ -111,6 +111,10 @@ 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) => {
|
paymentRouter.post('/create-portal-session', async (req, res, next) => {
|
||||||
if (!req.user) {
|
if (!req.user) {
|
||||||
return next("error finding user");
|
return next("error finding user");
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="description" content="LingDocs Signin">
|
||||||
|
<title>Store · LingDocs</title>
|
||||||
|
<link href="/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css" integrity="sha384-DyZ88mC6Up2uqS4h/KRgHuoeGwBcD4Ng9SiP4dIRy0EXTlnuz47vAwmeGwVChigm" crossorigin="anonymous">
|
||||||
|
<script>
|
||||||
|
function handleCancel() {
|
||||||
|
if (window.opener) {
|
||||||
|
const w = window.opener
|
||||||
|
try {
|
||||||
|
w.postMessage("cancelled", "https://dictionary.lingdocs.com");
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert("close window or go back to cancel");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container py-3">
|
||||||
|
<header>
|
||||||
|
<div class="d-flex flex-column flex-md-row align-items-center pb-3 mb-4 border-bottom">
|
||||||
|
<a href="/" class="d-flex align-items-center text-dark text-decoration-none">
|
||||||
|
<span class="fs-4">LingDocs</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<nav class="d-inline-flex mt-2 mt-md-0 ms-md-auto">
|
||||||
|
<a class="py-2 text-dark text-decoration-none" href="https://account.lingdocs.com/">Account</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="pricing-header p-3 pb-md-4 mx-auto text-center">
|
||||||
|
<h1 class="display-4 fw-normal">Student Account Pricing</h1>
|
||||||
|
<p class="fs-5 text-muted">Upgrade to a student account and activate a wordlist you can sync accross devices</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<div class="row justify-content-center row-cols-1 row-cols-md-3 mb-3 text-center">
|
||||||
|
<div class="col">
|
||||||
|
<div class="card mb-4 rounded-3 shadow-sm">
|
||||||
|
<div class="card-header py-3">
|
||||||
|
<h4 class="my-0 fw-normal">Monthly</h4>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<h1 class="card-title pricing-card-title">$1<small class="text-muted fw-light">/month</small></h1>
|
||||||
|
<ul class="list-unstyled mt-3 mb-4">
|
||||||
|
<li>Cancel anytime</li>
|
||||||
|
</ul>
|
||||||
|
<form action="/payment/create-checkout-session" method="POST">
|
||||||
|
<input type="hidden" name="priceId" value="price_1Lt0XdJnpCQCjf9pM9qqdyt6" />
|
||||||
|
<button class="w-100 btn btn-lg btn-primary" type="submit">Subscribe</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="card mb-4 rounded-3 shadow-sm">
|
||||||
|
<div class="card-header py-3">
|
||||||
|
<h4 class="my-0 fw-normal">Yearly</h4>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<h1 class="card-title pricing-card-title">$10<small class="text-muted fw-light">/year</small></h1>
|
||||||
|
<ul class="list-unstyled mt-3 mb-4">
|
||||||
|
<li>Save 20%</li>
|
||||||
|
</ul>
|
||||||
|
<form action="/payment/create-checkout-session" method="POST">
|
||||||
|
<input type="hidden" name="priceId" value="price_1Lt0XdJnpCQCjf9pHk1MQqCC" />
|
||||||
|
<button class="w-100 btn btn-lg btn-primary" type="submit">Subscribe</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-2">
|
||||||
|
<button onclick="handleCancel()" type="button" class="w-100 btn btn-lg btn-outline-secondary">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -52,10 +52,6 @@
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<h5>Account Level: <%= user.level.charAt(0).toUpperCase() + user.level.slice(1) %></h5>
|
<h5>Account Level: <%= user.level.charAt(0).toUpperCase() + user.level.slice(1) %></h5>
|
||||||
<% if (upgrade === "success" && user.level === "student") { %>
|
|
||||||
<p>🎉 Account upgraded to student 🎉</p>
|
|
||||||
<p>Thank you for your purchase!</p>
|
|
||||||
<% } %>
|
|
||||||
<% if (user.level === "basic") { %>
|
<% if (user.level === "basic") { %>
|
||||||
<% if (user.upgradeToStudentRequest === "waiting") { %>
|
<% if (user.upgradeToStudentRequest === "waiting") { %>
|
||||||
<p>Wating for upgrade approval</p>
|
<p>Wating for upgrade approval</p>
|
||||||
|
@ -191,6 +187,11 @@
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
w.postMessage("upgraded", "https://dictionary.lingodocs.com");
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// function handleRequestUpgrade() {
|
// function handleRequestUpgrade() {
|
||||||
// const btn = document.getElementById("upgrade-request-button");
|
// const btn = document.getElementById("upgrade-request-button");
|
||||||
|
|
4065
account/yarn.lock
4065
account/yarn.lock
File diff suppressed because it is too large
Load Diff
|
@ -40,7 +40,11 @@ const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUs
|
||||||
}, []);
|
}, []);
|
||||||
// TODO put the account url in an imported constant
|
// TODO put the account url in an imported constant
|
||||||
function handleIncomingMessage(event: MessageEvent<any>) {
|
function handleIncomingMessage(event: MessageEvent<any>) {
|
||||||
if (event.origin === "https://account.lingdocs.com" && event.data === "signed in" && popupRef) {
|
if (
|
||||||
|
event.origin === "https://account.lingdocs.com"
|
||||||
|
&& (event.data === "signed in" || event.data === "upgraded" || event.data === "cancelled")
|
||||||
|
&& popupRef
|
||||||
|
) {
|
||||||
loadUser();
|
loadUser();
|
||||||
popupRef.close();
|
popupRef.close();
|
||||||
}
|
}
|
||||||
|
@ -89,6 +93,9 @@ const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUs
|
||||||
function handleOpenSignup() {
|
function handleOpenSignup() {
|
||||||
popupRef = window.open("https://account.lingdocs.com", "account", "height=800,width=500,top=50,left=400");
|
popupRef = window.open("https://account.lingdocs.com", "account", "height=800,width=500,top=50,left=400");
|
||||||
}
|
}
|
||||||
|
function handleOpenUpgrade() {
|
||||||
|
popupRef = window.open("https://account.lingdocs.com/payment/store", "store", "height=800,width=500,top=50,left=400");
|
||||||
|
}
|
||||||
function handlePublish() {
|
function handlePublish() {
|
||||||
setPublishingStatus("publishing");
|
setPublishingStatus("publishing");
|
||||||
publishDictionary().then((response) => {
|
publishDictionary().then((response) => {
|
||||||
|
@ -176,7 +183,8 @@ const Account = ({ user, loadUser }: { user: AT.LingdocsUser | undefined, loadUs
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-outline-secondary"
|
className="btn btn-outline-secondary"
|
||||||
onClick={() => setShowingUpgradePrompt(true)}
|
// onClick={() => setShowingUpgradePrompt(true)}
|
||||||
|
onClick={handleOpenUpgrade}
|
||||||
data-testid="upgradeButton"
|
data-testid="upgradeButton"
|
||||||
>
|
>
|
||||||
<i className="fa fa-level-up-alt"></i> Upgrade Account
|
<i className="fa fa-level-up-alt"></i> Upgrade Account
|
||||||
|
|
Loading…
Reference in New Issue