feat: add EnergyVampirism, MoonPhaseTracker, NameHoroscope, PredictionMoon, Thermal, WallpapersZodiacSign,
This commit is contained in:
parent
bb815df7f7
commit
2a59a7e597
19
public/ButtonReload.svg
Normal file
19
public/ButtonReload.svg
Normal file
@ -0,0 +1,19 @@
|
||||
<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_b_1_8)">
|
||||
<circle cx="36" cy="36" r="36" fill="white" fill-opacity="0.45"/>
|
||||
</g>
|
||||
<g clip-path="url(#clip0_1_8)">
|
||||
<path d="M22.1944 36.0539C22.8689 36.0539 23.3888 35.534 23.3888 34.8595V33.5246C23.3888 31.1077 25.0328 29.534 27.5761 29.534H38.5363V32.8361C38.5363 33.3981 38.8736 33.7213 39.4497 33.7213C39.7025 33.7213 39.9696 33.623 40.1663 33.4543L45.4777 29.0562C45.9274 28.6909 45.9556 28.1148 45.4777 27.7213L40.1663 23.3091C39.9696 23.1405 39.7025 23.0562 39.4497 23.0562C38.8736 23.0562 38.5363 23.3653 38.5363 23.9415V27.2014H27.8009C23.6838 27.2014 21 29.548 21 33.356V34.8595C21 35.534 21.5059 36.0539 22.1944 36.0539ZM49.8056 35.0562C49.1171 35.0562 48.6113 35.5621 48.6113 36.2506V37.5855C48.6113 40.0023 46.9673 41.5621 44.4098 41.5621H33.4496V38.3022C33.4496 37.726 33.1265 37.4168 32.5504 37.4168C32.2834 37.4168 32.0305 37.5011 31.8197 37.6698L26.5082 42.068C26.0585 42.4614 26.0445 43.0234 26.5082 43.4028L31.8197 47.815C32.0305 47.9836 32.2834 48.0819 32.5504 48.0819C33.1265 48.0819 33.4496 47.7587 33.4496 47.1967V43.9086H44.185C48.3162 43.9086 51 41.5621 51 37.7541V36.2506C51 35.5621 50.4801 35.0562 49.8056 35.0562Z" fill="black" fill-opacity="0.6"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_b_1_8" x="-10" y="-10" width="92" height="92" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feGaussianBlur in="BackgroundImageFix" stdDeviation="5"/>
|
||||
<feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_1_8"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_backgroundBlur_1_8" result="shape"/>
|
||||
</filter>
|
||||
<clipPath id="clip0_1_8">
|
||||
<rect width="30" height="25.0819" fill="white" transform="translate(21 23)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
19
public/ButtonSave.svg
Normal file
19
public/ButtonSave.svg
Normal file
@ -0,0 +1,19 @@
|
||||
<svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_b_257_339)">
|
||||
<circle cx="36" cy="36" r="36" fill="white" fill-opacity="0.45"/>
|
||||
</g>
|
||||
<g clip-path="url(#clip0_257_339)">
|
||||
<path d="M26.307 53.4901H45.693C49.2253 53.4901 51 51.7324 51 48.2506V31.3831C51 27.9014 49.2253 26.1436 45.693 26.1436H40.9775V28.8648H45.6423C47.3155 28.8648 48.2788 29.7774 48.2788 31.5352V48.0986C48.2788 49.8563 47.3155 50.7689 45.6423 50.7689H26.3408C24.6507 50.7689 23.7211 49.8563 23.7211 48.0986V31.5352C23.7211 29.7774 24.6507 28.8648 26.3408 28.8648H31.0225V26.1436H26.307C22.7746 26.1436 21 27.9014 21 31.3831V48.2506C21 51.7324 22.7746 53.4901 26.307 53.4901ZM35.9915 42.369C36.3465 42.369 36.6338 42.2676 36.9718 41.9296L42.6845 36.4027C42.938 36.1494 43.0902 35.8788 43.0902 35.5239C43.0902 34.8309 42.5493 34.3408 41.8564 34.3408C41.5183 34.3408 41.1803 34.4761 40.9436 34.7465L38.3747 37.4676L37.2422 38.6675L37.3436 36.1324V18.3183C37.3436 17.6084 36.7183 17 35.9915 17C35.2648 17 34.6563 17.6084 34.6563 18.3183V36.1324L34.7577 38.6675L33.6084 37.4676L31.0563 34.7465C30.8197 34.4761 30.4479 34.3408 30.1268 34.3408C29.4169 34.3408 28.9098 34.8309 28.9098 35.5239C28.9098 35.8788 29.0451 36.1494 29.2986 36.4027L35.0113 41.9296C35.3662 42.2676 35.6535 42.369 35.9915 42.369Z" fill="black" fill-opacity="0.6"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_b_257_339" x="-10" y="-10" width="92" height="92" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feGaussianBlur in="BackgroundImageFix" stdDeviation="5"/>
|
||||
<feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_257_339"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_backgroundBlur_257_339" result="shape"/>
|
||||
</filter>
|
||||
<clipPath id="clip0_257_339">
|
||||
<rect width="30" height="37.3352" fill="white" transform="translate(21 17)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
@ -8,9 +8,52 @@ const dateFormatter = (date: string): string => {
|
||||
.join("-");
|
||||
};
|
||||
|
||||
interface IBestiesHoroscopePayload {
|
||||
birthDate: string;
|
||||
sign: string;
|
||||
}
|
||||
|
||||
interface IMyHoroscopePayload {
|
||||
birthDate: string;
|
||||
sign: string;
|
||||
period: string;
|
||||
}
|
||||
|
||||
interface IPredictionMoonsPayload {
|
||||
birthDate: string;
|
||||
sign: string;
|
||||
period: string;
|
||||
}
|
||||
|
||||
interface IThermalPayload {
|
||||
birthDate: string;
|
||||
sign: string;
|
||||
period: string;
|
||||
}
|
||||
|
||||
interface IMoonPhaseTrackerPayload {
|
||||
birthDate: string;
|
||||
sign: string;
|
||||
period: string;
|
||||
}
|
||||
|
||||
interface IEnergyVampirismPayload {
|
||||
birthDate: string;
|
||||
sign: string;
|
||||
period: string;
|
||||
}
|
||||
|
||||
export type AIRequestPayload =
|
||||
| IBestiesHoroscopePayload
|
||||
| IPredictionMoonsPayload
|
||||
| IMyHoroscopePayload
|
||||
| IThermalPayload
|
||||
| IMoonPhaseTrackerPayload
|
||||
| IEnergyVampirismPayload;
|
||||
|
||||
export interface Payload {
|
||||
promptKey: string;
|
||||
aiRequest: IAIRequestPayload;
|
||||
aiRequest: AIRequestPayload;
|
||||
token: string;
|
||||
}
|
||||
|
||||
@ -19,11 +62,6 @@ export interface PayloadGet {
|
||||
token: string;
|
||||
}
|
||||
|
||||
interface IAIRequestPayload {
|
||||
birthDate: string;
|
||||
sign: string;
|
||||
}
|
||||
|
||||
export interface Response {
|
||||
ai_request: IAiResponse;
|
||||
meta: IMeta;
|
||||
@ -74,18 +112,42 @@ export interface IAIRequest {
|
||||
};
|
||||
}
|
||||
|
||||
const getBody = (aiRequest: AIRequestPayload, promptKey: string): string => {
|
||||
if (["horoscope_besties"].includes(promptKey)) {
|
||||
return JSON.stringify({
|
||||
ai_request: {
|
||||
birth_date: dateFormatter(aiRequest.birthDate),
|
||||
sign: aiRequest.sign,
|
||||
},
|
||||
});
|
||||
}
|
||||
if (
|
||||
[
|
||||
"horoscope_name",
|
||||
"prediction_moons",
|
||||
"compatibility_thermal",
|
||||
"moonse_phase",
|
||||
"energy_vampirism",
|
||||
].includes(promptKey)
|
||||
) {
|
||||
return JSON.stringify({
|
||||
ai_request: {
|
||||
birth_date: dateFormatter(aiRequest.birthDate),
|
||||
sign: aiRequest.sign,
|
||||
period: (aiRequest as IPredictionMoonsPayload).period,
|
||||
},
|
||||
});
|
||||
}
|
||||
return JSON.stringify({ aiRequest });
|
||||
};
|
||||
|
||||
export const createRequest = ({
|
||||
promptKey,
|
||||
aiRequest,
|
||||
token,
|
||||
}: Payload): Request => {
|
||||
const url = new URL(routes.server.aiRequestsV2(promptKey));
|
||||
const body = JSON.stringify({
|
||||
ai_request: {
|
||||
birth_date: dateFormatter(aiRequest.birthDate),
|
||||
sign: aiRequest.sign,
|
||||
},
|
||||
});
|
||||
const body = getBody(aiRequest, promptKey);
|
||||
return new Request(url, {
|
||||
method: "POST",
|
||||
headers: getAuthHeaders(token),
|
||||
|
||||
@ -53,6 +53,12 @@ import AuthPage from "../AuthPage";
|
||||
import AuthResultPage from "../AuthResultPage";
|
||||
import MagicBallPage from "../pages/MagicBall";
|
||||
import BestiesHoroscopeResult from "../pages/BestiesHoroscopeResult";
|
||||
import PredictionMoonResult from "../pages/PredictionMoonResult";
|
||||
import MyHoroscopeResult from "../pages/MyHoroscopeResult";
|
||||
import ThermalResult from "../pages/ThermalResult";
|
||||
import MoonPhaseTrackerResult from "../pages/MoonPhaseTrackerResult";
|
||||
import EnergyVampirismResult from "../pages/EnergyVampirismResult";
|
||||
import NameHoroscopeResult from "../pages/NameHoroscopeResult";
|
||||
|
||||
function App(): JSX.Element {
|
||||
const [isSpecialOfferOpen, setIsSpecialOfferOpen] = useState<boolean>(false);
|
||||
@ -225,6 +231,30 @@ function App(): JSX.Element {
|
||||
path={routes.client.horoscopeBestiesResult()}
|
||||
element={<BestiesHoroscopeResult />}
|
||||
/>
|
||||
<Route
|
||||
path={routes.client.predictionMoonResult()}
|
||||
element={<PredictionMoonResult />}
|
||||
/>
|
||||
<Route
|
||||
path={routes.client.myHoroscopeResult()}
|
||||
element={<MyHoroscopeResult />}
|
||||
/>
|
||||
<Route
|
||||
path={routes.client.thermalResult()}
|
||||
element={<ThermalResult />}
|
||||
/>
|
||||
<Route
|
||||
path={routes.client.moonPhaseTracker()}
|
||||
element={<MoonPhaseTrackerResult />}
|
||||
/>
|
||||
<Route
|
||||
path={routes.client.energyVampirismResult()}
|
||||
element={<EnergyVampirismResult />}
|
||||
/>
|
||||
<Route
|
||||
path={routes.client.nameHoroscopeResult()}
|
||||
element={<NameHoroscopeResult />}
|
||||
/>
|
||||
</Route>
|
||||
</Route>
|
||||
<Route path="*" element={<NotFoundPage />} />
|
||||
@ -351,7 +381,6 @@ function PrivateOutlet(): JSX.Element {
|
||||
function PrivateSubscriptionOutlet(): JSX.Element {
|
||||
// const isProduction = import.meta.env.MODE === "production";
|
||||
const isProduction = false;
|
||||
console.log(isProduction);
|
||||
const status = useSelector(selectors.selectStatus);
|
||||
return status === "subscribed" || !isProduction ? (
|
||||
<Outlet />
|
||||
|
||||
52
src/components/EnergyVampirism/index.tsx
Normal file
52
src/components/EnergyVampirism/index.tsx
Normal file
@ -0,0 +1,52 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import styles from "./styles.module.css";
|
||||
import { useApi } from "@/api";
|
||||
import { getRandomArbitrary } from "@/services/random-value";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { selectors } from "@/store";
|
||||
|
||||
interface IEnergyVampirismProps {
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
function EnergyVampirism({ onClick }: IEnergyVampirismProps): JSX.Element {
|
||||
const api = useApi();
|
||||
const { t } = useTranslation();
|
||||
const [backgroundUrl, setBackgroundUrl] = useState("");
|
||||
const name = useSelector(selectors.selectUser).username;
|
||||
|
||||
const getImage = async () => {
|
||||
try {
|
||||
const categoryId = "au.energy_vampirism";
|
||||
const assets = (
|
||||
await api.getAssets({ category: String(categoryId || "1") })
|
||||
).assets;
|
||||
const randomAsset = assets[getRandomArbitrary(0, assets.length - 1)];
|
||||
setBackgroundUrl(randomAsset?.url || "");
|
||||
} catch (error) {
|
||||
console.error("Error: ", error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getImage();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.container}
|
||||
style={{ backgroundImage: `url(${backgroundUrl})` }}
|
||||
onClick={onClick}
|
||||
>
|
||||
<p className={styles.period}>Today</p>
|
||||
<p className={styles.text}>
|
||||
{name?.length ? `${name}, ` : ""}
|
||||
Discover the {t("Find out if you're an energy vampire today or not?")}
|
||||
</p>
|
||||
{/* <div className={styles.blur}></div> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default EnergyVampirism;
|
||||
29
src/components/EnergyVampirism/styles.module.css
Normal file
29
src/components/EnergyVampirism/styles.module.css
Normal file
@ -0,0 +1,29 @@
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 410px;
|
||||
border-radius: 17px;
|
||||
background-color: #000;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
padding: 18px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.period {
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
line-height: 20px;
|
||||
color: #b1b0b0;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 23px;
|
||||
font-weight: 500;
|
||||
line-height: 27px;
|
||||
color: #fff;
|
||||
}
|
||||
@ -16,13 +16,22 @@ import {
|
||||
import { actions, selectors } from "@/store";
|
||||
import { getRandomArbitrary } from "@/services/random-value";
|
||||
import Title from "../Title";
|
||||
import { UserDailyForecast } from "@/api/resources/UserDailyForecasts";
|
||||
// import { UserDailyForecast } from "@/api/resources/UserDailyForecasts";
|
||||
import { EPathsFromHome } from "@/store/siteConfig";
|
||||
import { buildFilename, saveFile } from "../WallpaperPage/utils";
|
||||
import Onboarding from "../Onboarding";
|
||||
import TextWithFinger from "../TextWithFinger";
|
||||
import Slider from "../Slider";
|
||||
import BestiesHoroscopeSlider, { Horoscope } from "../BestiesHoroscopeSlider";
|
||||
import PredictionMoonsSlider, {
|
||||
IPredictionMoon,
|
||||
} from "../PredictionMoonsSlider";
|
||||
import { predictionMoonsPeriods } from "@/data";
|
||||
import WallpapersZodiacSign from "../WallpapersZodiacSign";
|
||||
import ThermalSlider from "../ThermalSlider";
|
||||
import MoonPhaseTracker from "../MoonPhaseTracker";
|
||||
import EnergyVampirism from "../EnergyVampirism";
|
||||
import NameHoroscopeSlider from "../NameHoroscopeSlider";
|
||||
|
||||
const buttonTextFormatter = (text: string): JSX.Element => {
|
||||
const sentences = text.split(".");
|
||||
@ -37,16 +46,23 @@ const buttonTextFormatter = (text: string): JSX.Element => {
|
||||
|
||||
function HomePage(): JSX.Element {
|
||||
const token = useSelector(selectors.selectToken);
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
const buttonsRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const { i18n, t } = useTranslation();
|
||||
const locale = i18n.language;
|
||||
const birthdate = useSelector(selectors.selectBirthdate);
|
||||
const zodiacSign = getZodiacSignByDate(birthdate);
|
||||
const [asset, setAsset] = useState<Asset>();
|
||||
const [moonsAssets, setMoonsAssets] = useState<Asset[]>([]);
|
||||
const api = useApi();
|
||||
|
||||
const homeConfig = useSelector(selectors.selectHome);
|
||||
const isShowNavbar = homeConfig.isShowNavbar;
|
||||
const onboardingConfigHome = useSelector(selectors.selectOnboardingHome);
|
||||
|
||||
const bestiesHoroscopes = useSelector(selectors.selectCompatibilities);
|
||||
const compatibilities = useSelector(selectors.selectCompatibilities);
|
||||
|
||||
const [isShowOnboardingHome, setIsShowOnboardingHome] = useState(
|
||||
!onboardingConfigHome?.isShown
|
||||
@ -80,17 +96,14 @@ function HomePage(): JSX.Element {
|
||||
navigate(routes.client.breath());
|
||||
};
|
||||
|
||||
const handleMyHoroscope = () => {
|
||||
navigate(routes.client.myHoroscopeResult());
|
||||
};
|
||||
|
||||
const handleMagicBall = () => {
|
||||
navigate(routes.client.magicBall());
|
||||
};
|
||||
|
||||
const { i18n } = useTranslation();
|
||||
const locale = i18n.language;
|
||||
const birthdate = useSelector(selectors.selectBirthdate);
|
||||
const zodiacSign = getZodiacSignByDate(birthdate);
|
||||
const [asset, setAsset] = useState<Asset>();
|
||||
const api = useApi();
|
||||
|
||||
const assetsData = useCallback(async () => {
|
||||
const { asset_categories } = await api.getAssetCategories({ locale });
|
||||
const categoryId = getCategoryIdByZodiacSign(zodiacSign, asset_categories);
|
||||
@ -121,15 +134,32 @@ function HomePage(): JSX.Element {
|
||||
// isPending
|
||||
} = useApiCall<UserAura>(auraData);
|
||||
|
||||
const dailyForecastData = useCallback(async () => {
|
||||
const { user_daily_forecast } = await api.getDailyForecasts({ token });
|
||||
return user_daily_forecast;
|
||||
}, [api, token]);
|
||||
// const dailyForecastData = useCallback(async () => {
|
||||
// const { user_daily_forecast } = await api.getDailyForecasts({ token });
|
||||
// return user_daily_forecast;
|
||||
// }, [api, token]);
|
||||
|
||||
const {
|
||||
data: dailyForecast,
|
||||
// isPending
|
||||
} = useApiCall<UserDailyForecast>(dailyForecastData);
|
||||
// const {
|
||||
// data: dailyForecast,
|
||||
// // isPending
|
||||
// } = useApiCall<UserDailyForecast>(dailyForecastData);
|
||||
|
||||
useEffect(() => {
|
||||
getMoonsImages();
|
||||
}, []);
|
||||
|
||||
const getMoonsImages = async () => {
|
||||
const assets = (
|
||||
await api.getAssets({ category: String("au.prediction_moons" || "1") })
|
||||
).assets;
|
||||
const randomAssets: Asset[] = [];
|
||||
for (let i = 0; i < predictionMoonsPeriods.length; i++) {
|
||||
const index = getRandomArbitrary(0, assets.length - 1);
|
||||
randomAssets.push(assets[index]);
|
||||
assets.splice(index, 1);
|
||||
}
|
||||
setMoonsAssets(randomAssets);
|
||||
};
|
||||
|
||||
const downloadImg = () => {
|
||||
if (!asset) return;
|
||||
@ -143,6 +173,30 @@ function HomePage(): JSX.Element {
|
||||
);
|
||||
};
|
||||
|
||||
const handleThermal = (item: Horoscope) => {
|
||||
const { name, birthDate } = item;
|
||||
navigate(
|
||||
`${routes.client.thermalResult()}?name=${name}&birthDate=${birthDate}`
|
||||
);
|
||||
};
|
||||
|
||||
const handlePredictionMoon = (item: IPredictionMoon) => {
|
||||
const { period } = item;
|
||||
navigate(`${routes.client.predictionMoonResult()}?period=${period}`);
|
||||
};
|
||||
|
||||
const handleMoonPhaseTracker = () => {
|
||||
navigate(`${routes.client.moonPhaseTracker()}?period=today`);
|
||||
};
|
||||
|
||||
const handleEnergyVampirism = () => {
|
||||
navigate(`${routes.client.energyVampirismResult()}?period=today`);
|
||||
};
|
||||
|
||||
const handleNameHoroscope = (item: IPredictionMoon) => {
|
||||
navigate(`${routes.client.nameHoroscopeResult()}?period=${item.period}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<section
|
||||
className={`${styles.page} page`}
|
||||
@ -182,9 +236,11 @@ function HomePage(): JSX.Element {
|
||||
>
|
||||
<div
|
||||
ref={buttonsRef}
|
||||
className={`${styles["content__buttons"]} ${
|
||||
isShowNavbar ? styles["content__buttons--hidden"] : ""
|
||||
}`}
|
||||
className={`${styles["content__buttons"]}
|
||||
`}
|
||||
// ${
|
||||
// isShowNavbar ? styles["content__buttons--hidden"] : ""
|
||||
// }
|
||||
>
|
||||
<Onboarding
|
||||
targetRef={buttonsRef.current as HTMLDivElement}
|
||||
@ -209,6 +265,15 @@ function HomePage(): JSX.Element {
|
||||
>
|
||||
{buttonTextFormatter(t("aura-10_breath-button"))}
|
||||
</BlurringSubstrate>
|
||||
<BlurringSubstrate
|
||||
style={{ color: "#FD433F" }}
|
||||
className={styles["content__buttons-item"]}
|
||||
clickHandler={handleMyHoroscope}
|
||||
>
|
||||
{buttonTextFormatter(
|
||||
t("Receive an In-Depth Analysis and Today’s Horoscope")
|
||||
)}
|
||||
</BlurringSubstrate>
|
||||
</div>
|
||||
<div className={`${styles["content__buttons"]}`}>
|
||||
<div
|
||||
@ -221,12 +286,12 @@ function HomePage(): JSX.Element {
|
||||
|
||||
{/* SLIDERS */}
|
||||
<div className={styles.sliders}>
|
||||
<div>
|
||||
<div className={styles["slider"]}>
|
||||
<Title variant="h2" className={styles["sliders__title"]}>
|
||||
{"Your Besties' Horoscope"}
|
||||
</Title>
|
||||
<Slider>
|
||||
{bestiesHoroscopes.map((item, index) => (
|
||||
{compatibilities.map((item, index) => (
|
||||
<BestiesHoroscopeSlider
|
||||
data={item}
|
||||
key={index}
|
||||
@ -237,10 +302,81 @@ function HomePage(): JSX.Element {
|
||||
))}
|
||||
</Slider>
|
||||
</div>
|
||||
<div className={styles["slider"]}>
|
||||
<Title variant="h2" className={styles["sliders__title"]}>
|
||||
{"Prediction Based on Your Moons"}
|
||||
</Title>
|
||||
<Slider>
|
||||
{predictionMoonsPeriods.map((item, index) => (
|
||||
<PredictionMoonsSlider
|
||||
image={moonsAssets[index]?.url}
|
||||
data={item}
|
||||
key={index}
|
||||
onClick={() => {
|
||||
handlePredictionMoon(item);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Slider>
|
||||
</div>
|
||||
</div>
|
||||
{/* END SLIDERS */}
|
||||
|
||||
<div className={styles["content__daily-forecast"]}>
|
||||
<Title variant="h2" className={styles["sliders__title"]}>
|
||||
{"Energy Vampirism"}
|
||||
</Title>
|
||||
<EnergyVampirism onClick={handleEnergyVampirism} />
|
||||
|
||||
{/* SLIDERS */}
|
||||
<div className={styles.sliders}>
|
||||
<div className={styles["slider"]}>
|
||||
<Title variant="h2" className={styles["sliders__title"]}>
|
||||
{t("Your Name's Horoscope")}
|
||||
</Title>
|
||||
<Slider>
|
||||
{predictionMoonsPeriods.map((item, index) => (
|
||||
<NameHoroscopeSlider
|
||||
data={{ ...item, name: "Victor Ershov" }}
|
||||
key={index}
|
||||
onClick={() => {
|
||||
handleNameHoroscope(item);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Slider>
|
||||
</div>
|
||||
</div>
|
||||
{/* END SLIDERS */}
|
||||
|
||||
<Title variant="h2" className={styles["sliders__title"]}>
|
||||
{"AI-based unique Walpapers"}
|
||||
</Title>
|
||||
<WallpapersZodiacSign />
|
||||
|
||||
{/* SLIDERS */}
|
||||
<div className={styles.sliders}>
|
||||
<div className={styles["slider"]}>
|
||||
<Title variant="h2" className={styles["sliders__title"]}>
|
||||
{t("au.thermal_compatibility.result_title")}
|
||||
</Title>
|
||||
<Slider>
|
||||
{compatibilities.map((item, index) => (
|
||||
<ThermalSlider
|
||||
data={item}
|
||||
key={index}
|
||||
onClick={() => {
|
||||
handleThermal(item);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Slider>
|
||||
</div>
|
||||
</div>
|
||||
{/* END SLIDERS */}
|
||||
|
||||
<MoonPhaseTracker onClick={handleMoonPhaseTracker} />
|
||||
|
||||
{/* <div className={styles["content__daily-forecast"]}>
|
||||
{dailyForecast &&
|
||||
dailyForecast.forecasts.map((forecast, index) => (
|
||||
<div
|
||||
@ -251,7 +387,6 @@ function HomePage(): JSX.Element {
|
||||
variant="h3"
|
||||
className={styles["content__daily-forecast-title"]}
|
||||
>
|
||||
{/* {forecast.category} */}
|
||||
{t("aura.personal_aura.button")}
|
||||
</Title>
|
||||
<p className={styles["content__daily-forecast-body"]}>
|
||||
@ -259,7 +394,7 @@ function HomePage(): JSX.Element {
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
{/* </div> */}
|
||||
</section>
|
||||
|
||||
@ -187,6 +187,7 @@
|
||||
text-align: left;
|
||||
padding: 0 12px;
|
||||
margin-bottom: 12px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
|
||||
53
src/components/MoonPhaseTracker/index.tsx
Normal file
53
src/components/MoonPhaseTracker/index.tsx
Normal file
@ -0,0 +1,53 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import styles from "./styles.module.css";
|
||||
import { useApi } from "@/api";
|
||||
import { getRandomArbitrary } from "@/services/random-value";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
interface IMoonPhaseTracker {
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
function MoonPhaseTracker({ onClick }: IMoonPhaseTracker): JSX.Element {
|
||||
const api = useApi();
|
||||
const { t } = useTranslation();
|
||||
const [backgroundUrl, setBackgroundUrl] = useState("");
|
||||
|
||||
const getImage = async () => {
|
||||
try {
|
||||
const categoryId = "au.moonse_phase";
|
||||
const assets = (
|
||||
await api.getAssets({ category: String(categoryId || "1") })
|
||||
).assets;
|
||||
const randomAsset = assets[getRandomArbitrary(0, assets.length - 1)];
|
||||
setBackgroundUrl(randomAsset.url);
|
||||
} catch (error) {
|
||||
console.error("Error: ", error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getImage();
|
||||
}, []);
|
||||
|
||||
const removeLastWord = (sentence: string): string => {
|
||||
const lastIndex = sentence.lastIndexOf(" ");
|
||||
return sentence.substring(0, lastIndex);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.container}
|
||||
style={{ backgroundImage: `url(${backgroundUrl})` }}
|
||||
onClick={onClick}
|
||||
>
|
||||
<p className={styles.text}>Today</p>
|
||||
<p className={styles.text}>
|
||||
Discover the {removeLastWord(t("au.moonse_phase.result_title"))}
|
||||
</p>
|
||||
{/* <div className={styles.blur}></div> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default MoonPhaseTracker;
|
||||
38
src/components/MoonPhaseTracker/styles.module.css
Normal file
38
src/components/MoonPhaseTracker/styles.module.css
Normal file
@ -0,0 +1,38 @@
|
||||
.container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
align-items: flex-start;
|
||||
gap: 16px;
|
||||
background-color: #000;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
border-radius: 17px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.text {
|
||||
position: relative;
|
||||
color: #fff;
|
||||
font-size: 17px;
|
||||
line-height: 20px;
|
||||
font-weight: 500;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.blur {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
height: 35%;
|
||||
width: 100%;
|
||||
filter: blur(10px);
|
||||
z-index: 1;
|
||||
-webkit-backdrop-filter: blur(50px);
|
||||
backdrop-filter: blur(50px);
|
||||
}
|
||||
67
src/components/NameHoroscopeSlider/index.tsx
Normal file
67
src/components/NameHoroscopeSlider/index.tsx
Normal file
@ -0,0 +1,67 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import styles from "./styles.module.css";
|
||||
import {
|
||||
getCategoryIdByZodiacSign,
|
||||
getZodiacSignByDate,
|
||||
} from "@/services/zodiac-sign";
|
||||
import { useSelector } from "react-redux";
|
||||
import { selectors } from "@/store";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useApi } from "@/api";
|
||||
import { getRandomArbitrary } from "@/services/random-value";
|
||||
|
||||
interface INameHoroscopeSliderProps {
|
||||
data: INameHoroscope;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
export interface INameHoroscope {
|
||||
period: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
function NameHoroscopeSlider({
|
||||
data,
|
||||
onClick,
|
||||
}: INameHoroscopeSliderProps): JSX.Element {
|
||||
const api = useApi();
|
||||
const { i18n } = useTranslation();
|
||||
const locale = i18n.language;
|
||||
const birthDate = useSelector(selectors.selectBirthdate);
|
||||
const zodiacSign = getZodiacSignByDate(birthDate);
|
||||
const [backgroundUrl, setBackgroundUrl] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
const { asset_categories } = await api.getAssetCategories({ locale });
|
||||
const categoryId = getCategoryIdByZodiacSign(
|
||||
zodiacSign,
|
||||
asset_categories
|
||||
);
|
||||
const assets = (
|
||||
await api.getAssets({ category: String(categoryId || "1") })
|
||||
).assets;
|
||||
const randomAsset = assets[getRandomArbitrary(0, assets.length - 1)];
|
||||
setBackgroundUrl(randomAsset.url);
|
||||
} catch (error) {
|
||||
console.error("Error: ", error);
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{ backgroundImage: `url(${backgroundUrl})` }}
|
||||
className={styles.container}
|
||||
onClick={onClick}
|
||||
>
|
||||
<p className={styles.period}>{data.period}</p>
|
||||
<p className={styles.name}>
|
||||
<b>{data.name}</b>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default NameHoroscopeSlider;
|
||||
35
src/components/NameHoroscopeSlider/styles.module.css
Normal file
35
src/components/NameHoroscopeSlider/styles.module.css
Normal file
@ -0,0 +1,35 @@
|
||||
.container {
|
||||
width: 280px;
|
||||
height: 200px;
|
||||
border-radius: 100px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding: 24px 12px;
|
||||
background-repeat: no-repeat !important;
|
||||
background-size: cover !important;
|
||||
background-position: center !important;
|
||||
background-color: #000 !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.period {
|
||||
color: #b1b0b0;
|
||||
font-weight: 500;
|
||||
font-size: 17px;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.period::first-letter {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.name {
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
font-size: 23px;
|
||||
line-height: 27px;
|
||||
text-align: center;
|
||||
}
|
||||
31
src/components/PredictionMoonsSlider/index.tsx
Normal file
31
src/components/PredictionMoonsSlider/index.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
import styles from "./styles.module.css";
|
||||
|
||||
interface IPredictionMoonsSliderProps {
|
||||
image: string;
|
||||
data: IPredictionMoon;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
export interface IPredictionMoon {
|
||||
period: string;
|
||||
}
|
||||
|
||||
function PredictionMoonsSlider({
|
||||
image,
|
||||
data,
|
||||
onClick,
|
||||
}: IPredictionMoonsSliderProps): JSX.Element {
|
||||
return (
|
||||
<div
|
||||
className={styles.container}
|
||||
style={{ backgroundImage: `url(${image})` }}
|
||||
onClick={onClick}
|
||||
>
|
||||
<p className={styles.text}>
|
||||
<b>{data.period}</b>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default PredictionMoonsSlider;
|
||||
32
src/components/PredictionMoonsSlider/styles.module.css
Normal file
32
src/components/PredictionMoonsSlider/styles.module.css
Normal file
@ -0,0 +1,32 @@
|
||||
.container {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 17px;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: start;
|
||||
padding: 8px 12px;
|
||||
background-repeat: no-repeat !important;
|
||||
background-size: cover !important;
|
||||
background-position: center !important;
|
||||
background-color: #000 !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.text {
|
||||
color: #fff;
|
||||
font-weight: 400;
|
||||
font-size: 17px;
|
||||
line-height: 20px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.text::first-letter {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.text > b {
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
font-size: 18px;
|
||||
}
|
||||
61
src/components/ThermalSlider/index.tsx
Normal file
61
src/components/ThermalSlider/index.tsx
Normal file
@ -0,0 +1,61 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import styles from "./styles.module.css";
|
||||
import {
|
||||
getCategoryIdByZodiacSign,
|
||||
getZodiacSignByDate,
|
||||
} from "@/services/zodiac-sign";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useApi } from "@/api";
|
||||
import { getRandomArbitrary } from "@/services/random-value";
|
||||
|
||||
interface ThermalProps {
|
||||
data: Thermal;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
export interface Thermal {
|
||||
name: string;
|
||||
birthDate: string;
|
||||
}
|
||||
|
||||
function ThermalSlider({ data, onClick }: ThermalProps): JSX.Element {
|
||||
const api = useApi();
|
||||
const { i18n } = useTranslation();
|
||||
const locale = i18n.language;
|
||||
const zodiacSign = getZodiacSignByDate(data.birthDate);
|
||||
const [backgroundUrl, setBackgroundUrl] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
const { asset_categories } = await api.getAssetCategories({ locale });
|
||||
const categoryId = getCategoryIdByZodiacSign(
|
||||
zodiacSign,
|
||||
asset_categories
|
||||
);
|
||||
const assets = (
|
||||
await api.getAssets({ category: String(categoryId || "1") })
|
||||
).assets;
|
||||
const randomAsset = assets[getRandomArbitrary(0, assets.length - 1)];
|
||||
setBackgroundUrl(randomAsset.url);
|
||||
} catch (error) {
|
||||
console.error("Error: ", error);
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.container}
|
||||
onClick={onClick}
|
||||
>
|
||||
<img className={styles.background} src={backgroundUrl} alt="background image" />
|
||||
<div className={styles["name-container"]}>
|
||||
<p>with {data.name}</p>
|
||||
</div>
|
||||
<span className={styles.period}>Today</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ThermalSlider;
|
||||
58
src/components/ThermalSlider/styles.module.css
Normal file
58
src/components/ThermalSlider/styles.module.css
Normal file
@ -0,0 +1,58 @@
|
||||
.container {
|
||||
position: relative;
|
||||
padding: 4px;
|
||||
margin: 26px 0;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
background-repeat: no-repeat !important;
|
||||
background-size: cover !important;
|
||||
background-position: center !important;
|
||||
background-color: #000 !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.background {
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
left: -15px;
|
||||
width: calc(100% + 30px);
|
||||
height: calc(100% + 30px);
|
||||
object-fit: cover;
|
||||
border-radius: 100%;
|
||||
filter: blur(9px);
|
||||
}
|
||||
|
||||
.name-container {
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
margin-top: 28px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 64px;
|
||||
text-align: center;
|
||||
color: #000;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
font-weight: 600;
|
||||
font-size: 21px;
|
||||
line-height: 25px;
|
||||
background-color: #d9d9d985;
|
||||
border-radius: 100px;
|
||||
}
|
||||
|
||||
.period {
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
color: #fff;
|
||||
font-size: 17px;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
64
src/components/WallpapersZodiacSign/index.tsx
Normal file
64
src/components/WallpapersZodiacSign/index.tsx
Normal file
@ -0,0 +1,64 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useAuth } from "@/auth";
|
||||
import { useApi, Assets } from "@/api";
|
||||
import { saveFile, buildFilename } from "../WallpaperPage/utils";
|
||||
import styles from "./styles.module.css";
|
||||
import { useSelector } from "react-redux";
|
||||
import { selectors } from "@/store";
|
||||
import {
|
||||
getCategoryIdByZodiacSign,
|
||||
getZodiacSignByDate,
|
||||
} from "@/services/zodiac-sign";
|
||||
import { getRandomArbitrary } from "@/services/random-value";
|
||||
|
||||
function WallpapersZodiacSign(): JSX.Element {
|
||||
const api = useApi();
|
||||
const { i18n } = useTranslation();
|
||||
const locale = i18n.language;
|
||||
const [asset, setAsset] = useState<Assets.Asset>();
|
||||
|
||||
const {
|
||||
user,
|
||||
// token
|
||||
} = useAuth();
|
||||
const birthdate = useSelector(selectors.selectBirthdate);
|
||||
const zodiacSign = getZodiacSignByDate(birthdate);
|
||||
const category = user?.profile.sign?.sign || "";
|
||||
|
||||
const getZodiacWallpaper = async () => {
|
||||
const { asset_categories } = await api.getAssetCategories({ locale });
|
||||
const categoryId = getCategoryIdByZodiacSign(zodiacSign, asset_categories);
|
||||
const { assets } = await api.getAssets({
|
||||
category: String(categoryId || "1"),
|
||||
});
|
||||
const asset = assets[getRandomArbitrary(0, assets.length - 1)];
|
||||
setAsset(asset);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getZodiacWallpaper();
|
||||
}, []);
|
||||
|
||||
const saveImage = () =>
|
||||
asset &&
|
||||
saveFile(asset.url.replace("http://", "https://"), buildFilename(category));
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles["wallpaper"]}
|
||||
style={{ backgroundImage: `url(${asset?.url})` }}
|
||||
>
|
||||
<div className={styles["buttons-container"]}>
|
||||
<img src="/ButtonSave.svg" alt="Save image" onClick={saveImage} />
|
||||
<img
|
||||
src="/ButtonReload.svg"
|
||||
alt="Get new image"
|
||||
onClick={getZodiacWallpaper}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default WallpapersZodiacSign;
|
||||
22
src/components/WallpapersZodiacSign/styles.module.css
Normal file
22
src/components/WallpapersZodiacSign/styles.module.css
Normal file
@ -0,0 +1,22 @@
|
||||
.wallpaper {
|
||||
width: 100%;
|
||||
height: 520px;
|
||||
border-radius: 17px;
|
||||
background-color: #000;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
padding: 26px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.buttons-container {
|
||||
width: fit-content;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 18px;
|
||||
}
|
||||
@ -50,7 +50,7 @@
|
||||
.cross {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: solid 2px #bdbdbd;
|
||||
/* border: solid 2px #bdbdbd; */
|
||||
border-radius: 100%;
|
||||
rotate: 45deg;
|
||||
cursor: pointer;
|
||||
@ -62,7 +62,7 @@
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 10px;
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
background-color: #bdbdbd;
|
||||
}
|
||||
@ -74,6 +74,6 @@
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 2px;
|
||||
height: 10px;
|
||||
height: 20px;
|
||||
background-color: #bdbdbd;
|
||||
}
|
||||
|
||||
165
src/components/pages/EnergyVampirismResult/index.tsx
Normal file
165
src/components/pages/EnergyVampirismResult/index.tsx
Normal file
@ -0,0 +1,165 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Title from "@/components/Title";
|
||||
import styles from "./styles.module.css";
|
||||
import { useSelector } from "react-redux";
|
||||
import { selectors } from "@/store";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { AIRequestsV2, useApi, useApiCall } from "@/api";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import routes from "@/routes";
|
||||
import FullScreenModal from "@/components/FullScreenModal";
|
||||
import ProgressBarsModal, { ProgressBar } from "@/components/ProgressBarsModal";
|
||||
import {
|
||||
getCategoryIdByZodiacSign,
|
||||
getZodiacSignByDate,
|
||||
} from "@/services/zodiac-sign";
|
||||
import { getRandomArbitrary } from "@/services/random-value";
|
||||
|
||||
function EnergyVampirismResult(): JSX.Element {
|
||||
const token = useSelector(selectors.selectToken);
|
||||
const { i18n, t } = useTranslation();
|
||||
const locale = i18n.language;
|
||||
const navigate = useNavigate();
|
||||
const api = useApi();
|
||||
const homeConfig = useSelector(selectors.selectHome);
|
||||
const showNavbarFooter = homeConfig.isShowNavbar;
|
||||
const [text, setText] = useState("Loading...");
|
||||
const [isOpenModal, setIsOpenModal] = useState(true);
|
||||
const [isVisualLoading, setIsVisualLoading] = useState(true);
|
||||
const [isDataLoading, setIsDataLoading] = useState(true);
|
||||
const name = useSelector(selectors.selectUser).username;
|
||||
const birthDate = useSelector(selectors.selectBirthdate);
|
||||
const zodiacSign = getZodiacSignByDate(birthDate);
|
||||
const [backgroundUrl, setBackgroundUrl] = useState("");
|
||||
const timeoutRef = useRef<NodeJS.Timeout>();
|
||||
|
||||
const progressBars: ProgressBar[] = [
|
||||
{
|
||||
label: t("au.energy_vampirism.loading1"),
|
||||
},
|
||||
{
|
||||
label: t("au.energy_vampirism.loading2"),
|
||||
},
|
||||
{
|
||||
label: t("au.energy_vampirism.loading3"),
|
||||
},
|
||||
{
|
||||
label: t("au.energy_vampirism.loading4"),
|
||||
},
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
clearTimeout(timeoutRef.current);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleNext = () => {
|
||||
return navigate(routes.client.home());
|
||||
};
|
||||
|
||||
const loadData = useCallback(async () => {
|
||||
const payload: AIRequestsV2.Payload = {
|
||||
aiRequest: {
|
||||
birthDate,
|
||||
sign: getZodiacSignByDate(birthDate).toLowerCase(),
|
||||
},
|
||||
promptKey: "energy_vampirism",
|
||||
token,
|
||||
};
|
||||
const aIRequest = await api.AIRequestsV2(payload);
|
||||
if (aIRequest.ai_request.state !== "ready") {
|
||||
const getAIRequest = async () => {
|
||||
const aIRequestById = await api.getAIRequestsV2({
|
||||
id: aIRequest.ai_request.id,
|
||||
token,
|
||||
});
|
||||
if (aIRequestById.ai_request.state !== "ready") {
|
||||
timeoutRef.current = setTimeout(getAIRequest, 3000);
|
||||
}
|
||||
setText(aIRequestById?.ai_request?.response?.body || "Loading...");
|
||||
setIsDataLoading(false);
|
||||
checkLoading();
|
||||
return aIRequestById.ai_request;
|
||||
};
|
||||
return await getAIRequest();
|
||||
}
|
||||
setIsDataLoading(false);
|
||||
checkLoading();
|
||||
setText(aIRequest?.ai_request?.response?.response?.body || "Loading...");
|
||||
|
||||
return aIRequest?.ai_request?.response;
|
||||
}, [api, token, birthDate]);
|
||||
|
||||
useApiCall<AIRequestsV2.IAIRequest>(loadData);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
const { asset_categories } = await api.getAssetCategories({ locale });
|
||||
const categoryId = getCategoryIdByZodiacSign(
|
||||
zodiacSign,
|
||||
asset_categories
|
||||
);
|
||||
const assets = (
|
||||
await api.getAssets({ category: String(categoryId || "1") })
|
||||
).assets;
|
||||
const randomAsset = assets[getRandomArbitrary(0, assets.length - 1)];
|
||||
setBackgroundUrl(randomAsset.url);
|
||||
} catch (error) {
|
||||
console.error("Error: ", error);
|
||||
}
|
||||
})();
|
||||
}, [api, locale, zodiacSign]);
|
||||
|
||||
const getPaddingBottomPage = () => {
|
||||
if (showNavbarFooter) return "164px";
|
||||
return "108px";
|
||||
};
|
||||
|
||||
function checkLoading() {
|
||||
if (isVisualLoading || isDataLoading) {
|
||||
setIsOpenModal(true);
|
||||
} else {
|
||||
setIsOpenModal(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section
|
||||
className={`${styles.page} page`}
|
||||
style={{ paddingBottom: getPaddingBottomPage() }}
|
||||
>
|
||||
<FullScreenModal isOpen={isOpenModal}>
|
||||
<ProgressBarsModal
|
||||
progressBars={progressBars}
|
||||
onEndLoading={() => {
|
||||
setIsVisualLoading(false);
|
||||
checkLoading();
|
||||
}}
|
||||
>
|
||||
<Title variant="h2">
|
||||
{t("au.energy_vampirism.loading_title")}{" "}
|
||||
<span className={styles["loading-name"]}>{name}</span>
|
||||
</Title>
|
||||
<></>
|
||||
</ProgressBarsModal>
|
||||
</FullScreenModal>
|
||||
<div className={styles["cross-container"]}>
|
||||
<div className={styles.cross} onClick={handleNext}></div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["sign-image"]}
|
||||
style={{ backgroundImage: `url(${backgroundUrl})` }}
|
||||
>
|
||||
<Title variant="h2">
|
||||
<span className={styles["loading-name"]}>{name}</span>{" "}
|
||||
{t("au.energy_vampirism.result_title")}
|
||||
</Title>
|
||||
</div>
|
||||
<p className={styles.text}>{text}</p>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default EnergyVampirismResult;
|
||||
79
src/components/pages/EnergyVampirismResult/styles.module.css
Normal file
79
src/components/pages/EnergyVampirismResult/styles.module.css
Normal file
@ -0,0 +1,79 @@
|
||||
.page {
|
||||
position: relative;
|
||||
height: fit-content;
|
||||
min-height: 100vh;
|
||||
flex: auto;
|
||||
/* max-height: -webkit-fill-available; */
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
overflow-y: scroll;
|
||||
padding-bottom: 180px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.loading-name {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.sign-image {
|
||||
width: 100%;
|
||||
height: 446px;
|
||||
color: #fd433f;
|
||||
border-radius: 17px;
|
||||
background-color: #000;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 18px;
|
||||
line-height: 22px;
|
||||
font-weight: 400;
|
||||
padding: 0 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.cross-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.cross {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
/* border: solid 2px #bdbdbd; */
|
||||
border-radius: 100%;
|
||||
rotate: 45deg;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cross::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
background-color: #bdbdbd;
|
||||
}
|
||||
|
||||
.cross::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 2px;
|
||||
height: 20px;
|
||||
background-color: #bdbdbd;
|
||||
}
|
||||
157
src/components/pages/MoonPhaseTrackerResult/index.tsx
Normal file
157
src/components/pages/MoonPhaseTrackerResult/index.tsx
Normal file
@ -0,0 +1,157 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Title from "@/components/Title";
|
||||
import styles from "./styles.module.css";
|
||||
import { useSelector } from "react-redux";
|
||||
import { selectors } from "@/store";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { AIRequestsV2, useApi, useApiCall } from "@/api";
|
||||
import { useNavigate, useSearchParams } from "react-router-dom";
|
||||
import routes from "@/routes";
|
||||
import FullScreenModal from "@/components/FullScreenModal";
|
||||
import ProgressBarsModal, { ProgressBar } from "@/components/ProgressBarsModal";
|
||||
import { getZodiacSignByDate } from "@/services/zodiac-sign";
|
||||
import { getRandomArbitrary } from "@/services/random-value";
|
||||
|
||||
function MoonPhaseTrackerResult(): JSX.Element {
|
||||
const token = useSelector(selectors.selectToken);
|
||||
const { i18n, t } = useTranslation();
|
||||
const locale = i18n.language;
|
||||
const navigate = useNavigate();
|
||||
const api = useApi();
|
||||
const homeConfig = useSelector(selectors.selectHome);
|
||||
const showNavbarFooter = homeConfig.isShowNavbar;
|
||||
const [text, setText] = useState("Loading...");
|
||||
const [isOpenModal, setIsOpenModal] = useState(true);
|
||||
const [isVisualLoading, setIsVisualLoading] = useState(true);
|
||||
const [isDataLoading, setIsDataLoading] = useState(true);
|
||||
const [searchParams] = useSearchParams();
|
||||
const period = searchParams.get("period");
|
||||
const birthDate = useSelector(selectors.selectBirthdate);
|
||||
const zodiacSign = getZodiacSignByDate(birthDate);
|
||||
const [backgroundUrl, setBackgroundUrl] = useState("");
|
||||
const timeoutRef = useRef<NodeJS.Timeout>();
|
||||
|
||||
const progressBars: ProgressBar[] = [
|
||||
{
|
||||
label: t("au.moonse_phase.loading1"),
|
||||
},
|
||||
{
|
||||
label: t("au.moonse_phase.loading2"),
|
||||
},
|
||||
{
|
||||
label: t("au.moonse_phase.loading3"),
|
||||
},
|
||||
{
|
||||
label: t("au.moonse_phase.loading4"),
|
||||
},
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
clearTimeout(timeoutRef.current);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleNext = () => {
|
||||
return navigate(routes.client.home());
|
||||
};
|
||||
|
||||
const loadData = useCallback(async () => {
|
||||
const payload: AIRequestsV2.Payload = {
|
||||
aiRequest: {
|
||||
birthDate,
|
||||
sign: getZodiacSignByDate(birthDate).toLowerCase(),
|
||||
period: period?.toLowerCase() || "today",
|
||||
},
|
||||
promptKey: "moonse_phase",
|
||||
token,
|
||||
};
|
||||
const aIRequest = await api.AIRequestsV2(payload);
|
||||
if (aIRequest.ai_request.state !== "ready") {
|
||||
const getAIRequest = async () => {
|
||||
const aIRequestById = await api.getAIRequestsV2({
|
||||
id: aIRequest.ai_request.id,
|
||||
token,
|
||||
});
|
||||
|
||||
if (aIRequestById.ai_request.state !== "ready") {
|
||||
timeoutRef.current = setTimeout(getAIRequest, 3000);
|
||||
}
|
||||
setText(aIRequestById?.ai_request?.response?.body || "Loading...");
|
||||
setIsDataLoading(false);
|
||||
checkLoading();
|
||||
return aIRequestById.ai_request;
|
||||
};
|
||||
return await getAIRequest();
|
||||
}
|
||||
setIsDataLoading(false);
|
||||
checkLoading();
|
||||
setText(aIRequest?.ai_request?.response?.response?.body || "Loading...");
|
||||
|
||||
return aIRequest?.ai_request?.response;
|
||||
}, [api, token, birthDate, period]);
|
||||
|
||||
useApiCall<AIRequestsV2.IAIRequest>(loadData);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
const categoryId = "au.moonse_phase";
|
||||
const assets = (
|
||||
await api.getAssets({ category: String(categoryId || "1") })
|
||||
).assets;
|
||||
const randomAsset = assets[getRandomArbitrary(0, assets.length - 1)];
|
||||
setBackgroundUrl(randomAsset.url);
|
||||
} catch (error) {
|
||||
console.error("Error: ", error);
|
||||
}
|
||||
})();
|
||||
}, [api, locale, zodiacSign]);
|
||||
|
||||
const getPaddingBottomPage = () => {
|
||||
if (showNavbarFooter) return "164px";
|
||||
return "108px";
|
||||
};
|
||||
|
||||
function checkLoading() {
|
||||
if (isVisualLoading || isDataLoading) {
|
||||
setIsOpenModal(true);
|
||||
} else {
|
||||
setIsOpenModal(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section
|
||||
className={`${styles.page} page`}
|
||||
style={{ paddingBottom: getPaddingBottomPage() }}
|
||||
>
|
||||
<FullScreenModal isOpen={isOpenModal}>
|
||||
<ProgressBarsModal
|
||||
progressBars={progressBars}
|
||||
onEndLoading={() => {
|
||||
setIsVisualLoading(false);
|
||||
checkLoading();
|
||||
}}
|
||||
>
|
||||
<Title variant="h2">{t("au.moonse_phase.loading_title")}</Title>
|
||||
<></>
|
||||
</ProgressBarsModal>
|
||||
</FullScreenModal>
|
||||
<div className={styles["cross-container"]}>
|
||||
<div className={styles.cross} onClick={handleNext}></div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["sign-image"]}
|
||||
style={{ backgroundImage: `url(${backgroundUrl})` }}
|
||||
>
|
||||
<Title variant="h2">
|
||||
{t("au.moonse_phase.loading_title")} {period}
|
||||
</Title>
|
||||
</div>
|
||||
<p className={styles.text}>{text}</p>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default MoonPhaseTrackerResult;
|
||||
@ -0,0 +1,79 @@
|
||||
.page {
|
||||
position: relative;
|
||||
height: fit-content;
|
||||
min-height: 100vh;
|
||||
flex: auto;
|
||||
/* max-height: -webkit-fill-available; */
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
overflow-y: scroll;
|
||||
padding-bottom: 180px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.loading-name {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.sign-image {
|
||||
width: 100%;
|
||||
height: 446px;
|
||||
color: #fd433f;
|
||||
border-radius: 17px;
|
||||
background-color: #000;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 18px;
|
||||
line-height: 22px;
|
||||
font-weight: 400;
|
||||
padding: 0 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.cross-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.cross {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
/* border: solid 2px #bdbdbd; */
|
||||
border-radius: 100%;
|
||||
rotate: 45deg;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cross::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
background-color: #bdbdbd;
|
||||
}
|
||||
|
||||
.cross::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 2px;
|
||||
height: 20px;
|
||||
background-color: #bdbdbd;
|
||||
}
|
||||
161
src/components/pages/MyHoroscopeResult/index.tsx
Normal file
161
src/components/pages/MyHoroscopeResult/index.tsx
Normal file
@ -0,0 +1,161 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Title from "@/components/Title";
|
||||
import styles from "./styles.module.css";
|
||||
import { useSelector } from "react-redux";
|
||||
import { selectors } from "@/store";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { AIRequestsV2, useApi, useApiCall } from "@/api";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import routes from "@/routes";
|
||||
import FullScreenModal from "@/components/FullScreenModal";
|
||||
import ProgressBarsModal, { ProgressBar } from "@/components/ProgressBarsModal";
|
||||
import {
|
||||
getCategoryIdByZodiacSign,
|
||||
getZodiacSignByDate,
|
||||
} from "@/services/zodiac-sign";
|
||||
import { getRandomArbitrary } from "@/services/random-value";
|
||||
|
||||
function MyHoroscopeResult(): JSX.Element {
|
||||
const token = useSelector(selectors.selectToken);
|
||||
const { i18n, t } = useTranslation();
|
||||
const locale = i18n.language;
|
||||
const navigate = useNavigate();
|
||||
const api = useApi();
|
||||
const homeConfig = useSelector(selectors.selectHome);
|
||||
const showNavbarFooter = homeConfig.isShowNavbar;
|
||||
const [text, setText] = useState("Loading...");
|
||||
const [isOpenModal, setIsOpenModal] = useState(true);
|
||||
const [isVisualLoading, setIsVisualLoading] = useState(true);
|
||||
const [isDataLoading, setIsDataLoading] = useState(true);
|
||||
const birthDate = useSelector(selectors.selectBirthdate);
|
||||
const zodiacSign = getZodiacSignByDate(birthDate);
|
||||
const [backgroundUrl, setBackgroundUrl] = useState("");
|
||||
const timeoutRef = useRef<NodeJS.Timeout>();
|
||||
|
||||
const progressBars: ProgressBar[] = [
|
||||
{
|
||||
label: t("au.my_horoscope.loading1"),
|
||||
},
|
||||
{
|
||||
label: t("au.my_horoscope.loading2"),
|
||||
},
|
||||
{
|
||||
label: t("au.my_horoscope.loading3"),
|
||||
},
|
||||
{
|
||||
label: t("au.my_horoscope.loading4"),
|
||||
},
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
clearTimeout(timeoutRef.current);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleNext = () => {
|
||||
return navigate(routes.client.home());
|
||||
};
|
||||
|
||||
const loadData = useCallback(async () => {
|
||||
const payload: AIRequestsV2.Payload = {
|
||||
aiRequest: {
|
||||
birthDate,
|
||||
sign: getZodiacSignByDate(birthDate).toLowerCase(),
|
||||
period: "today",
|
||||
},
|
||||
promptKey: "horoscope_name",
|
||||
token,
|
||||
};
|
||||
const aIRequest = await api.AIRequestsV2(payload);
|
||||
if (aIRequest.ai_request.state !== "ready") {
|
||||
const getAIRequest = async () => {
|
||||
const aIRequestById = await api.getAIRequestsV2({
|
||||
id: aIRequest.ai_request.id,
|
||||
token,
|
||||
});
|
||||
if (aIRequestById.ai_request.state !== "ready") {
|
||||
timeoutRef.current = setTimeout(getAIRequest, 3000);
|
||||
}
|
||||
setText(aIRequestById?.ai_request?.response?.body || "Loading...");
|
||||
setIsDataLoading(false);
|
||||
checkLoading();
|
||||
return aIRequestById.ai_request;
|
||||
};
|
||||
return await getAIRequest();
|
||||
}
|
||||
setIsDataLoading(false);
|
||||
checkLoading();
|
||||
setText(aIRequest?.ai_request?.response?.response?.body || "Loading...");
|
||||
|
||||
return aIRequest?.ai_request?.response;
|
||||
}, [api, token, birthDate]);
|
||||
|
||||
useApiCall<AIRequestsV2.IAIRequest>(loadData);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
const { asset_categories } = await api.getAssetCategories({ locale });
|
||||
const categoryId = getCategoryIdByZodiacSign(
|
||||
zodiacSign,
|
||||
asset_categories
|
||||
);
|
||||
const assets = (
|
||||
await api.getAssets({ category: String(categoryId || "1") })
|
||||
).assets;
|
||||
const randomAsset = assets[getRandomArbitrary(0, assets.length - 1)];
|
||||
setBackgroundUrl(randomAsset.url);
|
||||
} catch (error) {
|
||||
console.error("Error: ", error);
|
||||
}
|
||||
})();
|
||||
}, [api, locale, zodiacSign]);
|
||||
|
||||
const getPaddingBottomPage = () => {
|
||||
if (showNavbarFooter) return "164px";
|
||||
return "108px";
|
||||
};
|
||||
|
||||
function checkLoading() {
|
||||
if (isVisualLoading || isDataLoading) {
|
||||
setIsOpenModal(true);
|
||||
} else {
|
||||
setIsOpenModal(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section
|
||||
className={`${styles.page} page`}
|
||||
style={{ paddingBottom: getPaddingBottomPage() }}
|
||||
>
|
||||
<FullScreenModal isOpen={isOpenModal}>
|
||||
<ProgressBarsModal
|
||||
progressBars={progressBars}
|
||||
onEndLoading={() => {
|
||||
setIsVisualLoading(false);
|
||||
checkLoading();
|
||||
}}
|
||||
>
|
||||
<Title variant="h2">{t("au.my_horoscope.loading_title")}</Title>
|
||||
<></>
|
||||
</ProgressBarsModal>
|
||||
</FullScreenModal>
|
||||
<div className={styles["cross-container"]}>
|
||||
<div className={styles.cross} onClick={handleNext}></div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["sign-image"]}
|
||||
style={{ backgroundImage: `url(${backgroundUrl})` }}
|
||||
>
|
||||
<Title variant="h2">
|
||||
{t("Receive an In-Depth Analysis and Today’s Horoscope")}
|
||||
</Title>
|
||||
</div>
|
||||
<p className={styles.text}>{text}</p>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default MyHoroscopeResult;
|
||||
79
src/components/pages/MyHoroscopeResult/styles.module.css
Normal file
79
src/components/pages/MyHoroscopeResult/styles.module.css
Normal file
@ -0,0 +1,79 @@
|
||||
.page {
|
||||
position: relative;
|
||||
height: fit-content;
|
||||
min-height: 100vh;
|
||||
flex: auto;
|
||||
/* max-height: -webkit-fill-available; */
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
overflow-y: scroll;
|
||||
padding-bottom: 180px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.loading-name {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.sign-image {
|
||||
width: 100%;
|
||||
height: 446px;
|
||||
color: #fd433f;
|
||||
border-radius: 17px;
|
||||
background-color: #000;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 18px;
|
||||
line-height: 22px;
|
||||
font-weight: 400;
|
||||
padding: 0 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.cross-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.cross {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
/* border: solid 2px #bdbdbd; */
|
||||
border-radius: 100%;
|
||||
rotate: 45deg;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cross::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
background-color: #bdbdbd;
|
||||
}
|
||||
|
||||
.cross::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 2px;
|
||||
height: 20px;
|
||||
background-color: #bdbdbd;
|
||||
}
|
||||
163
src/components/pages/NameHoroscopeResult/index.tsx
Normal file
163
src/components/pages/NameHoroscopeResult/index.tsx
Normal file
@ -0,0 +1,163 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Title from "@/components/Title";
|
||||
import styles from "./styles.module.css";
|
||||
import { useSelector } from "react-redux";
|
||||
import { selectors } from "@/store";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { AIRequestsV2, useApi, useApiCall } from "@/api";
|
||||
import { useNavigate, useSearchParams } from "react-router-dom";
|
||||
import routes from "@/routes";
|
||||
import FullScreenModal from "@/components/FullScreenModal";
|
||||
import ProgressBarsModal, { ProgressBar } from "@/components/ProgressBarsModal";
|
||||
import {
|
||||
getCategoryIdByZodiacSign,
|
||||
getZodiacSignByDate,
|
||||
} from "@/services/zodiac-sign";
|
||||
import { getRandomArbitrary } from "@/services/random-value";
|
||||
|
||||
function NameHoroscopeResult(): JSX.Element {
|
||||
const token = useSelector(selectors.selectToken);
|
||||
const { i18n, t } = useTranslation();
|
||||
const locale = i18n.language;
|
||||
const navigate = useNavigate();
|
||||
const api = useApi();
|
||||
const homeConfig = useSelector(selectors.selectHome);
|
||||
const showNavbarFooter = homeConfig.isShowNavbar;
|
||||
const [text, setText] = useState("Loading...");
|
||||
const [isOpenModal, setIsOpenModal] = useState(true);
|
||||
const [isVisualLoading, setIsVisualLoading] = useState(true);
|
||||
const [isDataLoading, setIsDataLoading] = useState(true);
|
||||
const [searchParams] = useSearchParams();
|
||||
const period = searchParams.get("period") || "today";
|
||||
const birthDate = useSelector(selectors.selectBirthdate);
|
||||
const zodiacSign = getZodiacSignByDate(birthDate);
|
||||
const [backgroundUrl, setBackgroundUrl] = useState("");
|
||||
const timeoutRef = useRef<NodeJS.Timeout>();
|
||||
|
||||
const progressBars: ProgressBar[] = [
|
||||
{
|
||||
label: t("au.name_horoscope.loading1"),
|
||||
},
|
||||
{
|
||||
label: t("au.name_horoscope.loading2"),
|
||||
},
|
||||
{
|
||||
label: t("au.name_horoscope.loading3"),
|
||||
},
|
||||
{
|
||||
label: t("au.name_horoscope.loading4"),
|
||||
},
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
clearTimeout(timeoutRef.current);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleNext = () => {
|
||||
return navigate(routes.client.home());
|
||||
};
|
||||
|
||||
const loadData = useCallback(async () => {
|
||||
const payload: AIRequestsV2.Payload = {
|
||||
aiRequest: {
|
||||
birthDate,
|
||||
sign: getZodiacSignByDate(birthDate).toLowerCase(),
|
||||
period,
|
||||
},
|
||||
promptKey: "horoscope_name",
|
||||
token,
|
||||
};
|
||||
const aIRequest = await api.AIRequestsV2(payload);
|
||||
if (aIRequest.ai_request.state !== "ready") {
|
||||
const getAIRequest = async () => {
|
||||
const aIRequestById = await api.getAIRequestsV2({
|
||||
id: aIRequest.ai_request.id,
|
||||
token,
|
||||
});
|
||||
if (aIRequestById.ai_request.state !== "ready") {
|
||||
timeoutRef.current = setTimeout(getAIRequest, 3000);
|
||||
}
|
||||
setText(aIRequestById?.ai_request?.response?.body || "Loading...");
|
||||
setIsDataLoading(false);
|
||||
checkLoading();
|
||||
return aIRequestById.ai_request;
|
||||
};
|
||||
return await getAIRequest();
|
||||
}
|
||||
setIsDataLoading(false);
|
||||
checkLoading();
|
||||
setText(aIRequest?.ai_request?.response?.response?.body || "Loading...");
|
||||
|
||||
return aIRequest?.ai_request?.response;
|
||||
}, [api, token, birthDate]);
|
||||
|
||||
useApiCall<AIRequestsV2.IAIRequest>(loadData);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
const { asset_categories } = await api.getAssetCategories({ locale });
|
||||
const categoryId = getCategoryIdByZodiacSign(
|
||||
zodiacSign,
|
||||
asset_categories
|
||||
);
|
||||
const assets = (
|
||||
await api.getAssets({ category: String(categoryId || "1") })
|
||||
).assets;
|
||||
const randomAsset = assets[getRandomArbitrary(0, assets.length - 1)];
|
||||
setBackgroundUrl(randomAsset.url);
|
||||
} catch (error) {
|
||||
console.error("Error: ", error);
|
||||
}
|
||||
})();
|
||||
}, [api, locale, zodiacSign]);
|
||||
|
||||
const getPaddingBottomPage = () => {
|
||||
if (showNavbarFooter) return "164px";
|
||||
return "108px";
|
||||
};
|
||||
|
||||
function checkLoading() {
|
||||
if (isVisualLoading || isDataLoading) {
|
||||
setIsOpenModal(true);
|
||||
} else {
|
||||
setIsOpenModal(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section
|
||||
className={`${styles.page} page`}
|
||||
style={{ paddingBottom: getPaddingBottomPage() }}
|
||||
>
|
||||
<FullScreenModal isOpen={isOpenModal}>
|
||||
<ProgressBarsModal
|
||||
progressBars={progressBars}
|
||||
onEndLoading={() => {
|
||||
setIsVisualLoading(false);
|
||||
checkLoading();
|
||||
}}
|
||||
>
|
||||
<Title variant="h2">{t("au.name_horoscope.loading_title")}</Title>
|
||||
<></>
|
||||
</ProgressBarsModal>
|
||||
</FullScreenModal>
|
||||
<div className={styles["cross-container"]}>
|
||||
<div className={styles.cross} onClick={handleNext}></div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["sign-image"]}
|
||||
style={{ backgroundImage: `url(${backgroundUrl})` }}
|
||||
>
|
||||
<Title variant="h2">
|
||||
{t("Receive an In-Depth Analysis and Today’s Horoscope")}
|
||||
</Title>
|
||||
</div>
|
||||
<p className={styles.text}>{text}</p>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default NameHoroscopeResult;
|
||||
79
src/components/pages/NameHoroscopeResult/styles.module.css
Normal file
79
src/components/pages/NameHoroscopeResult/styles.module.css
Normal file
@ -0,0 +1,79 @@
|
||||
.page {
|
||||
position: relative;
|
||||
height: fit-content;
|
||||
min-height: 100vh;
|
||||
flex: auto;
|
||||
/* max-height: -webkit-fill-available; */
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
overflow-y: scroll;
|
||||
padding-bottom: 180px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.loading-name {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.sign-image {
|
||||
width: 100%;
|
||||
height: 446px;
|
||||
color: #fd433f;
|
||||
border-radius: 17px;
|
||||
background-color: #000;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 18px;
|
||||
line-height: 22px;
|
||||
font-weight: 400;
|
||||
padding: 0 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.cross-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.cross {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
/* border: solid 2px #bdbdbd; */
|
||||
border-radius: 100%;
|
||||
rotate: 45deg;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cross::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
background-color: #bdbdbd;
|
||||
}
|
||||
|
||||
.cross::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 2px;
|
||||
height: 20px;
|
||||
background-color: #bdbdbd;
|
||||
}
|
||||
156
src/components/pages/PredictionMoonResult/index.tsx
Normal file
156
src/components/pages/PredictionMoonResult/index.tsx
Normal file
@ -0,0 +1,156 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Title from "@/components/Title";
|
||||
import styles from "./styles.module.css";
|
||||
import { useSelector } from "react-redux";
|
||||
import { selectors } from "@/store";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { AIRequestsV2, useApi, useApiCall } from "@/api";
|
||||
import { useNavigate, useSearchParams } from "react-router-dom";
|
||||
import routes from "@/routes";
|
||||
import FullScreenModal from "@/components/FullScreenModal";
|
||||
import ProgressBarsModal, { ProgressBar } from "@/components/ProgressBarsModal";
|
||||
import {
|
||||
getCategoryIdByZodiacSign,
|
||||
getZodiacSignByDate,
|
||||
} from "@/services/zodiac-sign";
|
||||
import { getRandomArbitrary } from "@/services/random-value";
|
||||
|
||||
function PredictionMoonResult(): JSX.Element {
|
||||
const token = useSelector(selectors.selectToken);
|
||||
const { i18n, t } = useTranslation();
|
||||
const locale = i18n.language;
|
||||
const navigate = useNavigate();
|
||||
const api = useApi();
|
||||
const homeConfig = useSelector(selectors.selectHome);
|
||||
const showNavbarFooter = homeConfig.isShowNavbar;
|
||||
const [text, setText] = useState("Loading...");
|
||||
const [isOpenModal, setIsOpenModal] = useState(true);
|
||||
const [isVisualLoading, setIsVisualLoading] = useState(true);
|
||||
const [isDataLoading, setIsDataLoading] = useState(true);
|
||||
const [searchParams] = useSearchParams();
|
||||
const period = searchParams.get("period");
|
||||
const birthDate = useSelector(selectors.selectBirthdate);
|
||||
const zodiacSign = getZodiacSignByDate(birthDate);
|
||||
const [backgroundUrl, setBackgroundUrl] = useState("");
|
||||
|
||||
const progressBars: ProgressBar[] = [
|
||||
{
|
||||
label: t("au.prediction_moons.loading1"),
|
||||
},
|
||||
{
|
||||
label: t("au.prediction_moons.loading2"),
|
||||
},
|
||||
{
|
||||
label: t("au.prediction_moons.loading3"),
|
||||
},
|
||||
{
|
||||
label: t("au.prediction_moons.loading4"),
|
||||
},
|
||||
];
|
||||
|
||||
const handleNext = () => {
|
||||
return navigate(routes.client.home());
|
||||
};
|
||||
|
||||
const loadData = useCallback(async () => {
|
||||
const payload: AIRequestsV2.Payload = {
|
||||
aiRequest: {
|
||||
birthDate,
|
||||
sign: getZodiacSignByDate(birthDate).toLowerCase(),
|
||||
period: period?.toLowerCase() || "today",
|
||||
},
|
||||
promptKey: "prediction_moons",
|
||||
token,
|
||||
};
|
||||
const aIRequest = await api.AIRequestsV2(payload);
|
||||
if (aIRequest.ai_request.state !== "ready") {
|
||||
const getAIRequest = async () => {
|
||||
const aIRequestById = await api.getAIRequestsV2({
|
||||
id: aIRequest.ai_request.id,
|
||||
token,
|
||||
});
|
||||
if (aIRequestById.ai_request.state !== "ready") {
|
||||
setTimeout(getAIRequest, 3000);
|
||||
}
|
||||
setText(aIRequestById?.ai_request?.response?.body || "Loading...");
|
||||
setIsDataLoading(false);
|
||||
checkLoading();
|
||||
return aIRequestById.ai_request;
|
||||
};
|
||||
return await getAIRequest();
|
||||
}
|
||||
setIsDataLoading(false);
|
||||
checkLoading();
|
||||
setText(aIRequest?.ai_request?.response?.response?.body || "Loading...");
|
||||
|
||||
return aIRequest?.ai_request?.response;
|
||||
}, [api, token, birthDate, period]);
|
||||
|
||||
useApiCall<AIRequestsV2.IAIRequest>(loadData);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
const { asset_categories } = await api.getAssetCategories({ locale });
|
||||
const categoryId = getCategoryIdByZodiacSign(
|
||||
zodiacSign,
|
||||
asset_categories
|
||||
);
|
||||
const assets = (
|
||||
await api.getAssets({ category: String(categoryId || "1") })
|
||||
).assets;
|
||||
const randomAsset = assets[getRandomArbitrary(0, assets.length - 1)];
|
||||
setBackgroundUrl(randomAsset.url);
|
||||
} catch (error) {
|
||||
console.error("Error: ", error);
|
||||
}
|
||||
})();
|
||||
}, [api, locale, zodiacSign]);
|
||||
|
||||
const getPaddingBottomPage = () => {
|
||||
if (showNavbarFooter) return "164px";
|
||||
return "108px";
|
||||
};
|
||||
|
||||
function checkLoading() {
|
||||
if (isVisualLoading || isDataLoading) {
|
||||
setIsOpenModal(true);
|
||||
} else {
|
||||
setIsOpenModal(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section
|
||||
className={`${styles.page} page`}
|
||||
style={{ paddingBottom: getPaddingBottomPage() }}
|
||||
>
|
||||
<FullScreenModal isOpen={isOpenModal}>
|
||||
<ProgressBarsModal
|
||||
progressBars={progressBars}
|
||||
onEndLoading={() => {
|
||||
setIsVisualLoading(false);
|
||||
checkLoading();
|
||||
}}
|
||||
>
|
||||
<Title variant="h2">{t("au.prediction_moons.loading_title")}</Title>
|
||||
<></>
|
||||
</ProgressBarsModal>
|
||||
</FullScreenModal>
|
||||
<div className={styles["cross-container"]}>
|
||||
<div className={styles.cross} onClick={handleNext}></div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["sign-image"]}
|
||||
style={{ backgroundImage: `url(${backgroundUrl})` }}
|
||||
>
|
||||
<Title variant="h2">
|
||||
{t("au.prediction_moons.result_title")} {period}
|
||||
</Title>
|
||||
</div>
|
||||
<p className={styles.text}>{text}</p>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default PredictionMoonResult;
|
||||
79
src/components/pages/PredictionMoonResult/styles.module.css
Normal file
79
src/components/pages/PredictionMoonResult/styles.module.css
Normal file
@ -0,0 +1,79 @@
|
||||
.page {
|
||||
position: relative;
|
||||
height: fit-content;
|
||||
min-height: 100vh;
|
||||
flex: auto;
|
||||
/* max-height: -webkit-fill-available; */
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
overflow-y: scroll;
|
||||
padding-bottom: 180px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.loading-name {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.sign-image {
|
||||
width: 100%;
|
||||
height: 446px;
|
||||
color: #fd433f;
|
||||
border-radius: 17px;
|
||||
background-color: #000;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 18px;
|
||||
line-height: 22px;
|
||||
font-weight: 400;
|
||||
padding: 0 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.cross-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.cross {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
/* border: solid 2px #bdbdbd; */
|
||||
border-radius: 100%;
|
||||
rotate: 45deg;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cross::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
background-color: #bdbdbd;
|
||||
}
|
||||
|
||||
.cross::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 2px;
|
||||
height: 20px;
|
||||
background-color: #bdbdbd;
|
||||
}
|
||||
160
src/components/pages/ThermalResult/index.tsx
Normal file
160
src/components/pages/ThermalResult/index.tsx
Normal file
@ -0,0 +1,160 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Title from "@/components/Title";
|
||||
import styles from "./styles.module.css";
|
||||
import { useSelector } from "react-redux";
|
||||
import { selectors } from "@/store";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { AIRequestsV2, useApi, useApiCall } from "@/api";
|
||||
import { useNavigate, useSearchParams } from "react-router-dom";
|
||||
import routes from "@/routes";
|
||||
import FullScreenModal from "@/components/FullScreenModal";
|
||||
import ProgressBarsModal, { ProgressBar } from "@/components/ProgressBarsModal";
|
||||
import {
|
||||
getCategoryIdByZodiacSign,
|
||||
getZodiacSignByDate,
|
||||
} from "@/services/zodiac-sign";
|
||||
import { getRandomArbitrary } from "@/services/random-value";
|
||||
|
||||
function ThermalResult(): JSX.Element {
|
||||
const token = useSelector(selectors.selectToken);
|
||||
const { i18n, t } = useTranslation();
|
||||
const locale = i18n.language;
|
||||
const navigate = useNavigate();
|
||||
const api = useApi();
|
||||
const homeConfig = useSelector(selectors.selectHome);
|
||||
const showNavbarFooter = homeConfig.isShowNavbar;
|
||||
const [text, setText] = useState("Loading...");
|
||||
const [isOpenModal, setIsOpenModal] = useState(true);
|
||||
const [isVisualLoading, setIsVisualLoading] = useState(true);
|
||||
const [isDataLoading, setIsDataLoading] = useState(true);
|
||||
const [searchParams] = useSearchParams();
|
||||
const name = searchParams.get("name");
|
||||
const birthDate = searchParams.get("birthDate") || "";
|
||||
const zodiacSign = getZodiacSignByDate(birthDate);
|
||||
const [backgroundUrl, setBackgroundUrl] = useState("");
|
||||
|
||||
const progressBars: ProgressBar[] = [
|
||||
{
|
||||
label: t("au.thermal_compatibility.loading1"),
|
||||
},
|
||||
{
|
||||
label: t("au.thermal_compatibility.loading2"),
|
||||
},
|
||||
{
|
||||
label: t("au.thermal_compatibility.loading3"),
|
||||
},
|
||||
{
|
||||
label: t("au.thermal_compatibility.loading4"),
|
||||
},
|
||||
];
|
||||
|
||||
const handleNext = () => {
|
||||
return navigate(routes.client.home());
|
||||
};
|
||||
|
||||
const loadData = useCallback(async () => {
|
||||
const payload: AIRequestsV2.Payload = {
|
||||
aiRequest: {
|
||||
birthDate,
|
||||
sign: getZodiacSignByDate(birthDate).toLowerCase(),
|
||||
period: 'today'
|
||||
},
|
||||
promptKey: "compatibility_thermal",
|
||||
token,
|
||||
};
|
||||
const aIRequest = await api.AIRequestsV2(payload);
|
||||
if (aIRequest.ai_request.state !== "ready") {
|
||||
const getAIRequest = async () => {
|
||||
const aIRequestById = await api.getAIRequestsV2({
|
||||
id: aIRequest.ai_request.id,
|
||||
token,
|
||||
});
|
||||
if (aIRequestById.ai_request.state !== "ready") {
|
||||
setTimeout(getAIRequest, 3000);
|
||||
}
|
||||
setText(aIRequestById?.ai_request?.response?.body || "Loading...");
|
||||
setIsDataLoading(false);
|
||||
checkLoading();
|
||||
return aIRequestById.ai_request;
|
||||
};
|
||||
return await getAIRequest();
|
||||
}
|
||||
setIsDataLoading(false);
|
||||
checkLoading();
|
||||
setText(aIRequest?.ai_request?.response?.response?.body || "Loading...");
|
||||
|
||||
return aIRequest?.ai_request?.response;
|
||||
}, [api, token, birthDate]);
|
||||
|
||||
useApiCall<AIRequestsV2.IAIRequest>(loadData);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
const { asset_categories } = await api.getAssetCategories({ locale });
|
||||
const categoryId = getCategoryIdByZodiacSign(
|
||||
zodiacSign,
|
||||
asset_categories
|
||||
);
|
||||
const assets = (
|
||||
await api.getAssets({ category: String(categoryId || "1") })
|
||||
).assets;
|
||||
const randomAsset = assets[getRandomArbitrary(0, assets.length - 1)];
|
||||
setBackgroundUrl(randomAsset.url);
|
||||
} catch (error) {
|
||||
console.error("Error: ", error);
|
||||
}
|
||||
})();
|
||||
}, [api, locale, zodiacSign]);
|
||||
|
||||
const getPaddingBottomPage = () => {
|
||||
if (showNavbarFooter) return "164px";
|
||||
return "108px";
|
||||
};
|
||||
|
||||
function checkLoading() {
|
||||
if (isVisualLoading || isDataLoading) {
|
||||
setIsOpenModal(true);
|
||||
} else {
|
||||
setIsOpenModal(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section
|
||||
className={`${styles.page} page`}
|
||||
style={{ paddingBottom: getPaddingBottomPage() }}
|
||||
>
|
||||
<FullScreenModal isOpen={isOpenModal}>
|
||||
<ProgressBarsModal
|
||||
progressBars={progressBars}
|
||||
onEndLoading={() => {
|
||||
setIsVisualLoading(false);
|
||||
checkLoading();
|
||||
}}
|
||||
>
|
||||
<Title variant="h2">
|
||||
{t("au.thermal_compatibility.loading_title")}
|
||||
</Title>
|
||||
<></>
|
||||
</ProgressBarsModal>
|
||||
</FullScreenModal>
|
||||
<div className={styles["cross-container"]}>
|
||||
<div className={styles.cross} onClick={handleNext}></div>
|
||||
</div>
|
||||
<div
|
||||
className={styles["sign-image"]}
|
||||
style={{ backgroundImage: `url(${backgroundUrl})` }}
|
||||
>
|
||||
<img className={styles["thermal-image"]} src={backgroundUrl} alt="background image" />
|
||||
<Title className={styles.title} variant="h2">
|
||||
{t("au.thermal_compatibility.result_title")}{" "}
|
||||
<span className={styles["loading-name"]}>{name}</span>
|
||||
</Title>
|
||||
</div>
|
||||
<p className={styles.text}>{text}</p>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default ThermalResult;
|
||||
94
src/components/pages/ThermalResult/styles.module.css
Normal file
94
src/components/pages/ThermalResult/styles.module.css
Normal file
@ -0,0 +1,94 @@
|
||||
.page {
|
||||
position: relative;
|
||||
height: fit-content;
|
||||
min-height: 100vh;
|
||||
flex: auto;
|
||||
/* max-height: -webkit-fill-available; */
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
overflow-y: scroll;
|
||||
padding-bottom: 180px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.loading-name {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.sign-image {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
aspect-ratio: 1 / 1;
|
||||
color: #fd433f;
|
||||
border-radius: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.thermal-image {
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
left: -15px;
|
||||
width: calc(100% + 30px);
|
||||
height: calc(100% + 30px);
|
||||
object-fit: cover;
|
||||
border-radius: 100%;
|
||||
filter: blur(36px);
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.title {
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 18px;
|
||||
line-height: 22px;
|
||||
font-weight: 400;
|
||||
padding: 0 8px;
|
||||
text-align: left;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.cross-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.cross {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
/* border: solid 2px #bdbdbd; */
|
||||
border-radius: 100%;
|
||||
rotate: 45deg;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cross::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
background-color: #bdbdbd;
|
||||
}
|
||||
|
||||
.cross::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 2px;
|
||||
height: 20px;
|
||||
background-color: #bdbdbd;
|
||||
}
|
||||
16
src/data.ts
Normal file
16
src/data.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { IPredictionMoon } from "./components/PredictionMoonsSlider";
|
||||
|
||||
export const predictionMoonsPeriods: IPredictionMoon[] = [
|
||||
{
|
||||
period: "today",
|
||||
},
|
||||
{
|
||||
period: "week",
|
||||
},
|
||||
{
|
||||
period: "month",
|
||||
},
|
||||
{
|
||||
period: "year",
|
||||
},
|
||||
];
|
||||
@ -34,11 +34,19 @@ const routes = {
|
||||
home: () => [host, "home"].join("/"),
|
||||
breathResult: () => [host, "breath", "result"].join("/"),
|
||||
magicBall: () => [host, "magic-ball"].join("/"),
|
||||
horoscopeBestiesResult: () => [host, "horoscope", "besties"].join("/"),
|
||||
horoscopeBestiesResult: () => [host, "horoscope-besties"].join("/"),
|
||||
predictionMoonResult: () => [host, "prediction-moon"].join("/"),
|
||||
myHoroscopeResult: () => [host, "my-horoscope"].join("/"),
|
||||
thermalResult: () => [host, "thermal"].join("/"),
|
||||
moonPhaseTracker: () => [host, "moon-phase-tracker"].join("/"),
|
||||
energyVampirismResult: () => [host, "energy-vampirism"].join("/"),
|
||||
nameHoroscopeResult: () => [host, "name-horoscope"].join("/"),
|
||||
},
|
||||
server: {
|
||||
appleAuth: (origin: string) => [apiHost, "auth", "apple", `gate?origin=${origin}`].join("/"),
|
||||
googleAuth: (origin: string) => [apiHost, "auth", "google", `gate?origin=${origin}`].join("/"),
|
||||
appleAuth: (origin: string) =>
|
||||
[apiHost, "auth", "apple", `gate?origin=${origin}`].join("/"),
|
||||
googleAuth: (origin: string) =>
|
||||
[apiHost, "auth", "google", `gate?origin=${origin}`].join("/"),
|
||||
user: () => [apiHost, prefix, "user.json"].join("/"),
|
||||
token: () => [apiHost, prefix, "auth", "token.json"].join("/"),
|
||||
elements: () => [apiHost, prefix, "elements.json"].join("/"),
|
||||
@ -82,8 +90,12 @@ const routes = {
|
||||
getUserCallbacks: (id: string) =>
|
||||
[apiHost, prefix, "user", "callbacks", `${id}.json`].join("/"),
|
||||
getTranslations: () => [siteHost, "api/v2", "t.json"].join("/"),
|
||||
aiRequestsV2: (promptKey: string) => [apiHost, "api/v2", "ai", "prompts", promptKey, "requests.json"].join("/"),
|
||||
getAiRequestsV2: (id: string) => [apiHost, "api/v2", "ai", "requests", `${id}.json`].join("/"),
|
||||
aiRequestsV2: (promptKey: string) =>
|
||||
[apiHost, "api/v2", "ai", "prompts", promptKey, "requests.json"].join(
|
||||
"/"
|
||||
),
|
||||
getAiRequestsV2: (id: string) =>
|
||||
[apiHost, "api/v2", "ai", "requests", `${id}.json`].join("/"),
|
||||
},
|
||||
};
|
||||
|
||||
@ -137,6 +149,12 @@ export const withoutFooterRoutes = [
|
||||
routes.client.paymentStripe(),
|
||||
routes.client.magicBall(),
|
||||
routes.client.horoscopeBestiesResult(),
|
||||
routes.client.predictionMoonResult(),
|
||||
routes.client.myHoroscopeResult(),
|
||||
routes.client.thermalResult(),
|
||||
routes.client.moonPhaseTracker(),
|
||||
routes.client.energyVampirismResult(),
|
||||
routes.client.nameHoroscopeResult(),
|
||||
];
|
||||
export const hasNoFooter = (path: string) =>
|
||||
!withoutFooterRoutes.includes(path);
|
||||
@ -161,6 +179,13 @@ export const withoutHeaderRoutes = [
|
||||
routes.client.paymentFail(),
|
||||
routes.client.magicBall(),
|
||||
routes.client.horoscopeBestiesResult(),
|
||||
routes.client.predictionMoonResult(),
|
||||
routes.client.myHoroscopeResult(),
|
||||
routes.client.myHoroscopeResult(),
|
||||
routes.client.thermalResult(),
|
||||
routes.client.moonPhaseTracker(),
|
||||
routes.client.energyVampirismResult(),
|
||||
routes.client.nameHoroscopeResult(),
|
||||
];
|
||||
export const hasNoHeader = (path: string) =>
|
||||
!withoutHeaderRoutes.includes(path);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user