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"; import locales from "@/locales/locales"; import { ELocalesPlacement, language } from "@/locales"; import { useTranslations } from "@/hooks/translations"; interface IUsePaywallProps { placementKey: EPlacementKeys; localesPlacement?: ELocalesPlacement; } interface IGetTextProps { replacementSelector?: string; color?: string; replacement?: { target: string; replacement: string; }; } export function usePaywall({ placementKey, localesPlacement = ELocalesPlacement.V0, }: IUsePaywallProps) { const locale = language; const { translate } = useTranslations(localesPlacement); 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 [placementId, setPlacementId] = useState(""); const [paywallId, setPaywallId] = useState(""); 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); setPaywallId(paywall.paywallId || ""); setPlacementId(paywall.placementId || ""); dispatch( actions.paywalls.updatePaywall({ [placementKey]: 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]?.paywall) { getPaywallByPlacementKey(placementKey); } else { setPaywall(paywalls[placementKey]?.paywall); setPaywallId(paywalls[placementKey]?.paywallId || ""); setPlacementId(paywalls[placementKey]?.placementId || ""); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [getPaywallByPlacementKey, placementKey, isMustUpdate]); const getText = useCallback( (key: string, options?: IGetTextProps) => { const { replacementSelector = "span", color = "inherit", replacement, } = options || {}; const property = properties.find((property) => property.key === key); if (!property) return ""; let text = property.value; if (locale in locales) { text = `${paywall?.key.replaceAll(".", "_")}.${key.replaceAll( ".", "_" )}`; if (translate(text) === text) { 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) { let replacementValue = colorElement.value; if (locale in locales) { replacementValue = `${paywall?.key.replaceAll( ".", "_" )}.${colorElement.key.replaceAll(".", "_")}`; element = `${paywall?.key.replaceAll(".", "_")}.${key.replaceAll( ".", "_" )}`; if (translate(replacementValue) === replacementValue) { replacementValue = colorElement.value; element = text; } } element = translate(element).replace( colorElement.value, `<${replacementSelector} class="${ property.key }" style="color: ${color}">${translate( replacementValue )}` ); } return parse(element); } if (text && replacement) { return `${translate(text)}`.replace( replacement.target, replacement.replacement ); } return translate(text); }, [locale, paywall?.key, properties, translate] ); return useMemo( () => ({ paywall, isLoading, error, products, properties, placementId, paywallId, getText, }), [ paywall, isLoading, error, products, properties, placementId, paywallId, getText, ] ); }