diff --git a/lib/components/Paywall.tsx b/lib/components/Paywall.tsx new file mode 100644 index 0000000..0d22912 --- /dev/null +++ b/lib/components/Paywall.tsx @@ -0,0 +1,112 @@ +import React, { useState, createContext, useContext, useEffect } from "react"; +import { usePolyfire } from "../hooks"; + +export interface PaywallRootProps { + children?: React.JSX.Element | (React.JSX.Element | string)[] | string; + paymentLink: string; +} +export interface PaywallAuthorizedProps { + children?: React.JSX.Element | (React.JSX.Element | string)[] | string; +} +export interface PaywallNotAuthorizedProps { + children?: React.JSX.Element | (React.JSX.Element | string)[] | string; +} +export interface PaywallLoadingProps { + children?: React.JSX.Element | (React.JSX.Element | string)[] | string; +} +export interface PaywallPaymentLinkProps extends React.HTMLAttributes { + children?: React.JSX.Element | (React.JSX.Element | string)[] | string; +} + +const PaywallContext = createContext<{ + status: "loading" | "paywall" | "no-paywall"; + userId?: string; + paymentLinkBase?: string; +}>({ status: "loading" }); + +export const Paywall = { + Root({ children, paymentLink }: PaywallRootProps): React.ReactElement { + const { + auth: { + status, + user: { getAuthID, usage }, + }, + } = usePolyfire(); + + const [paywallStatus, setPaywallStatus] = useState<"loading" | "paywall" | "no-paywall">( + "loading", + ); + const [userId, setUserId] = useState(); + + useEffect(() => { + if (status === "authenticated") { + const updateUsage = async () => { + const userId = await getAuthID(); + setUserId(userId); + + const userUsage = await usage(); + if (userUsage.rateLimit === undefined || userUsage.rateLimit === null) { + setPaywallStatus("no-paywall"); + } else { + setPaywallStatus( + userUsage.rateLimit <= userUsage.usage ? "paywall" : "no-paywall", + ); + } + }; + + updateUsage(); + } + }, [status, getAuthID, usage]); + + return ( + + {children} + + ); + }, + + Authorized({ children }: PaywallAuthorizedProps): React.ReactElement | null { + const { status } = useContext(PaywallContext); + + if (status === "no-paywall") { + return <>{children}; + } + + return null; + }, + + NotAuthorized({ children }: PaywallNotAuthorizedProps): React.ReactElement | null { + const { status } = useContext(PaywallContext); + + if (status === "paywall") { + return <>{children}; + } + + return null; + }, + + Loading({ children }: PaywallLoadingProps): React.ReactElement | null { + const { status } = useContext(PaywallContext); + + if (status === "loading") { + return <>{children}; + } + + return null; + }, + + PaymentLink({ children, ...props }: PaywallPaymentLinkProps): React.ReactElement { + const { paymentLinkBase, userId } = useContext(PaywallContext); + + return ( + + {children} + + ); + }, +}; diff --git a/lib/components/index.tsx b/lib/components/index.tsx index 84cbf57..50c5f12 100644 --- a/lib/components/index.tsx +++ b/lib/components/index.tsx @@ -4,6 +4,14 @@ import { TextSummary, TextSummaryProps } from "./TextSummary"; import { AutoCompleteInput, AutoCompleteInputProps } from "./AutoCompleteInput"; import { AutoCompleteTextArea, AutoCompleteTextAreaProps } from "./AutoCompleteTextArea"; import { ImageGenerated, ImageGeneratedProps } from "./ImageGenerated"; +import { + Paywall, + PaywallRootProps, + PaywallAuthorizedProps, + PaywallNotAuthorizedProps, + PaywallLoadingProps, + PaywallPaymentLinkProps, +} from "./Paywall"; import { Login, LoginProps } from "./Login"; export { @@ -19,6 +27,12 @@ export { ImageGeneratedProps, TextTranslated, TextTranslatedProps, + Paywall, + PaywallRootProps, + PaywallAuthorizedProps, + PaywallNotAuthorizedProps, + PaywallLoadingProps, + PaywallPaymentLinkProps, Login, - LoginProps, + LoginProps };