import { useApi } from "@/api"; import { EPlacementKeys, IPaywall } from "@/api/resources/Paywall"; import { actions, selectors } from "@/store"; import { useCallback, useEffect, useMemo, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import parse from "html-react-parser"; import { defaultPaywalls } from "./defaultPaywalls"; interface IUsePaywallProps { placementKey: EPlacementKeys; } interface IGetTextProps { replacementSelector?: string; color?: string; replacement?: { target: string; replacement: string; }; } export function usePaywall({ placementKey }: IUsePaywallProps) { const api = useApi(); const dispatch = useDispatch(); const token = useSelector(selectors.selectToken); const [paywall, setPaywall] = useState(); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(false); const products = useMemo(() => paywall?.products || [], [paywall?.products]); const properties = useMemo( () => paywall?.properties || [], [paywall?.properties] ); const isMustUpdate = useSelector(selectors.selectPaywallsIsMustUpdate); const paywalls = useSelector(selectors.selectPaywalls); const getPaywallByPlacementKey = useCallback( async (placementKey: EPlacementKeys) => { try { setIsLoading(true); setError(false); const paywall = await api.getPaywallByPlacementKey({ placementKey, token, }); if ("paywall" in paywall && paywall.paywall) { setPaywall(paywall.paywall); dispatch( actions.paywalls.updatePaywall({ [placementKey]: paywall.paywall, }) ); dispatch( actions.paywalls.updateIsMustUpdate({ [placementKey]: false, }) ); } } catch (error) { console.error(error); setError(true); setPaywall(defaultPaywalls[placementKey]); } finally { setIsLoading(false); } }, [api, dispatch, token] ); useEffect(() => { if (isMustUpdate[placementKey] || !paywalls[placementKey]) { getPaywallByPlacementKey(placementKey); } else { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion setPaywall(paywalls[placementKey]!); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [getPaywallByPlacementKey, placementKey, isMustUpdate]); const getText = useCallback( ( key: string, { replacementSelector = "span", color = "inherit", replacement, }: IGetTextProps ) => { const property = properties.find((property) => property.key === key); if (!property) return ""; const text = property.value; const colorElements = properties.filter((property) => property.key.includes(`${key}.color`) ); if (text && colorElements.length) { let element = text; for (const colorElement of colorElements) { element = element.replace( colorElement.value, `<${replacementSelector} class="${property.key}" style="color: ${color}">${colorElement.value}` ); } return parse(element); } if (text && replacement) { return text.replace(replacement.target, replacement.replacement); } return text; }, [properties] ); return useMemo( () => ({ paywall, isLoading, error, products, properties, getText, }), [error, isLoading, paywall, products, properties, getText] ); }