mirror of
https://github.com/fergalmoran/supanextail.git
synced 2026-01-06 16:45:07 +00:00
New price page + update packages + pnpm instead of npm
Feature/new price page
This commit is contained in:
9
.github/workflows/ci.yml
vendored
9
.github/workflows/ci.yml
vendored
@@ -8,15 +8,18 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
- uses: pnpm/action-setup@v2.0.1
|
||||||
|
with:
|
||||||
|
version: 6.20.3
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: '14.x'
|
node-version: '14.x'
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: pnpm ci
|
||||||
- name: Install Playwright
|
- name: Install Playwright
|
||||||
run: npx playwright install --with-deps
|
run: pnpx playwright install --with-deps
|
||||||
- name: Run Playwright tests
|
- name: Run Playwright tests
|
||||||
run: npm run test
|
run: pnpm run test
|
||||||
env:
|
env:
|
||||||
# This might depend on your test-runner/language binding
|
# This might depend on your test-runner/language binding
|
||||||
PLAYWRIGHT_TEST_BASE_URL: ${{ github.event.deployment_status.target_url }}
|
PLAYWRIGHT_TEST_BASE_URL: ${{ github.event.deployment_status.target_url }}
|
||||||
|
|||||||
@@ -9,27 +9,14 @@ https://dashboard.stripe.com/test/settings/billing/portal
|
|||||||
import { getSub, supabase } from 'utils/supabaseClient';
|
import { getSub, supabase } from 'utils/supabaseClient';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { Switch } from '@headlessui/react';
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import router from 'next/router';
|
import router from 'next/router';
|
||||||
import { useAuth } from 'utils/AuthContext';
|
import { useAuth } from 'utils/AuthContext';
|
||||||
|
|
||||||
const Pricing = (): JSX.Element => {
|
const Pricing = (): JSX.Element => {
|
||||||
const [yearly, setyearly] = useState(false);
|
|
||||||
const { user, session } = useAuth();
|
const { user, session } = useAuth();
|
||||||
const [customerId, setCustomerId] = useState(null);
|
const [customerId, setCustomerId] = useState(null);
|
||||||
const [sub, setSub] = useState(false);
|
const [sub, setSub] = useState(false);
|
||||||
const flat = false; // Switch between subscription system or flat prices
|
|
||||||
|
|
||||||
const portal = () => {
|
|
||||||
axios
|
|
||||||
.post('/api/stripe/customer-portal', {
|
|
||||||
customerId,
|
|
||||||
})
|
|
||||||
.then((result) => {
|
|
||||||
router.push(result.data.url);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (user) {
|
if (user) {
|
||||||
@@ -45,235 +32,117 @@ const Pricing = (): JSX.Element => {
|
|||||||
}
|
}
|
||||||
}, [user]);
|
}, [user]);
|
||||||
|
|
||||||
const Prices = {
|
|
||||||
personal: {
|
|
||||||
monthly: {
|
|
||||||
id: 'price_1J5q2yDMjD0UnVmMXzEWYDnl',
|
|
||||||
desc: 'Personal plan (monthly)',
|
|
||||||
},
|
|
||||||
annually: {
|
|
||||||
id: 'price_1J5q45DMjD0UnVmMQxXHKGAv',
|
|
||||||
desc: 'Personal plan (annually)',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
team: {
|
|
||||||
monthly: {
|
|
||||||
id: 'price_1J5q3GDMjD0UnVmMlHc5Eedq',
|
|
||||||
desc: 'Team plan (monthly)',
|
|
||||||
},
|
|
||||||
annually: {
|
|
||||||
id: 'price_1J5q8zDMjD0UnVmMqsngM91X',
|
|
||||||
desc: 'Team plan (annually)',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
pro: {
|
|
||||||
monthly: {
|
|
||||||
id: 'price_1J6KRuDMjD0UnVmMIItaOdT3',
|
|
||||||
desc: 'Pro plan (monthly)',
|
|
||||||
},
|
|
||||||
annually: {
|
|
||||||
id: 'price_1J5q9VDMjD0UnVmMIQtVDSZ9',
|
|
||||||
desc: 'Pro plan (annually)',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const pricing = {
|
|
||||||
monthly: {
|
|
||||||
personal: '$5/mo',
|
|
||||||
team: '$15/mo',
|
|
||||||
pro: '$35/mo',
|
|
||||||
},
|
|
||||||
yearly: {
|
|
||||||
personal: '$50/yr',
|
|
||||||
team: '$150/yr',
|
|
||||||
pro: '$350/yr',
|
|
||||||
},
|
|
||||||
flat: {
|
|
||||||
personal: '€49',
|
|
||||||
team: '€99',
|
|
||||||
pro: '€149',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = async (e: React.SyntheticEvent<HTMLButtonElement>, priceId: string) => {
|
const handleSubmit = async (e: React.SyntheticEvent<HTMLButtonElement>, priceId: string) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
// Create a Checkout Session. This will redirect the user to the Stripe website for the payment.
|
// Create a Checkout Session. This will redirect the user to the Stripe website for the payment.
|
||||||
axios
|
if (sub) {
|
||||||
.post('/api/stripe/create-checkout-session', {
|
axios
|
||||||
priceId,
|
.post('/api/stripe/customer-portal', {
|
||||||
email: user.email,
|
customerId,
|
||||||
customerId,
|
})
|
||||||
userId: user.id,
|
.then((result) => {
|
||||||
tokenId: session.access_token,
|
router.push(result.data.url);
|
||||||
pay_mode: flat ? 'payment' : 'subscription',
|
});
|
||||||
})
|
} else
|
||||||
.then((result) => router.push(result.data.url));
|
axios
|
||||||
|
.post('/api/stripe/create-checkout-session', {
|
||||||
|
priceId,
|
||||||
|
email: user.email,
|
||||||
|
customerId,
|
||||||
|
userId: user.id,
|
||||||
|
tokenId: session.access_token,
|
||||||
|
pay_mode: 'subscription',
|
||||||
|
})
|
||||||
|
.then((result) => router.push(result.data.url));
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className="w-full mx-auto px-5 py-10 mb-10">
|
<div>
|
||||||
<div className="text-center max-w-xl mx-auto">
|
<div className="container px-6 py-8 mx-auto text-base-100">
|
||||||
<h1 className="text-3xl sm:text-5xl font-bold font-title mb-5">Pricing</h1>
|
<h2 className="text-3xl sm:text-4xl text-center mb-5 mt-0 font-bold font-title text-base-content">
|
||||||
<h3 className="text-lg font-light leading-8 p-3 mb-5">
|
Pricing
|
||||||
This is an example of a pricing page. You can choose a payment method, monthly or yearly.
|
</h2>
|
||||||
</h3>
|
<div className="mt-16 flex flex-col items-center justify-center space-y-8 lg:-mx-4 lg:flex-row lg:items-stretch lg:space-y-0">
|
||||||
</div>
|
<div className="flex flex-col w-full max-w-sm p-8 space-y-8 text-center bg-base-100 rounded-lg lg:mx-4 shadow-lg text-base-content">
|
||||||
{!flat && (
|
<div className="flex-shrink-0">
|
||||||
<div className="flex justify-between max-w-xs m-auto mb-3">
|
<h3 className="inline-flex items-center badge-neutral badge badge-lg bg-base-content text-base-100">
|
||||||
<div>
|
Casual
|
||||||
<p className={`${yearly ? 'text-gray-500' : null}`}>Billed monthly</p>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="flex-shrink-0">
|
||||||
<Switch
|
<span className="pt-2 text-4xl font-bold uppercase">FREE</span>
|
||||||
checked={yearly}
|
</div>
|
||||||
onChange={setyearly}
|
<ul className="flex-1 space-y-4 text-base-content">
|
||||||
className={`bg-primary relative inline-flex flex-shrink-0 h-[38px] w-[74px]
|
<li>Up to 10 projects</li>
|
||||||
border-2 border-transparent rounded-full cursor-pointer transition-colors
|
<li>Up to 20 collaborators</li>
|
||||||
ease-in-out duration-200 focus:outline-none focus-visible:ring-2
|
<li>10Gb of storage</li>
|
||||||
focus-visible:ring-white focus-visible:ring-opacity-75`}
|
|
||||||
>
|
|
||||||
<span className="sr-only">Switch bill</span>
|
|
||||||
<span
|
|
||||||
aria-hidden="true"
|
|
||||||
className={`${yearly ? 'translate-x-9' : 'translate-x-0'}
|
|
||||||
pointer-events-none inline-block h-[34px] w-[34px] rounded-full bg-white shadow-lg transform ring-0 transition ease-in-out duration-200`}
|
|
||||||
/>
|
|
||||||
</Switch>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className={`${!yearly ? 'text-gray-500' : null}`}>Billed annually</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="max-w-4xl mx-auto md:flex space-x-4">
|
|
||||||
<div className="w-full md:w-1/3 md:max-w-none px-8 md:px-10 py-8 md:py-10 mb-3 mx-auto md:my-6 rounded-md shadow-lg shadow-gray-600 md:flex md:flex-col">
|
|
||||||
<div className="w-full flex-grow">
|
|
||||||
<h2 className="text-center font-bold uppercase mb-4">Personal</h2>
|
|
||||||
<h3 className="text-center font-bold text-4xl mb-5">
|
|
||||||
{flat
|
|
||||||
? pricing.flat.personal
|
|
||||||
: yearly
|
|
||||||
? pricing.yearly.personal
|
|
||||||
: pricing.monthly.personal}
|
|
||||||
</h3>
|
|
||||||
<ul className="text-sm px-5 mb-8 text-left">
|
|
||||||
<li className="leading-tight">
|
|
||||||
<i className="mdi mdi-check-bold text-lg" /> A cool feature
|
|
||||||
</li>
|
|
||||||
<li className="leading-tight">
|
|
||||||
<i className="mdi mdi-check-bold text-lg" /> Another feature
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<button className="btn btn-primary">Start for free</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
|
||||||
<button
|
<div className="flex flex-col w-full max-w-sm p-8 space-y-8 text-center bg-base-100 rounded-lg lg:mx-4 shadow-lg text-base-content">
|
||||||
className="btn btn-primary w-full"
|
<div className="flex-shrink-0">
|
||||||
onClick={
|
<h3 className="inline-flex items-center badge-neutral badge badge-lg bg-base-content text-base-100">
|
||||||
user
|
Professional
|
||||||
? sub
|
</h3>
|
||||||
? () => {
|
</div>
|
||||||
portal();
|
<div className="flex-shrink-0">
|
||||||
}
|
<span className="pt-2 text-4xl font-bold uppercase">$4.90</span>
|
||||||
: (e) =>
|
<span>/month</span>
|
||||||
handleSubmit(
|
</div>
|
||||||
e,
|
<ul className="flex-1 space-y-4 text-base-content">
|
||||||
yearly ? Prices.personal.annually.id : Prices.personal.monthly.id
|
<li>Up to 30 projects</li>
|
||||||
)
|
<li>Up to 25 collaborators</li>
|
||||||
: () => {
|
<li>100Gb of storage</li>
|
||||||
router.push('/signup');
|
<li>Real-time collaborations</li>
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{user ? (sub ? 'Upgrade' : 'Buy Now') : 'Register'}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="w-full md:w-1/3 md:max-w-none px-8 md:px-10 py-8 md:py-10 mb-3 mx-auto md:my-6 rounded-md shadow-lg shadow-gray-600 md:flex md:flex-col">
|
|
||||||
<div className="w-full flex-grow">
|
|
||||||
<h2 className="text-center font-bold uppercase mb-4">Team</h2>
|
|
||||||
<h3 className="text-center font-bold text-4xl mb-5">
|
|
||||||
{flat ? pricing.flat.team : yearly ? pricing.yearly.team : pricing.monthly.team}
|
|
||||||
</h3>
|
|
||||||
<ul className="text-sm px-5 mb-8 text-left">
|
|
||||||
<li className="leading-tight">
|
|
||||||
<i className="mdi mdi-check-bold text-lg" /> All basic features
|
|
||||||
</li>
|
|
||||||
<li className="leading-tight">
|
|
||||||
<i className="mdi mdi-check-bold text-lg" /> Dolor sit amet
|
|
||||||
</li>
|
|
||||||
<li className="leading-tight">
|
|
||||||
<i className="mdi mdi-check-bold text-lg" /> Consectetur
|
|
||||||
</li>
|
|
||||||
<li className="leading-tight">
|
|
||||||
<i className="mdi mdi-check-bold text-lg" /> Adipisicing
|
|
||||||
</li>
|
|
||||||
<li className="leading-tight">
|
|
||||||
<i className="mdi mdi-check-bold text-lg" /> Elit repellat
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
{user ? (
|
||||||
|
<button
|
||||||
|
className="btn btn-primary"
|
||||||
|
onClick={(e) => {
|
||||||
|
handleSubmit(e, 'price_1JtHhaDMjD0UnVmM5uCyyrWn');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{sub ? 'Handle subscription' : 'Subscribe'}
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<button className="btn btn-primary" onClick={() => router.push('/login')}>
|
||||||
|
Log in
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
|
||||||
<button
|
<div className="flex flex-col w-full max-w-sm p-8 space-y-8 text-center bg-base-100 rounded-lg lg:mx-4 shadow-lg text-base-content">
|
||||||
className="btn btn-primary w-full"
|
<div className="flex-shrink-0">
|
||||||
onClick={
|
<h3 className="inline-flex items-center badge-neutral badge badge-lg bg-base-content text-base-100">
|
||||||
user
|
Business
|
||||||
? sub
|
</h3>
|
||||||
? () => {
|
</div>
|
||||||
portal();
|
<div className="flex-shrink-0">
|
||||||
}
|
<span className="pt-2 text-4xl font-bold uppercase">$24.90</span>
|
||||||
: (e) =>
|
<span>/month</span>
|
||||||
handleSubmit(e, yearly ? Prices.team.annually.id : Prices.team.monthly.id)
|
</div>
|
||||||
: () => {
|
<ul className="flex-1 space-y-4 text-base-content">
|
||||||
router.push('/signup');
|
<li>Up to 60 projects</li>
|
||||||
}
|
<li>Up to 200 collaborators</li>
|
||||||
}
|
<li>1Tb of storage</li>
|
||||||
>
|
<li>Real-time collaborations</li>
|
||||||
{user ? (sub ? 'Upgrade' : 'Buy Now') : 'Register'}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="w-full md:w-1/3 md:max-w-none px-8 md:px-10 py-8 md:py-10 mb-3 mx-auto md:my-6 rounded-md shadow-lg shadow-gray-600 md:flex md:flex-col">
|
|
||||||
<div className="w-full flex-grow">
|
|
||||||
<h2 className="text-center font-bold uppercase mb-4">Pro</h2>
|
|
||||||
<h3 className="text-center font-bold text-4xl mb-5">
|
|
||||||
{flat ? pricing.flat.pro : yearly ? pricing.yearly.pro : pricing.monthly.pro}
|
|
||||||
</h3>
|
|
||||||
<ul className="text-sm px-5 mb-8 text-left">
|
|
||||||
<li className="leading-tight">
|
|
||||||
<i className="mdi mdi-check-bold text-lg" /> Lorem ipsum
|
|
||||||
</li>
|
|
||||||
<li className="leading-tight">
|
|
||||||
<i className="mdi mdi-check-bold text-lg" /> Dolor sit amet
|
|
||||||
</li>
|
|
||||||
<li className="leading-tight">
|
|
||||||
<i className="mdi mdi-check-bold text-lg" /> Consectetur
|
|
||||||
</li>
|
|
||||||
<li className="leading-tight">
|
|
||||||
<i className="mdi mdi-check-bold text-lg" /> Adipisicing
|
|
||||||
</li>
|
|
||||||
<li className="leading-tight">
|
|
||||||
<i className="mdi mdi-check-bold text-lg" /> Much more...
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
|
||||||
<div className="w-full">
|
{user ? (
|
||||||
<button
|
<button
|
||||||
className="btn btn-primary w-full"
|
className="btn btn-primary"
|
||||||
onClick={
|
onClick={(e) => {
|
||||||
user
|
handleSubmit(e, 'price_1JtHhaDMjD0UnVmM5uCyyrWn');
|
||||||
? sub
|
}}
|
||||||
? () => {
|
>
|
||||||
portal();
|
{sub ? 'Handle subscription' : 'Subscribe'}
|
||||||
}
|
</button>
|
||||||
: (e) =>
|
) : (
|
||||||
handleSubmit(e, yearly ? Prices.pro.annually.id : Prices.pro.monthly.id)
|
<button className="btn btn-primary" onClick={() => router.push('/login')}>
|
||||||
: () => {
|
Log in
|
||||||
router.push('/signup');
|
</button>
|
||||||
}
|
)}
|
||||||
}
|
|
||||||
>
|
|
||||||
{user ? (sub ? 'Upgrade' : 'Buy Now') : 'Register'}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
14638
package-lock.json
generated
14638
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
53
package.json
53
package.json
@@ -10,50 +10,51 @@
|
|||||||
"test": "playwright test"
|
"test": "playwright test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@headlessui/react": "^1.4.1",
|
"@headlessui/react": "^1.4.2",
|
||||||
"@sendgrid/mail": "^7.4.7",
|
"@sendgrid/mail": "^7.6.0",
|
||||||
"@stripe/stripe-js": "^1.18.0",
|
"@stripe/stripe-js": "^1.21.1",
|
||||||
"@supabase/supabase-js": "^1.25.0",
|
"@supabase/gotrue-js": "^1.20.0",
|
||||||
"@types/node": "^16.10.1",
|
"@supabase/supabase-js": "^1.27.0",
|
||||||
"@types/react": "^17.0.24",
|
"@types/node": "^16.11.7",
|
||||||
"@types/react-dom": "^17.0.9",
|
"@types/react": "^17.0.34",
|
||||||
"axios": "^0.21.4",
|
"@types/react-dom": "^17.0.11",
|
||||||
|
"axios": "^0.24.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"daisyui": "^1.14.1",
|
"daisyui": "^1.16.2",
|
||||||
"express-rate-limit": "^5.3.0",
|
"express-rate-limit": "^5.5.1",
|
||||||
"micro": "^9.3.4",
|
"micro": "^9.3.4",
|
||||||
"next": ">=11.1.2",
|
"next": ">=12.0.3",
|
||||||
"next-seo": "^4.28.1",
|
"next-seo": "^4.28.1",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-feather": "^2.0.9",
|
"react-feather": "^2.0.9",
|
||||||
"react-icons": "^4.2.0",
|
"react-icons": "^4.3.1",
|
||||||
"react-toastify": "^8.0.3",
|
"react-toastify": "^8.1.0",
|
||||||
"stripe": "^8.176.0",
|
"stripe": "^8.186.1",
|
||||||
"typescript": "^4.4.3"
|
"typescript": "^4.4.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@next/eslint-plugin-next": "^11.1.2",
|
"@next/eslint-plugin-next": "^12.0.3",
|
||||||
"@playwright/test": "^1.16.0",
|
"@playwright/test": "^1.16.3",
|
||||||
"@types/cors": "^2.8.12",
|
"@types/cors": "^2.8.12",
|
||||||
"@types/express-rate-limit": "^5.1.3",
|
"@types/express-rate-limit": "^5.1.3",
|
||||||
"@types/micro": "^7.3.6",
|
"@types/micro": "^7.3.6",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.32.0",
|
"@typescript-eslint/eslint-plugin": "^5.3.1",
|
||||||
"autoprefixer": "^10.3.6",
|
"autoprefixer": "^10.4.0",
|
||||||
"eslint": "^7.32.0",
|
"eslint": "^8.2.0",
|
||||||
"eslint-config-airbnb": "^18.2.1",
|
"eslint-config-airbnb": "^18.2.1",
|
||||||
"eslint-config-next": "^11.1.2",
|
"eslint-config-next": "^12.0.3",
|
||||||
"eslint-config-prettier": "^8.3.0",
|
"eslint-config-prettier": "^8.3.0",
|
||||||
"eslint-import-resolver-alias": "^1.1.2",
|
"eslint-import-resolver-alias": "^1.1.2",
|
||||||
"eslint-plugin-cypress": "^2.12.1",
|
"eslint-plugin-cypress": "^2.12.1",
|
||||||
"eslint-plugin-import": "^2.24.2",
|
"eslint-plugin-import": "^2.25.2",
|
||||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
"eslint-plugin-react": "^7.26.0",
|
"eslint-plugin-react": "^7.26.1",
|
||||||
"eslint-plugin-react-hooks": "^4.2.0",
|
"eslint-plugin-react-hooks": "^4.3.0",
|
||||||
"eslint-plugin-simple-import-sort": "^7.0.0",
|
"eslint-plugin-simple-import-sort": "^7.0.0",
|
||||||
"postcss": "^8.3.8",
|
"postcss": "^8.3.11",
|
||||||
"prettier": "^2.4.1",
|
"prettier": "^2.4.1",
|
||||||
"tailwindcss": "^2.2.16"
|
"tailwindcss": "^2.2.19"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,7 +86,6 @@ export async function getServerSideProps(context: NextPageContext) {
|
|||||||
.eq('id', user.id)
|
.eq('id', user.id)
|
||||||
.single();
|
.single();
|
||||||
|
|
||||||
console.log(plan);
|
|
||||||
// Check the subscription plan. If it doesnt exist, return null
|
// Check the subscription plan. If it doesnt exist, return null
|
||||||
const subscription = plan?.subscription
|
const subscription = plan?.subscription
|
||||||
? await stripe.subscriptions.retrieve(plan.subscription)
|
? await stripe.subscriptions.retrieve(plan.subscription)
|
||||||
|
|||||||
5035
pnpm-lock.yaml
generated
Normal file
5035
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -36,8 +36,7 @@
|
|||||||
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
|
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
|
||||||
/* Module Resolution Options */
|
/* Module Resolution Options */
|
||||||
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||||
"baseUrl": "./", /* Base directory to resolve non-absolute module names. */ /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
"baseUrl": "./", /* Base directory to resolve non-absolute module names. */ /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
|
||||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||||
// "types": [], /* Type declaration files to be included in compilation. */
|
// "types": [], /* Type declaration files to be included in compilation. */
|
||||||
"allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
"allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||||
@@ -47,8 +46,7 @@
|
|||||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||||
"inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
"inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||||
"inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ /* Experimental Options */
|
"inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ /* Experimental Options */// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
|
||||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||||
/* Advanced Options */
|
/* Advanced Options */
|
||||||
"skipLibCheck": true, /* Skip type checking of declaration files. */
|
"skipLibCheck": true, /* Skip type checking of declaration files. */
|
||||||
@@ -61,7 +59,8 @@
|
|||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true
|
"isolatedModules": true,
|
||||||
|
"incremental": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"next-env.d.ts",
|
"next-env.d.ts",
|
||||||
|
|||||||
1
tsconfig.tsbuildinfo
Normal file
1
tsconfig.tsbuildinfo
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user