w-aura/src/hooks/paywall/usePaywall.tsx
2024-05-27 20:43:33 +00:00

125 lines
3.6 KiB
TypeScript

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<IPaywall>();
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}</${replacementSelector}>`
);
}
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]
);
}