180 lines
5.2 KiB
TypeScript
180 lines
5.2 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";
|
|
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<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 [placementId, setPlacementId] = useState<string>("");
|
|
const [paywallId, setPaywallId] = useState<string>("");
|
|
|
|
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
|
|
)}</${replacementSelector}>`
|
|
);
|
|
}
|
|
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,
|
|
]
|
|
);
|
|
}
|