feat: add magic ball page and home button, add besties horoscope slider

This commit is contained in:
gofnnp 2023-11-23 06:05:52 +04:00
parent f90d66f3ba
commit 0f6f8f7e72
13 changed files with 262 additions and 38 deletions

View File

@ -344,7 +344,8 @@ function PrivateOutlet(): JSX.Element {
} }
function PrivateSubscriptionOutlet(): JSX.Element { function PrivateSubscriptionOutlet(): JSX.Element {
const isProduction = import.meta.env.MODE === "production"; // const isProduction = import.meta.env.MODE === "production";
const isProduction = false;
console.log(isProduction); console.log(isProduction);
const status = useSelector(selectors.selectStatus); const status = useSelector(selectors.selectStatus);
return status === "subscribed" || !isProduction ? ( return status === "subscribed" || !isProduction ? (

View File

@ -0,0 +1,66 @@
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 BestiesHoroscopeSliderProps {
data: Horoscope;
}
export interface Horoscope {
name: string;
birthDate: string;
}
function BestiesHoroscopeSlider({
data,
}: BestiesHoroscopeSliderProps): JSX.Element {
const api = useApi();
const { i18n, t } = 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}
style={{
background: `url(${backgroundUrl})`,
}}
onLoad={() => {
console.log("start");
}}
>
<p className={styles.text}>
{t("au.besties.result")}
<b> {data.name}</b>
</p>
</div>
);
}
export default BestiesHoroscopeSlider;

View File

@ -0,0 +1,28 @@
.container {
width: max-content;
max-width: 280px;
height: 160px;
border-radius: 17px;
display: flex;
align-items: flex-end;
justify-content: center;
padding: 8px 12px;
background-repeat: no-repeat !important;
background-size: cover !important;
background-position: center !important;
background-color: #000 !important;
}
.text {
color: #b1b0b0;
font-weight: 400;
font-size: 17px;
line-height: 20px;
text-align: left;
}
.text > b {
color: #fff;
font-weight: 700;
font-size: 18px;
}

View File

@ -90,8 +90,16 @@ function CompatibilityPage(): JSX.Element {
birthDate: selectedDate, birthDate: selectedDate,
}, },
categoryId: compatCategory, categoryId: compatCategory,
selfName,
}) })
); );
dispatch(
actions.compatibilities.update({
name,
birthDate: getDateAsString(selectedDate),
})
);
navigate(routes.client.compatibilityResult()); navigate(routes.client.compatibilityResult());
}; };

View File

