feat(dashboard-v2): introduce PlansProvider
This commit is contained in:
parent
020fec5ce1
commit
8eacf13806
|
@ -0,0 +1,7 @@
|
||||||
|
import { createContext } from "react";
|
||||||
|
|
||||||
|
export const PlansContext = createContext({
|
||||||
|
plans: [],
|
||||||
|
limits: [],
|
||||||
|
error: null,
|
||||||
|
});
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import useSWR from "swr";
|
||||||
|
|
||||||
|
import freePlan from "../../lib/tiers";
|
||||||
|
|
||||||
|
import { PlansContext } from "./PlansContext";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOTE: this function heavily relies on the fact that each Plan's `tier`
|
||||||
|
* property corresponds to the plan's index in UserLimits array in
|
||||||
|
* skynet-accounts code.
|
||||||
|
*
|
||||||
|
* @see https://github.com/SkynetLabs/skynet-accounts/blob/7337e740b71b77e6d08016db801e293b8ad81abc/database/user.go#L53-L101
|
||||||
|
*/
|
||||||
|
const aggregatePlansAndLimits = (plans, limits) => {
|
||||||
|
const sortedPlans = [freePlan, ...plans].sort((planA, planB) => planA.tier - planB.tier);
|
||||||
|
|
||||||
|
// Decorate each plan with its corresponding limits data, if available.
|
||||||
|
if (limits?.length) {
|
||||||
|
return sortedPlans.map((plan) => ({ ...plan, limits: limits[plan.tier] || null }));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we don't have the limits data yet, set just return the plans.
|
||||||
|
|
||||||
|
return sortedPlans;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PlansProvider = ({ children }) => {
|
||||||
|
const { data: rawPlans, error: plansError } = useSWR("stripe/prices");
|
||||||
|
const { data: limits, error: limitsError } = useSWR("limits");
|
||||||
|
|
||||||
|
const [plans, setPlans] = useState([freePlan]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (plansError || limitsError) {
|
||||||
|
setLoading(false);
|
||||||
|
setError(plansError || limitsError);
|
||||||
|
} else if (rawPlans) {
|
||||||
|
setLoading(false);
|
||||||
|
setPlans(aggregatePlansAndLimits(rawPlans, limits?.userLimits));
|
||||||
|
}
|
||||||
|
}, [rawPlans, limits, plansError, limitsError]);
|
||||||
|
|
||||||
|
return <PlansContext.Provider value={{ plans, error, loading }}>{children}</PlansContext.Provider>;
|
||||||
|
};
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "./PlansProvider";
|
||||||
|
export * from "./usePlans";
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { useContext } from "react";
|
||||||
|
|
||||||
|
import { PlansContext } from "./PlansContext";
|
||||||
|
|
||||||
|
export const usePlans = () => useContext(PlansContext);
|
Reference in New Issue