feat: add user path from home, add preview before breath, fix home buttons background color
This commit is contained in:
parent
ed5cd812ce
commit
30d1ded4f5
@ -16,6 +16,7 @@ function BreathPage(): JSX.Element {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [asset, setAsset] = useState<Asset>();
|
const [asset, setAsset] = useState<Asset>();
|
||||||
const [isOpenModal, setIsOpenModal] = useState<boolean>(true);
|
const [isOpenModal, setIsOpenModal] = useState<boolean>(true);
|
||||||
|
const [isShowPreview, setIsShowPreview] = useState<boolean>(true);
|
||||||
const api = useApi();
|
const api = useApi();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -27,26 +28,33 @@ function BreathPage(): JSX.Element {
|
|||||||
return assets;
|
return assets;
|
||||||
}, [api]);
|
}, [api]);
|
||||||
|
|
||||||
const {
|
const { data } = useApiCall<Asset[]>(assetsData);
|
||||||
data,
|
|
||||||
} = useApiCall<Asset[]>(assetsData);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpenModal) return;
|
if (isOpenModal) return;
|
||||||
|
const previewTimeOut = setTimeout(() => {
|
||||||
|
setIsShowPreview(false);
|
||||||
|
}, 10_000);
|
||||||
|
|
||||||
const timeOut = setTimeout(() => {
|
const navigateTimeOut = setTimeout(() => {
|
||||||
navigate(routes.client.breathResult());
|
navigate(routes.client.breathResult());
|
||||||
}, 50_000);
|
}, 60_000);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
clearTimeout(timeOut);
|
clearTimeout(navigateTimeOut);
|
||||||
|
clearTimeout(previewTimeOut);
|
||||||
};
|
};
|
||||||
}, [navigate, isOpenModal]);
|
}, [navigate, isOpenModal]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data) {
|
if (!data) return;
|
||||||
|
const leoTimeOut = setTimeout(() => {
|
||||||
setAsset(data[getRandomArbitrary(0, data?.length || 0)]);
|
setAsset(data[getRandomArbitrary(0, data?.length || 0)]);
|
||||||
}
|
}, 10_000);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearTimeout(leoTimeOut);
|
||||||
|
};
|
||||||
}, [data, isOpenModal]);
|
}, [data, isOpenModal]);
|
||||||
|
|
||||||
const beginBreath = () => {
|
const beginBreath = () => {
|
||||||
@ -95,13 +103,26 @@ function BreathPage(): JSX.Element {
|
|||||||
<section
|
<section
|
||||||
className={`${styles.page} page`}
|
className={`${styles.page} page`}
|
||||||
style={{
|
style={{
|
||||||
backgroundImage: !isOpenModal ? `url(${asset?.url})` : "none",
|
backgroundImage: `url(${
|
||||||
|
!isOpenModal && !isShowPreview ? asset?.url : "none"
|
||||||
|
})`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{!isOpenModal && isShowPreview && (
|
||||||
|
<div className={styles.preview}>
|
||||||
|
<img className={styles.leo} src="/leo.png" alt="leo" />
|
||||||
|
<Title
|
||||||
|
variant="h2"
|
||||||
|
className={`${styles.text} ${styles["breath-relax"]}`}
|
||||||
|
>
|
||||||
|
{t("aura.breath_relax.text")}
|
||||||
|
</Title>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<FullScreenModal isOpen={isOpenModal}>
|
<FullScreenModal isOpen={isOpenModal}>
|
||||||
<StartBreathModalChild handleBegin={beginBreath} />
|
<StartBreathModalChild handleBegin={beginBreath} />
|
||||||
</FullScreenModal>
|
</FullScreenModal>
|
||||||
{!isOpenModal && (
|
{!isOpenModal && !isShowPreview && (
|
||||||
<div className={styles["text-container"]}>
|
<div className={styles["text-container"]}>
|
||||||
<Title
|
<Title
|
||||||
variant="h2"
|
variant="h2"
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: #01010b;
|
background-color: #01010b;
|
||||||
background-size: cover;
|
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
flex: auto;
|
flex: auto;
|
||||||
}
|
}
|
||||||
@ -38,6 +38,85 @@
|
|||||||
animation-timing-function: linear;
|
animation-timing-function: linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.preview {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leo {
|
||||||
|
width: 90%;
|
||||||
|
animation-name: leo;
|
||||||
|
animation-duration: 10s;
|
||||||
|
animation-iteration-count: 1;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breath-relax {
|
||||||
|
animation-name: breath-relax;
|
||||||
|
animation-duration: 10s;
|
||||||
|
animation-iteration-count: 1;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes leo {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
scale: 1;
|
||||||
|
}
|
||||||
|
5% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
10% {
|
||||||
|
scale: 1;
|
||||||
|
}
|
||||||
|
25% {
|
||||||
|
scale: 1.1;
|
||||||
|
}
|
||||||
|
35% {
|
||||||
|
scale: 1.1;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
scale: 1;
|
||||||
|
}
|
||||||
|
60% {
|
||||||
|
scale: 1;
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
scale: 1.1;
|
||||||
|
}
|
||||||
|
85% {
|
||||||
|
scale: 1.1;
|
||||||
|
}
|
||||||
|
95% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
scale: 1;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes breath-relax {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
5% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
10% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
95% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
scale: 1;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes breath-in {
|
@keyframes breath-in {
|
||||||
0% {
|
0% {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|||||||
@ -1,21 +1,41 @@
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import Title from "../Title";
|
import Title from "../Title";
|
||||||
import styles from "./styles.module.css";
|
import styles from "./styles.module.css";
|
||||||
import { useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { selectors } from "@/store";
|
import { actions, selectors } from "@/store";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
import { AICompats, AIRequests, useApi, useApiCall } from "@/api";
|
import { AICompats, AIRequests, useApi, useApiCall } from "@/api";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import routes from "@/routes";
|
||||||
|
import { EPathsFromHome } from "@/store/siteConfig";
|
||||||
|
|
||||||
function CompatResultPage(): JSX.Element {
|
function CompatResultPage(): JSX.Element {
|
||||||
const token =
|
const token =
|
||||||
"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjIzNjEyLCJpYXQiOjE2OTM0MTg5MTAsImV4cCI6MTcwMjA1ODkxMCwianRpIjoiNzg5MjkwYWItODg0YS00MGUyLTkyNjEtOWI2OGEyNjkwNmE0IiwiZW1haWwiOiJvdGhlckBleGFtcGxlLmNvbSIsInN0YXRlIjoicHJvdmVuIiwibG9jIjoiZW4iLCJ0eiI6LTI4ODAwLCJ0eXBlIjoiZW1haWwiLCJpc3MiOiJjb20ubGlmZS5hdXJhIn0.J2ocWIv5jKzuKMcwMgWMiNMyGg5qLlMAeln-bQm_9lw";
|
"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjIzNjEyLCJpYXQiOjE2OTM0MTg5MTAsImV4cCI6MTcwMjA1ODkxMCwianRpIjoiNzg5MjkwYWItODg0YS00MGUyLTkyNjEtOWI2OGEyNjkwNmE0IiwiZW1haWwiOiJvdGhlckBleGFtcGxlLmNvbSIsInN0YXRlIjoicHJvdmVuIiwibG9jIjoiZW4iLCJ0eiI6LTI4ODAwLCJ0eXBlIjoiZW1haWwiLCJpc3MiOiJjb20ubGlmZS5hdXJhIn0.J2ocWIv5jKzuKMcwMgWMiNMyGg5qLlMAeln-bQm_9lw";
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const navigate = useNavigate();
|
||||||
const api = useApi();
|
const api = useApi();
|
||||||
|
const dispatch = useDispatch();
|
||||||
const birthdate = useSelector(selectors.selectBirthdate);
|
const birthdate = useSelector(selectors.selectBirthdate);
|
||||||
const rightUser = useSelector(selectors.selectRightUser);
|
const rightUser = useSelector(selectors.selectRightUser);
|
||||||
const categoryId = useSelector(selectors.selectCategoryId);
|
const categoryId = useSelector(selectors.selectCategoryId);
|
||||||
|
const homeConfig = useSelector(selectors.selectHome);
|
||||||
const [text, setText] = useState("Loading...");
|
const [text, setText] = useState("Loading...");
|
||||||
|
|
||||||
|
const handleNext = () => {
|
||||||
|
dispatch(
|
||||||
|
actions.siteConfig.update({
|
||||||
|
home: { pathFromHome: homeConfig.pathFromHome, isShowNavbar: true },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
if (homeConfig.pathFromHome === EPathsFromHome.breath) {
|
||||||
|
return navigate(routes.client.home());
|
||||||
|
}
|
||||||
|
if (homeConfig.pathFromHome === EPathsFromHome.compatibility) {
|
||||||
|
return navigate(routes.client.breath());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const loadData = useCallback(async () => {
|
const loadData = useCallback(async () => {
|
||||||
const right_bday =
|
const right_bday =
|
||||||
typeof rightUser.birthDate === "string"
|
typeof rightUser.birthDate === "string"
|
||||||
@ -55,6 +75,7 @@ function CompatResultPage(): JSX.Element {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`${styles.page} page`}>
|
<section className={`${styles.page} page`}>
|
||||||
|
{text !== "Loading..." && <div className={styles.cross} onClick={handleNext}></div>}
|
||||||
<div className={styles["title-container"]}>
|
<div className={styles["title-container"]}>
|
||||||
<Title variant="h2">{t("you_and", { user: rightUser.name })}</Title>
|
<Title variant="h2">{t("you_and", { user: rightUser.name })}</Title>
|
||||||
</div>
|
</div>
|
||||||
@ -64,6 +85,19 @@ function CompatResultPage(): JSX.Element {
|
|||||||
</Title>
|
</Title>
|
||||||
<p className={styles["result-container__text"]}>{text}</p>
|
<p className={styles["result-container__text"]}>{text}</p>
|
||||||
</div>
|
</div>
|
||||||
|
{text !== "Loading..." && (
|
||||||
|
<div className={styles["button-container"]}>
|
||||||
|
<p className={styles["button-container__text"]}>
|
||||||
|
{t("now-you-know")}
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
className={styles["button-container__button"]}
|
||||||
|
onClick={handleNext}
|
||||||
|
>
|
||||||
|
{t("go-through")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,30 +2,100 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
height: calc(100vh - 50px);
|
height: calc(100vh - 50px);
|
||||||
flex: auto;
|
flex: auto;
|
||||||
max-height: -webkit-fill-available;
|
/* max-height: -webkit-fill-available; */
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
padding-bottom: 180px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title-container {
|
.title-container {
|
||||||
color: #e9445a;
|
color: #e9445a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.percent {
|
.percent {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.result-container {
|
.result-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.result-container__title {
|
.result-container__title {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.result-container__text {
|
.result-container__text {
|
||||||
white-space:pre-wrap;
|
white-space: pre-wrap;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button-container {
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 560px;
|
||||||
|
bottom: 0;
|
||||||
|
border-radius: 16px 16px 0 0;
|
||||||
|
background-color: rgba(128, 128, 128, 0.546);
|
||||||
|
-webkit-backdrop-filter: blur(14px);
|
||||||
|
backdrop-filter: blur(14px);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 16px 0 24px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-container__text {
|
||||||
|
max-width: calc(100% - 64px);
|
||||||
|
text-align: center;
|
||||||
|
color: #7ce4fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-container__button {
|
||||||
|
border: none;
|
||||||
|
bottom: 24px;
|
||||||
|
width: calc(100% - 64px);
|
||||||
|
max-width: 496px;
|
||||||
|
border-radius: 32px;
|
||||||
|
padding: 24px 0;
|
||||||
|
background: -moz-linear-gradient(to bottom, #2dc8e2, #2b7ed6);
|
||||||
|
background: -webkit-linear-gradient(to bottom, #2dc8e2, #2b7ed6);
|
||||||
|
background: linear-gradient(to bottom, #2dc8e2, #2b7ed6);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cross {
|
||||||
|
position: absolute;
|
||||||
|
top: 24px;
|
||||||
|
right: 24px;
|
||||||
|
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: 10px;
|
||||||
|
height: 2px;
|
||||||
|
background-color: #bdbdbd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cross::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 2px;
|
||||||
|
height: 10px;
|
||||||
|
background-color: #bdbdbd;
|
||||||
|
}
|
||||||
|
|||||||
@ -22,6 +22,7 @@ function CompatibilityPage(): JSX.Element {
|
|||||||
const [name, setName] = useState<string>('');
|
const [name, setName] = useState<string>('');
|
||||||
const [date, setDate] = useState<string | IDate>('');
|
const [date, setDate] = useState<string | IDate>('');
|
||||||
const [compatCategory, setCompatCategory] = useState(1);
|
const [compatCategory, setCompatCategory] = useState(1);
|
||||||
|
|
||||||
const handleNext = () => {
|
const handleNext = () => {
|
||||||
dispatch(actions.compatibility.update({
|
dispatch(actions.compatibility.update({
|
||||||
rightUser: {
|
rightUser: {
|
||||||
|
|||||||
@ -8,13 +8,19 @@ import { useCallback, useEffect, useState } from "react";
|
|||||||
import BlurringSubstrate from "../BlurringSubstrate";
|
import BlurringSubstrate from "../BlurringSubstrate";
|
||||||
import EnergyValues from "../EnergyValues";
|
import EnergyValues from "../EnergyValues";
|
||||||
import { UserAura } from "@/api/resources/Auras";
|
import { UserAura } from "@/api/resources/Auras";
|
||||||
import { useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { getCategoryIdByZodiacSign, getZodiacSignByDate } from "@/services/zodiac-sign";
|
import {
|
||||||
import { selectors } from "@/store";
|
getCategoryIdByZodiacSign,
|
||||||
|
getZodiacSignByDate,
|
||||||
|
} from "@/services/zodiac-sign";
|
||||||
|
import { actions, selectors } from "@/store";
|
||||||
import { getRandomArbitrary } from "@/services/random-value";
|
import { getRandomArbitrary } from "@/services/random-value";
|
||||||
import Title from "../Title";
|
import Title from "../Title";
|
||||||
import { UserDailyForecast } from "@/api/resources/UserDailyForecasts";
|
import { UserDailyForecast } from "@/api/resources/UserDailyForecasts";
|
||||||
import { download } from "@/services/download";
|
import { download } from "@/services/download";
|
||||||
|
import { EPathsFromHome } from "@/store/siteConfig";
|
||||||
|
import NavbarHome, { INavbarHomeItems } from "../NavbarHome";
|
||||||
|
|
||||||
|
|
||||||
const buttonTextFormatter = (text: string): JSX.Element => {
|
const buttonTextFormatter = (text: string): JSX.Element => {
|
||||||
const sentences = text.split(".");
|
const sentences = text.split(".");
|
||||||
@ -32,12 +38,54 @@ function HomePage(): JSX.Element {
|
|||||||
"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjIzNjEyLCJpYXQiOjE2OTM0MTg5MTAsImV4cCI6MTcwMjA1ODkxMCwianRpIjoiNzg5MjkwYWItODg0YS00MGUyLTkyNjEtOWI2OGEyNjkwNmE0IiwiZW1haWwiOiJvdGhlckBleGFtcGxlLmNvbSIsInN0YXRlIjoicHJvdmVuIiwibG9jIjoiZW4iLCJ0eiI6LTI4ODAwLCJ0eXBlIjoiZW1haWwiLCJpc3MiOiJjb20ubGlmZS5hdXJhIn0.J2ocWIv5jKzuKMcwMgWMiNMyGg5qLlMAeln-bQm_9lw";
|
"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOjIzNjEyLCJpYXQiOjE2OTM0MTg5MTAsImV4cCI6MTcwMjA1ODkxMCwianRpIjoiNzg5MjkwYWItODg0YS00MGUyLTkyNjEtOWI2OGEyNjkwNmE0IiwiZW1haWwiOiJvdGhlckBleGFtcGxlLmNvbSIsInN0YXRlIjoicHJvdmVuIiwibG9jIjoiZW4iLCJ0eiI6LTI4ODAwLCJ0eXBlIjoiZW1haWwiLCJpc3MiOiJjb20ubGlmZS5hdXJhIn0.J2ocWIv5jKzuKMcwMgWMiNMyGg5qLlMAeln-bQm_9lw";
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const homeConfig = useSelector(selectors.selectHome);
|
||||||
|
const isShowNavbar = homeConfig.isShowNavbar;
|
||||||
const handleCompatibility = () => {
|
const handleCompatibility = () => {
|
||||||
|
dispatch(
|
||||||
|
actions.siteConfig.update({
|
||||||
|
home: { pathFromHome: EPathsFromHome.compatibility, isShowNavbar },
|
||||||
|
})
|
||||||
|
);
|
||||||
navigate(routes.client.compatibility());
|
navigate(routes.client.compatibility());
|
||||||
};
|
};
|
||||||
const handleBreath = () => {
|
const handleBreath = () => {
|
||||||
|
dispatch(
|
||||||
|
actions.siteConfig.update({
|
||||||
|
home: { pathFromHome: EPathsFromHome.breath, isShowNavbar },
|
||||||
|
})
|
||||||
|
);
|
||||||
navigate(routes.client.breath());
|
navigate(routes.client.breath());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const navbarHomeItems: INavbarHomeItems[] = [
|
||||||
|
{
|
||||||
|
title: 'Breathing',
|
||||||
|
path: routes.client.breath(),
|
||||||
|
image: '',
|
||||||
|
onClick: handleBreath
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Aura',
|
||||||
|
path: routes.client.home(),
|
||||||
|
image: '',
|
||||||
|
active: true,
|
||||||
|
onClick: () => null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Compatibility',
|
||||||
|
path: routes.client.compatibility(),
|
||||||
|
image: '',
|
||||||
|
onClick: handleCompatibility
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'My Moon',
|
||||||
|
path: routes.client.home(),
|
||||||
|
image: '',
|
||||||
|
onClick: () => null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
const { i18n } = useTranslation();
|
const { i18n } = useTranslation();
|
||||||
const locale = i18n.language;
|
const locale = i18n.language;
|
||||||
@ -49,9 +97,11 @@ function HomePage(): JSX.Element {
|
|||||||
const assetsData = useCallback(async () => {
|
const assetsData = useCallback(async () => {
|
||||||
const { asset_categories } = await api.getAssetCategories({ locale });
|
const { asset_categories } = await api.getAssetCategories({ locale });
|
||||||
const categoryId = getCategoryIdByZodiacSign(zodiacSign, asset_categories);
|
const categoryId = getCategoryIdByZodiacSign(zodiacSign, asset_categories);
|
||||||
const { assets } = await api.getAssets({ category: String(categoryId || "1") });
|
const { assets } = await api.getAssets({
|
||||||
|
category: String(categoryId || "1"),
|
||||||
|
});
|
||||||
return assets;
|
return assets;
|
||||||
}, [api]);
|
}, [api, locale, zodiacSign]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: assets,
|
data: assets,
|
||||||
@ -77,7 +127,7 @@ function HomePage(): JSX.Element {
|
|||||||
const dailyForecastData = useCallback(async () => {
|
const dailyForecastData = useCallback(async () => {
|
||||||
const { user_daily_forecast } = await api.getDailyForecasts({ token });
|
const { user_daily_forecast } = await api.getDailyForecasts({ token });
|
||||||
return user_daily_forecast;
|
return user_daily_forecast;
|
||||||
}, [api, token])
|
}, [api, token]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: dailyForecast,
|
data: dailyForecast,
|
||||||
@ -85,14 +135,16 @@ function HomePage(): JSX.Element {
|
|||||||
} = useApiCall<UserDailyForecast>(dailyForecastData);
|
} = useApiCall<UserDailyForecast>(dailyForecastData);
|
||||||
|
|
||||||
const downloadImg = () => {
|
const downloadImg = () => {
|
||||||
if( !asset ) return;
|
if (!asset) return;
|
||||||
download(asset.url, 'image.png');
|
download(asset.url, "image.png");
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
className={`${styles.page} page`}
|
className={`${styles.page} page`}
|
||||||
style={{ backgroundImage: `url(${asset?.url.replace('http://', 'https://')})` }}
|
style={{
|
||||||
|
backgroundImage: `url(${asset?.url.replace("http://", "https://")})`,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className={styles.header}>
|
<div className={styles.header}>
|
||||||
<BlurringSubstrate>
|
<BlurringSubstrate>
|
||||||
@ -128,18 +180,26 @@ function HomePage(): JSX.Element {
|
|||||||
</BlurringSubstrate>
|
</BlurringSubstrate>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles["content__daily-forecast"]}>
|
<div className={styles["content__daily-forecast"]}>
|
||||||
{dailyForecast && dailyForecast.forecasts.map((forecast, index) => (
|
{dailyForecast &&
|
||||||
<div className={styles["content__daily-forecast-item"]} key={index}>
|
dailyForecast.forecasts.map((forecast, index) => (
|
||||||
<Title variant="h3" className={styles["content__daily-forecast-title"]}>
|
<div
|
||||||
{forecast.category}
|
className={styles["content__daily-forecast-item"]}
|
||||||
</Title>
|
key={index}
|
||||||
<p className={styles["content__daily-forecast-body"]}>
|
>
|
||||||
{forecast.body}
|
<Title
|
||||||
</p>
|
variant="h3"
|
||||||
</div>
|
className={styles["content__daily-forecast-title"]}
|
||||||
))}
|
>
|
||||||
|
{forecast.category}
|
||||||
|
</Title>
|
||||||
|
<p className={styles["content__daily-forecast-body"]}>
|
||||||
|
{forecast.body}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{isShowNavbar && <NavbarHome items={navbarHomeItems} />}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -97,6 +97,7 @@
|
|||||||
border-radius: 25px !important;
|
border-radius: 25px !important;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
background-color: #00000094;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
33
src/components/NavbarHome/index.tsx
Normal file
33
src/components/NavbarHome/index.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
import styles from './styles.module.css'
|
||||||
|
|
||||||
|
export interface INavbarHomeItems {
|
||||||
|
title: string
|
||||||
|
path: string
|
||||||
|
image: string
|
||||||
|
active?: boolean
|
||||||
|
onClick?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
interface INavbarHomeProps {
|
||||||
|
items: INavbarHomeItems[]
|
||||||
|
}
|
||||||
|
|
||||||
|
function NavbarHome({items}: INavbarHomeProps): JSX.Element {
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`${styles['container']}`}>
|
||||||
|
{items.map((item, index) => (
|
||||||
|
<div className={`${styles['navbar-item']} ${item.active ? styles['navbar-item--active'] : ''}`} key={index}>
|
||||||
|
<Link to={item.path} onClick={item.onClick}>
|
||||||
|
{/* <img src={item.image} alt={item.title} /> */}
|
||||||
|
<p>{item.title}</p>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NavbarHome
|
||||||
23
src/components/NavbarHome/styles.module.css
Normal file
23
src/components/NavbarHome/styles.module.css
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
.container {
|
||||||
|
width: 100vw;
|
||||||
|
max-width: 560px;
|
||||||
|
background-color: #232322;
|
||||||
|
padding: 12px 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-item {
|
||||||
|
font-size: 12px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
color: #dedede;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-item--active {
|
||||||
|
color: #f24058;
|
||||||
|
}
|
||||||
@ -2,8 +2,8 @@ import { useNavigate } from 'react-router-dom'
|
|||||||
import routes from '@/routes'
|
import routes from '@/routes'
|
||||||
import styles from './styles.module.css'
|
import styles from './styles.module.css'
|
||||||
import UserHeader from '../UserHeader'
|
import UserHeader from '../UserHeader'
|
||||||
import { useSelector } from 'react-redux'
|
import { useDispatch, useSelector } from 'react-redux'
|
||||||
import { selectors } from '@/store'
|
import { actions, selectors } from '@/store'
|
||||||
import Title from '../Title'
|
import Title from '../Title'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import EmailsList from '../EmailsList'
|
import EmailsList from '../EmailsList'
|
||||||
@ -12,10 +12,17 @@ import PriceList from '../PriceList'
|
|||||||
function PriceListPage(): JSX.Element {
|
function PriceListPage(): JSX.Element {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const homeConfig = useSelector(selectors.selectHome);
|
||||||
const selectedPrice = useSelector(selectors.selectSelectedPrice)
|
const selectedPrice = useSelector(selectors.selectSelectedPrice)
|
||||||
|
|
||||||
const email = useSelector(selectors.selectEmail)
|
const email = useSelector(selectors.selectEmail)
|
||||||
const handleNext = () => {
|
const handleNext = () => {
|
||||||
|
dispatch(
|
||||||
|
actions.siteConfig.update({
|
||||||
|
home: { pathFromHome: homeConfig.pathFromHome, isShowNavbar: false },
|
||||||
|
})
|
||||||
|
);
|
||||||
navigate(routes.client.subscription())
|
navigate(routes.client.subscription())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,33 @@
|
|||||||
import Title from "../Title";
|
import Title from "../Title";
|
||||||
import styles from "./styles.module.css";
|
import styles from "./styles.module.css";
|
||||||
import { useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { selectors } from "@/store";
|
import { actions, selectors } from "@/store";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import routes from "@/routes";
|
||||||
|
import { EPathsFromHome } from "@/store/siteConfig";
|
||||||
|
|
||||||
function UserCallbacksPage(): JSX.Element {
|
function UserCallbacksPage(): JSX.Element {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const dispatch = useDispatch();
|
||||||
const statChanges = useSelector(selectors.selectUserCallbacksPrevStat);
|
const statChanges = useSelector(selectors.selectUserCallbacksPrevStat);
|
||||||
const text = useSelector(selectors.selectUserCallbacksDescription);
|
const text = useSelector(selectors.selectUserCallbacksDescription);
|
||||||
|
const homeConfig = useSelector(selectors.selectHome);
|
||||||
|
|
||||||
|
const handleNext = () => {
|
||||||
|
dispatch(actions.siteConfig.update({ home: { pathFromHome: homeConfig.pathFromHome, isShowNavbar: true } }));
|
||||||
|
if (homeConfig.pathFromHome === EPathsFromHome.compatibility) {
|
||||||
|
return navigate(routes.client.home());
|
||||||
|
}
|
||||||
|
if (homeConfig.pathFromHome === EPathsFromHome.breath) {
|
||||||
|
return navigate(routes.client.compatibility());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`${styles.page} page`}>
|
<section className={`${styles.page} page`}>
|
||||||
|
<div className={styles.cross} onClick={handleNext}></div>
|
||||||
<div className={styles["title-container"]}>
|
<div className={styles["title-container"]}>
|
||||||
<Title variant="h3" className={styles.percent}>
|
<Title variant="h3" className={styles.percent}>
|
||||||
<>
|
<>
|
||||||
@ -37,6 +55,9 @@ function UserCallbacksPage(): JSX.Element {
|
|||||||
</div>
|
</div>
|
||||||
<p className={styles["result-container__text"]}>{text}</p>
|
<p className={styles["result-container__text"]}>{text}</p>
|
||||||
</div>
|
</div>
|
||||||
|
<button className={styles.button} onClick={handleNext}>
|
||||||
|
{t("use-all-power")}
|
||||||
|
</button>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
.page {
|
.page {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: calc(100vh - 50px);
|
height: calc(100vh - 50px);
|
||||||
max-height: -webkit-fill-available;
|
/* max-height: -webkit-fill-available; */
|
||||||
flex: auto;
|
flex: auto;
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
color: #bababb;
|
color: #bababb;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
padding-bottom: 114px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.result-container__values {
|
.result-container__values {
|
||||||
@ -35,3 +36,51 @@
|
|||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
margin-top: 32px;
|
margin-top: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
position: fixed;
|
||||||
|
border: none;
|
||||||
|
bottom: 24px;
|
||||||
|
width: calc(100% - 64px);
|
||||||
|
max-width: 496px;
|
||||||
|
border-radius: 32px;
|
||||||
|
padding: 24px 0;
|
||||||
|
background: -moz-linear-gradient(to bottom, #01d400, #196e17);
|
||||||
|
background: -webkit-linear-gradient(to bottom, #01d400, #196e17);
|
||||||
|
background: linear-gradient(to bottom, #01d400, #196e17);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cross {
|
||||||
|
position: absolute;
|
||||||
|
top: 24px;
|
||||||
|
right: 24px;
|
||||||
|
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: 10px;
|
||||||
|
height: 2px;
|
||||||
|
background-color: #bdbdbd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cross::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 2px;
|
||||||
|
height: 10px;
|
||||||
|
background-color: #bdbdbd;
|
||||||
|
}
|
||||||
@ -85,5 +85,9 @@ export default {
|
|||||||
"breathe-subtitle": "Breathing practice will help improve your aura. Breath in the positive energy, breathe out the negative...",
|
"breathe-subtitle": "Breathing practice will help improve your aura. Breath in the positive energy, breathe out the negative...",
|
||||||
"breathe-title": "Stop and breathe to help you relax and focus on what really matters.",
|
"breathe-title": "Stop and breathe to help you relax and focus on what really matters.",
|
||||||
"aura-begin_breathe-button": "BEGIN",
|
"aura-begin_breathe-button": "BEGIN",
|
||||||
|
"aura.breath_relax.text": "Breath & Relax",
|
||||||
|
"use-all-power": "Use all the power of your Aura",
|
||||||
|
"go-through": "Go through practicing recovery",
|
||||||
|
"now-you-know": "Now you know who`s causing your financial energy loss.",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
5
src/services/url/index.ts
Normal file
5
src/services/url/index.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export const getQueryParam = (paramName: string) => {
|
||||||
|
const search = window.location.search;
|
||||||
|
const params = new URLSearchParams(search);
|
||||||
|
return params.get(paramName);
|
||||||
|
};
|
||||||
@ -3,6 +3,7 @@ import token, { actions as tokenActions, selectToken } from './token'
|
|||||||
import user, { actions as userActions, selectUser } from './user'
|
import user, { actions as userActions, selectUser } from './user'
|
||||||
import form, { actions as formActions, selectors as formSelectors } from './form'
|
import form, { actions as formActions, selectors as formSelectors } from './form'
|
||||||
import aura, { actions as auraActions } from './aura'
|
import aura, { actions as auraActions } from './aura'
|
||||||
|
import siteConfig, { selectHome, actions as siteConfigActions } from './siteConfig'
|
||||||
import payment, { actions as paymentActions } from './payment'
|
import payment, { actions as paymentActions } from './payment'
|
||||||
import subscriptionPlans, { actions as subscriptionPlasActions, selectPlanById } from './subscriptionPlan'
|
import subscriptionPlans, { actions as subscriptionPlasActions, selectPlanById } from './subscriptionPlan'
|
||||||
import status, { actions as userStatusActions, selectStatus } from './status'
|
import status, { actions as userStatusActions, selectStatus } from './status'
|
||||||
@ -15,8 +16,9 @@ import { selectRightUser, selectCategoryId } from './compatibility'
|
|||||||
import { selectUserCallbacksDescription, selectUserCallbacksPrevStat } from './userCallbacks'
|
import { selectUserCallbacksDescription, selectUserCallbacksPrevStat } from './userCallbacks'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const preloadedState = loadStore()
|
const preloadedState = loadStore()
|
||||||
export const reducer = combineReducers({ token, user, form, status, subscriptionPlans, aura, payment, compatibility, userCallbacks })
|
export const reducer = combineReducers({ token, user, form, status, subscriptionPlans, aura, payment, compatibility, userCallbacks, siteConfig })
|
||||||
export const actions = {
|
export const actions = {
|
||||||
token: tokenActions,
|
token: tokenActions,
|
||||||
user: userActions,
|
user: userActions,
|
||||||
@ -24,6 +26,7 @@ export const actions = {
|
|||||||
status: userStatusActions,
|
status: userStatusActions,
|
||||||
subscriptionPlan: subscriptionPlasActions,
|
subscriptionPlan: subscriptionPlasActions,
|
||||||
aura: auraActions,
|
aura: auraActions,
|
||||||
|
siteConfig: siteConfigActions,
|
||||||
compatibility: compatibilityActions,
|
compatibility: compatibilityActions,
|
||||||
payment: paymentActions,
|
payment: paymentActions,
|
||||||
userCallbacks: userCallbacksActions,
|
userCallbacks: userCallbacksActions,
|
||||||
@ -40,6 +43,7 @@ export const selectors = {
|
|||||||
selectSelectedPrice,
|
selectSelectedPrice,
|
||||||
selectUserCallbacksDescription,
|
selectUserCallbacksDescription,
|
||||||
selectUserCallbacksPrevStat,
|
selectUserCallbacksPrevStat,
|
||||||
|
selectHome,
|
||||||
...formSelectors,
|
...formSelectors,
|
||||||
}
|
}
|
||||||
export type RootState = ReturnType<typeof reducer>
|
export type RootState = ReturnType<typeof reducer>
|
||||||
|
|||||||
39
src/store/siteConfig.ts
Normal file
39
src/store/siteConfig.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { createSlice, createSelector } from "@reduxjs/toolkit";
|
||||||
|
import type { PayloadAction } from "@reduxjs/toolkit";
|
||||||
|
|
||||||
|
export enum EPathsFromHome {
|
||||||
|
compatibility,
|
||||||
|
breath
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISiteConfig {
|
||||||
|
home: {
|
||||||
|
isShowNavbar: boolean;
|
||||||
|
pathFromHome: EPathsFromHome;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: ISiteConfig = {
|
||||||
|
home: {
|
||||||
|
isShowNavbar: false,
|
||||||
|
pathFromHome: EPathsFromHome.compatibility
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const siteConfigSlice = createSlice({
|
||||||
|
name: "siteConfig",
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
update(state, action: PayloadAction<Partial<ISiteConfig>>) {
|
||||||
|
return { ...state, ...action.payload };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
extraReducers: (builder) => builder.addCase("reset", () => initialState),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const { actions } = siteConfigSlice;
|
||||||
|
export const selectHome = createSelector(
|
||||||
|
(state: { siteConfig: ISiteConfig }) => state.siteConfig.home,
|
||||||
|
(siteConfig) => siteConfig
|
||||||
|
);
|
||||||
|
export default siteConfigSlice.reducer;
|
||||||
Loading…
Reference in New Issue
Block a user