@ -21,6 +21,8 @@ import { EPathsFromHome } from "@/store/siteConfig";
import { buildFilename, saveFile } from "../WallpaperPage/utils"; import { buildFilename, saveFile } from "../WallpaperPage/utils";
import Onboarding from "../Onboarding"; import Onboarding from "../Onboarding";
import TextWithFinger from "../TextWithFinger"; import TextWithFinger from "../TextWithFinger";
import Slider from "../Slider";
import BestiesHoroscopeSlider from "../BestiesHoroscopeSlider";
const buttonTextFormatter = (text: string): JSX.Element => { const buttonTextFormatter = (text: string): JSX.Element => {
const sentences = text.split("."); const sentences = text.split(".");
@ -44,6 +46,8 @@ function HomePage(): JSX.Element {
const isShowNavbar = homeConfig.isShowNavbar; const isShowNavbar = homeConfig.isShowNavbar;
const onboardingConfigHome = useSelector(selectors.selectOnboardingHome); const onboardingConfigHome = useSelector(selectors.selectOnboardingHome);
const bestiesHoroscopes = useSelector(selectors.selectCompatibilities);
const [isShowOnboardingHome, setIsShowOnboardingHome] = useState( const [isShowOnboardingHome, setIsShowOnboardingHome] = useState(
!onboardingConfigHome?.isShown !onboardingConfigHome?.isShown
); );
@ -163,41 +167,60 @@ function HomePage(): JSX.Element {
: "calc(100vh - 500px)", : "calc(100vh - 500px)",
}} }}
> >
{ <div
<div ref={buttonsRef}
ref={buttonsRef} className={`${styles["content__buttons"]} ${
className={`${styles["content__buttons"]} ${ isShowNavbar ? styles["content__buttons--hidden"] : ""
isShowNavbar ? styles["content__buttons--hidden"] : "" }`}
}`} >
<Onboarding
targetRef={buttonsRef.current as HTMLDivElement}
isShow={isShowOnboardingHome}
> >
<Onboarding <TextWithFinger
targetRef={buttonsRef.current as HTMLDivElement} text={t("au.web_onbording.start")}
isShow={isShowOnboardingHome} crossClickHandler={() => setIsShowOnboardingHome(false)}
> />
<TextWithFinger </Onboarding>
text={t("au.web_onbording.start")} <BlurringSubstrate
crossClickHandler={() => setIsShowOnboardingHome(false)} style={{ color: "#fa71ea" }}
/> className={styles["content__buttons-item"]}
</Onboarding> clickHandler={handleCompatibility}
<BlurringSubstrate >
style={{ color: "#fa71ea" }} {buttonTextFormatter(t("aura-money_compatibility-button"))}
className={styles["content__buttons-item"]} </BlurringSubstrate>
clickHandler={handleCompatibility} <BlurringSubstrate
> style={{ color: "#00f0ff" }}
{buttonTextFormatter(t("aura-money_compatibility-button"))} className={styles["content__buttons-item"]}
</BlurringSubstrate> clickHandler={handleBreath}
<BlurringSubstrate >
style={{ color: "#00f0ff" }} {buttonTextFormatter(t("aura-10_breath-button"))}
className={styles["content__buttons-item"]} </BlurringSubstrate>
clickHandler={handleBreath} </div>
> <div className={`${styles["content__buttons"]}`}>
{buttonTextFormatter(t("aura-10_breath-button"))} <div
</BlurringSubstrate> className={`${styles["content__aura"]}`}
<div className={`${styles["content__aura"]}`} onClick={handleMagicBall}> onClick={handleMagicBall}
<p className={styles["content__aura-text"]}>{"Get an answer"}</p> >
</div> <p className={styles["content__aura-text"]}>{"Get an answer"}</p>
</div> </div>
} </div>
{/* SLIDERS */}
<div className={styles.sliders}>
<div>
<Title variant="h2" className={styles["sliders__title"]}>
{"Your Besties' Horoscope"}
</Title>
<Slider>
{bestiesHoroscopes.map((item, index) => (
<BestiesHoroscopeSlider data={item} key={index} />
))}
</Slider>
</div>
</div>
{/* END SLIDERS */}
<div className={styles["content__daily-forecast"]}> <div className={styles["content__daily-forecast"]}>
{dailyForecast && {dailyForecast &&
dailyForecast.forecasts.map((forecast, index) => ( dailyForecast.forecasts.map((forecast, index) => (

View File

@ -149,6 +149,7 @@
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center center; background-position: center center;
animation: pulse 1s alternate infinite; animation: pulse 1s alternate infinite;
cursor: pointer;
} }
.content__aura-text { .content__aura-text {
@ -157,6 +158,24 @@
color: #fff; color: #fff;
font-size: 16px; font-size: 16px;
margin: auto; margin: auto;
user-select: none;
}
.sliders {
width: 100vw;
max-width: 560px;
display: flex;
flex-direction: column;
gap: 42px;
}
.sliders__title {
font-weight: 700;
font-size: 23px;
color: #FD433F;
text-align: left;
padding: 0 12px;
margin-bottom: 12px;
} }
@keyframes pulse { @keyframes pulse {

View File

@ -0,0 +1,16 @@
import styles from "./styles.module.css";
interface ISliderProps {
children: JSX.Element[];
className?: string;
}
function Slider({ children, className }: ISliderProps): JSX.Element {
return (
<div className={styles.container}>
<div className={`${styles.slider} ${className || ""}`}>{children}</div>
</div>
);
}
export default Slider;

View File

@ -0,0 +1,17 @@
.slider {
width: fit-content;
height: fit-content;
display: flex;
flex-direction: row;
gap: 16px;
padding: 0 12px;
}
.container {
width: 100%;
overflow-x: scroll;
}
.container::-webkit-scrollbar {
display: none;
}

View File

@ -49,6 +49,12 @@ export function StripePage(): JSX.Element {
return ( return (
<div className={`${styles.page} page`}> <div className={`${styles.page} page`}>
<img
className={`${styles.cross}`}
src="/cross.png"
alt="Cross"
onClick={() => navigate(routes.client.home())}
/>
{isLoading ? ( {isLoading ? (
<div className={styles["payment-loader"]}> <div className={styles["payment-loader"]}>
<Loader /> <Loader />

View File

@ -1,5 +1,6 @@
.page { .page {
position: relative; /* position: relative; */
position: static;
/* height: calc(100vh - 50px); /* height: calc(100vh - 50px);
max-height: -webkit-fill-available; */ max-height: -webkit-fill-available; */
flex: auto; flex: auto;
@ -14,3 +15,13 @@
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.cross {
position: absolute;
top: -36px;
right: 28px;
width: 22px;
height: 22px;
cursor: pointer;
z-index: 9;
}

View File

@ -63,8 +63,6 @@ function MagicBallPage(): JSX.Element {
setIsRunning(false); setIsRunning(false);
return; return;
} }
const canVibrate = !!window.navigator.vibrate;
if (canVibrate) window.navigator.vibrate(100);
setProcessState((prev) => prev + 1); setProcessState((prev) => prev + 1);
}, },
isRunning ? 1000 : null isRunning ? 1000 : null

View File

@ -0,0 +1,23 @@
import { Horoscope } from "@/components/BestiesHoroscopeSlider";
import { createSlice, createSelector } from "@reduxjs/toolkit";
import type { PayloadAction } from "@reduxjs/toolkit";
const initialState: Horoscope[] = []
const compatibilitiesSlice = createSlice({
name: "compatibilities",
initialState,
reducers: {
update(state, action: PayloadAction<Horoscope>) {
return [ ...initialState, ...state, action.payload ];
},
},
extraReducers: (builder) => builder.addCase("reset", () => initialState),
});
export const { actions } = compatibilitiesSlice;
export const selectCompatibilities = createSelector(
(state: { compatibilities: Horoscope[] }) => state.compatibilities,
(compatibilities) => compatibilities
);
export default compatibilitiesSlice.reducer;

View File

@ -33,8 +33,13 @@ import subscriptionPlans, {
} from "./subscriptionPlan"; } from "./subscriptionPlan";
import status, { actions as userStatusActions, selectStatus } from "./status"; import status, { actions as userStatusActions, selectStatus } from "./status";
import compatibility, { import compatibility, {
actions as compatibilityActions, selectSelfName, actions as compatibilityActions,
selectSelfName,
} from "./compatibility"; } from "./compatibility";
import compatibilities, {
actions as compatibilitiesActions,
selectCompatibilities,
} from "./compatibilities";
import userCallbacks, { import userCallbacks, {
actions as userCallbacksActions, actions as userCallbacksActions,
} from "./userCallbacks"; } from "./userCallbacks";
@ -57,6 +62,7 @@ export const actions = {
aura: auraActions, aura: auraActions,
siteConfig: siteConfigActions, siteConfig: siteConfigActions,
compatibility: compatibilityActions, compatibility: compatibilityActions,
compatibilities: compatibilitiesActions,
payment: paymentActions, payment: paymentActions,
userCallbacks: userCallbacksActions, userCallbacks: userCallbacksActions,
onboardingConfig: onboardingConfigActions, onboardingConfig: onboardingConfigActions,
@ -82,6 +88,7 @@ export const selectors = {
selectOnboardingCompatibility, selectOnboardingCompatibility,
selectOnboardingBreath, selectOnboardingBreath,
selectOnboardingNavbarFooter, selectOnboardingNavbarFooter,
selectCompatibilities,
...formSelectors, ...formSelectors,
}; };
@ -94,6 +101,7 @@ export const reducer = combineReducers({
aura, aura,
payment, payment,
compatibility, compatibility,
compatibilities,
userCallbacks, userCallbacks,
siteConfig, siteConfig,
onboardingConfig, onboardingConfig,