From 91d405147b4e42cd30e0f53051db5733297b06cb Mon Sep 17 00:00:00 2001 From: Lancelot Owczarczak Date: Tue, 12 Dec 2023 13:33:53 +0100 Subject: [PATCH] :zap: react/components: Change sub-component style in Paywall --- lib/components/Paywall.tsx | 162 ++++++++++++++++++++++++------------- lib/components/index.tsx | 15 +++- 2 files changed, 117 insertions(+), 60 deletions(-) diff --git a/lib/components/Paywall.tsx b/lib/components/Paywall.tsx index 0e231c1..0d22912 100644 --- a/lib/components/Paywall.tsx +++ b/lib/components/Paywall.tsx @@ -1,66 +1,112 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, createContext, useContext, useEffect } from "react"; import { usePolyfire } from "../hooks"; -export interface PaywallProps { - children: React.JSX.Element | React.JSX.Element[] | string; +export interface PaywallRootProps { + children?: React.JSX.Element | (React.JSX.Element | string)[] | string; paymentLink: string; - - loading?: React.JSX.Element | React.JSX.Element[] | string; - paywall?: (paymentLink: string) => React.JSX.Element; } +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); -export function Paywall({ - children, - paymentLink, - loading = "Loading ...", - paywall = (paymentLink) => ( - Click here to upgrade to premium and access the application - ), -}: PaywallProps): 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(); + if (status === "no-paywall") { + return <>{children}; } - }, [status, getAuthID, usage]); - switch (paywallStatus) { - case "loading": - return <>{loading}; - case "no-paywall": + return null; + }, + + NotAuthorized({ children }: PaywallNotAuthorizedProps): React.ReactElement | null { + const { status } = useContext(PaywallContext); + + if (status === "paywall") { return <>{children}; - case "paywall": - return paywall( - `${paymentLink}?client_reference_id=${encodeURIComponent(userId || "")}`, - ); - default: - throw new Error( - "Should be unreachable. If you're getting this error while using polyfire, please submit an issue here: https://github.com/polyfire-ai/polyfire-js/issues/new", - ); - } -} + } + + 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 ad64dc7..7423f06 100644 --- a/lib/components/index.tsx +++ b/lib/components/index.tsx @@ -3,7 +3,14 @@ import { TextTranslated, TextTranslatedProps } from "./TextTranslated"; import { TextSummary, TextSummaryProps } from "./TextSummary"; import { AutoCompleteInput } from "./AutoCompleteInput"; import { ImageGenerated, ImageGeneratedProps } from "./ImageGenerated"; -import { Paywall, PaywallProps } from "./Paywall"; +import { + Paywall, + PaywallRootProps, + PaywallAuthorizedProps, + PaywallNotAuthorizedProps, + PaywallLoadingProps, + PaywallPaymentLinkProps, +} from "./Paywall"; export { TextGenerated, @@ -16,5 +23,9 @@ export { TextTranslated, TextTranslatedProps, Paywall, - PaywallProps, + PaywallRootProps, + PaywallAuthorizedProps, + PaywallNotAuthorizedProps, + PaywallLoadingProps, + PaywallPaymentLinkProps, };