payments
This commit is contained in:
parent
c2f4254249
commit
21aa045d2a
|
@ -1,5 +1,12 @@
|
||||||
{
|
{
|
||||||
"sub": "ab776d6d-f324-4fa7-a728-7587d5215481",
|
"firstName": "John",
|
||||||
|
"lastName": "Doe",
|
||||||
|
"email": "john@example.com",
|
||||||
|
"sub": "ab776d6d-f324-4fa7-4k21-7587d5215481",
|
||||||
"tier": 1,
|
"tier": 1,
|
||||||
"subscribedUntil": "0001-01-01T00:00:00Z"
|
"subscribedUntil": "0001-01-01T00:00:00Z",
|
||||||
|
"subscriptionStatus": "active",
|
||||||
|
"subscriptionCancelAt": "2021-04-21T00:00:00Z",
|
||||||
|
"subscriptionCancelAtPeriodEnd": true,
|
||||||
|
"stripeCustomerId": "cus_J0iYnAp6LRgsTI"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import dayjs from "dayjs";
|
||||||
import Layout from "../components/Layout";
|
import Layout from "../components/Layout";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
@ -5,9 +6,17 @@ import ky from "ky/umd";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
const plans = [
|
const plans = [
|
||||||
{ id: "initial_free", stripe: null, name: "Free", price: 0, description: "Unlimited bandwidth with throttled speed" },
|
{
|
||||||
|
id: "initial_free",
|
||||||
|
tier: 1,
|
||||||
|
stripe: null,
|
||||||
|
name: "Free",
|
||||||
|
price: 0,
|
||||||
|
description: "Unlimited bandwidth with throttled speed",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "initial_plus",
|
id: "initial_plus",
|
||||||
|
tier: 2,
|
||||||
stripe: "price_1IO6FpIzjULiPWN6XHIG5mU9",
|
stripe: "price_1IO6FpIzjULiPWN6XHIG5mU9",
|
||||||
name: "Skynet Plus",
|
name: "Skynet Plus",
|
||||||
price: 5,
|
price: 5,
|
||||||
|
@ -15,6 +24,7 @@ const plans = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "initial_pro",
|
id: "initial_pro",
|
||||||
|
tier: 3,
|
||||||
stripe: "price_1IO6FpIzjULiPWN6xYjmUuGb",
|
stripe: "price_1IO6FpIzjULiPWN6xYjmUuGb",
|
||||||
name: "Skynet Pro",
|
name: "Skynet Pro",
|
||||||
price: 20,
|
price: 20,
|
||||||
|
@ -22,6 +32,7 @@ const plans = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "initial_extreme",
|
id: "initial_extreme",
|
||||||
|
tier: 4,
|
||||||
stripe: "price_1IO6FpIzjULiPWN636iFN02j",
|
stripe: "price_1IO6FpIzjULiPWN636iFN02j",
|
||||||
name: "Skynet Extreme",
|
name: "Skynet Extreme",
|
||||||
price: 80,
|
price: 80,
|
||||||
|
@ -30,6 +41,7 @@ const plans = [
|
||||||
];
|
];
|
||||||
|
|
||||||
const fetcher = (url) => fetch(url).then((r) => r.json());
|
const fetcher = (url) => fetch(url).then((r) => r.json());
|
||||||
|
const apiPrefix = process.env.NODE_ENV === "development" ? "/api/stubs" : "";
|
||||||
|
|
||||||
const ActiveBadge = () => {
|
const ActiveBadge = () => {
|
||||||
return (
|
return (
|
||||||
|
@ -40,11 +52,9 @@ const ActiveBadge = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Payments() {
|
export default function Payments() {
|
||||||
const { data: user } = useSWR("/user", fetcher);
|
const { data: user } = useSWR(`${apiPrefix}/user`, fetcher);
|
||||||
const { data: subscription } = useSWR("/api/stripe/subscription", fetcher);
|
const [selectedPlan, setSelectedPlan] = useState(plans[0]);
|
||||||
const [selectedPlanId, setSelectedPlanId] = useState("initial_free");
|
const activePlan = plans.find(({ tier }) => user?.tier === tier);
|
||||||
const [activePlanId, setActivePlanId] = useState(null);
|
|
||||||
const selectedPlan = plans.find(({ id }) => selectedPlanId === id);
|
|
||||||
const handleSubscribe = async () => {
|
const handleSubscribe = async () => {
|
||||||
try {
|
try {
|
||||||
const price = selectedPlan.stripe;
|
const price = selectedPlan.stripe;
|
||||||
|
@ -56,12 +66,6 @@ export default function Payments() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const plan = plans.find(({ stripe }) => subscription?.plan?.id === stripe);
|
|
||||||
|
|
||||||
setActivePlanId(plan);
|
|
||||||
}, [subscription, setActivePlanId]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout title="Payments">
|
<Layout title="Payments">
|
||||||
<div className="bg-white rounded-lg shadow px-5 py-6 sm:px-6">
|
<div className="bg-white rounded-lg shadow px-5 py-6 sm:px-6">
|
||||||
|
@ -77,8 +81,17 @@ export default function Payments() {
|
||||||
<div className="bg-white overflow-hidden shadow rounded-lg">
|
<div className="bg-white overflow-hidden shadow rounded-lg">
|
||||||
<div className="px-4 py-5 sm:p-6">
|
<div className="px-4 py-5 sm:p-6">
|
||||||
<dt className="text-sm font-medium text-gray-500 truncate">Subscription status</dt>
|
<dt className="text-sm font-medium text-gray-500 truncate">Subscription status</dt>
|
||||||
<dd className="mt-1 text-3xl font-semibold text-gray-900 capitalize">{subscription?.status ?? "—"}</dd>
|
<dd className="mt-1 text-3xl font-semibold text-gray-900 capitalize">
|
||||||
|
{user?.subscriptionStatus ?? "—"}
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
{user?.subscriptionCancelAtPeriodEnd && (
|
||||||
|
<div className="bg-gray-50 px-4 py-4 sm:px-6">
|
||||||
|
<div className="text-sm">
|
||||||
|
Your plan will be cancelled on {dayjs(user.subscriptionCancelAt).format("D MMM YYYY")}.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* <div className="flex flex-col bg-white overflow-hidden shadow rounded-lg">
|
{/* <div className="flex flex-col bg-white overflow-hidden shadow rounded-lg">
|
||||||
|
@ -112,6 +125,7 @@ export default function Payments() {
|
||||||
<div className="text-sm">All paid up!</div>
|
<div className="text-sm">All paid up!</div>
|
||||||
</div>
|
</div>
|
||||||
</div> */}
|
</div> */}
|
||||||
|
|
||||||
<div className="bg-white overflow-hidden shadow rounded-lg">
|
<div className="bg-white overflow-hidden shadow rounded-lg">
|
||||||
<div className="px-4 py-5 sm:p-6">
|
<div className="px-4 py-5 sm:p-6">
|
||||||
<dt className="text-sm font-medium text-gray-500 truncate">asdas</dt>
|
<dt className="text-sm font-medium text-gray-500 truncate">asdas</dt>
|
||||||
|
@ -149,11 +163,11 @@ export default function Payments() {
|
||||||
type="radio"
|
type="radio"
|
||||||
className="h-4 w-4 text-orange-500 cursor-pointer focus:ring-gray-900 border-gray-300"
|
className="h-4 w-4 text-orange-500 cursor-pointer focus:ring-gray-900 border-gray-300"
|
||||||
aria-describedby="plan-option-pricing-0 plan-option-limit-0"
|
aria-describedby="plan-option-pricing-0 plan-option-limit-0"
|
||||||
checked={plan.id === selectedPlanId}
|
checked={plan === selectedPlan}
|
||||||
onChange={() => console.log(plan.id) || setSelectedPlanId(plan.id)}
|
onChange={() => console.log(plan.name) || setSelectedPlan(plan)}
|
||||||
/>
|
/>
|
||||||
<span className="ml-3 font-medium text-gray-900">{plan.name}</span>
|
<span className="ml-3 font-medium text-gray-900">{plan.name}</span>
|
||||||
{activePlanId === plan.id && <ActiveBadge />}
|
{activePlan === plan && <ActiveBadge />}
|
||||||
</label>
|
</label>
|
||||||
<p id="plan-option-pricing-0" className="ml-6 pl-1 text-sm md:ml-0 md:pl-0 md:text-center">
|
<p id="plan-option-pricing-0" className="ml-6 pl-1 text-sm md:ml-0 md:pl-0 md:text-center">
|
||||||
{/* On: "text-orange-900", Off: "text-gray-900" */}
|
{/* On: "text-orange-900", Off: "text-gray-900" */}
|
||||||
|
@ -175,7 +189,7 @@ export default function Payments() {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleSubscribe}
|
onClick={handleSubscribe}
|
||||||
disabled={activePlanId === selectedPlanId}
|
disabled={activePlan === selectedPlan}
|
||||||
className="bg-green-800 disabled:bg-gray-300 disabled:text-gray-400 border border-transparent rounded-md shadow-sm py-2 px-4 inline-flex justify-center text-sm font-medium text-white hover:bg-green-900 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-900"
|
className="bg-green-800 disabled:bg-gray-300 disabled:text-gray-400 border border-transparent rounded-md shadow-sm py-2 px-4 inline-flex justify-center text-sm font-medium text-white hover:bg-green-900 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-900"
|
||||||
>
|
>
|
||||||
Subscribe
|
Subscribe
|
||||||
|
|
Reference in New Issue