w-aura/src/components/WallpaperPage/index.tsx

127 lines
4.1 KiB
TypeScript

import { useCallback } from "react";
import { useTranslation } from "react-i18next";
import { useAuth } from "@/auth";
import { useApi, useApiCall, Assets, DailyForecasts } from "@/api";
import { saveFile, buildFilename } from "./utils";
import Loader, { LoaderColor } from "../Loader";
import styles from "./styles.module.css";
import { useSelector } from "react-redux";
import { selectors } from "@/store";
import {
getCategoryIdByZodiacSign,
getZodiacSignByDate,
} from "@/services/zodiac-sign";
import { Zodiac, ZodiacParagraph } from "@/api/resources/Zodiacs";
type Forecasts = DailyForecasts.Forecast[];
type PersonalAssets = Assets.Asset[];
interface WallpaperData {
assets: PersonalAssets;
forecasts: Forecasts;
zodiac: Zodiac;
}
function getZodiacParagraphs(
paragraphs: ZodiacParagraph[],
depth = 0
): JSX.Element[] {
depth++;
if (!paragraphs) {
return [];
}
function getTypeOfContent(content: string[] | ZodiacParagraph[]) {
if (Array.isArray(content) && content.length > 0) {
return typeof content[0];
}
}
return paragraphs.map((paragraph, index) => {
const Headline = `h${depth}` as keyof JSX.IntrinsicElements;
return (
<div className={styles["wallpaper-paragraph"]} key={index}>
<Headline
className={`${styles["wallpaper-paragraph__title"]} ${
depth % 2 === 0 ? styles["wallpaper-paragraph__title--white"] : ""
}`}
>
{paragraph.title}
</Headline>
{getTypeOfContent(paragraph.content) === "string"
? paragraph.content.map((content, _index) => (
<p key={_index}>{content as string}</p>
))
: getZodiacParagraphs(paragraph.content as ZodiacParagraph[], depth)}
</div>
);
});
}
function WallpaperPage(): JSX.Element {
const api = useApi();
const { i18n } = useTranslation();
const locale = i18n.language;
const token = useSelector(selectors.selectToken);
const {
user,
// token
} = useAuth();
const birthdate = useSelector(selectors.selectBirthdate);
const zodiacSign = getZodiacSignByDate(birthdate);
const category = user?.profile.sign?.sign || "";
const loadData = useCallback(async () => {
const { asset_categories } = await api.getAssetCategories({ locale });
const categoryId = getCategoryIdByZodiacSign(zodiacSign, asset_categories);
return Promise.all([
api.getZodiacs({ zodiac: zodiacSign.toLowerCase(), token }),
api.getAssets({ category: String(categoryId || "1") }),
api.getDailyForecasts({ token }),
]).then(([{ zodiac }, { assets }, { user_daily_forecast }]) => ({
zodiac,
assets,
forecasts: user_daily_forecast.forecasts,
}));
}, [api, token, locale, zodiacSign]);
const { data, isPending } = useApiCall<WallpaperData>(loadData);
const asset = data ? data.assets.at(0) : null;
const zodiacInfo = data ? data.zodiac : null;
const handleClick = () =>
asset &&
saveFile(asset.url.replace("http://", "https://"), buildFilename(category));
return (
<section className={styles["wallpaper-page"]}>
<div
className={styles["wallpaper-image"]}
style={{ backgroundImage: `url(${asset?.url})` }}
>
{asset ? (
<div className={styles["btn-download"]} onClick={handleClick} />
) : null}
{isPending ? <Loader color={LoaderColor.White} /> : null}
</div>
<div className={styles["wallpaper-content"]}>
{isPending ? null : (
<>
<div className={styles["zodiac-metas"]}>
{zodiacInfo?.metas.map((meta, index) => (
<div key={index} className={styles["zodiac-meta"]}>
<p className={styles["zodiac-meta-label"]}>{meta.label}</p>
<p className={styles["zodiac-meta-value"]}>{meta.value}</p>
</div>
))}
</div>
<div className={styles["wallpaper-forecast"]}>
{getZodiacParagraphs(zodiacInfo?.paragraphs || [])}
</div>
</>
)}
</div>
</section>
);
}
export default WallpaperPage;