Skip to content

Commit

Permalink
⚡ react/components: Change sub-component style in Paywall
Browse files Browse the repository at this point in the history
  • Loading branch information
lowczarc committed Dec 12, 2023
1 parent 5354cde commit 91d4051
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 60 deletions.
162 changes: 104 additions & 58 deletions lib/components/Paywall.tsx
Original file line number Diff line number Diff line change
@@ -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<HTMLElement> {
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<string>();

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 (
<PaywallContext.Provider
value={{ status: paywallStatus, userId, paymentLinkBase: paymentLink }}
>
{children}
</PaywallContext.Provider>
);
},

Authorized({ children }: PaywallAuthorizedProps): React.ReactElement | null {
const { status } = useContext(PaywallContext);

export function Paywall({
children,
paymentLink,
loading = "Loading ...",
paywall = (paymentLink) => (
<a href={paymentLink}>Click here to upgrade to premium and access the application</a>
),
}: PaywallProps): React.ReactElement {
const {
auth: {
status,
user: { getAuthID, usage },
},
} = usePolyfire();

const [paywallStatus, setPaywallStatus] = useState<"loading" | "paywall" | "no-paywall">(
"loading",
);
const [userId, setUserId] = useState<string>();

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 (
<a
{...props}
href={`${paymentLinkBase}?client_reference_id=${encodeURIComponent(userId || "")}`}
>
{children}
</a>
);
},
};
15 changes: 13 additions & 2 deletions lib/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -16,5 +23,9 @@ export {
TextTranslated,
TextTranslatedProps,
Paywall,
PaywallProps,
PaywallRootProps,
PaywallAuthorizedProps,
PaywallNotAuthorizedProps,
PaywallLoadingProps,
PaywallPaymentLinkProps,
};

0 comments on commit 91d4051

Please sign in to comment.