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 {
const isProduction = import.meta.env.MODE === "production";
// const isProduction = import.meta.env.MODE === "production";
const isProduction = false;
console.log(isProduction);
const status = useSelector(selectors.selectStatus);
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,
},
categoryId: compatCategory,
selfName,
})
);
dispatch(
actions.compatibilities.update({
name,
birthDate: getDateAsString(selectedDate),
})
);
navigate(routes.client.compatibilityResult());
};

View File

@ -21,6 +21,8 @@ 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 from "../BestiesHoroscopeSlider";
const buttonTextFormatter = (text: string): JSX.Element => {
const sentences = text.split(".");
@ -44,6 +46,8 @@ function HomePage(): JSX.Element {
const isShowNavbar = homeConfig.isShowNavbar;
const onboardingConfigHome = useSelector(selectors.selectOnboardingHome);
const bestiesHoroscopes = useSelector(selectors.selectCompatibilities);
const [isShowOnboardingHome, setIsShowOnboardingHome] = useState(
!onboardingConfigHome?.isShown
);
@ -163,41 +167,60 @@ function HomePage(): JSX.Element {
: "calc(100vh - 500px)",
}}
>
{
<div
ref={buttonsRef}
className={`${styles["content__buttons"]} ${
isShowNavbar ? styles["content__buttons--hidden"] : ""
}`}
<div
ref={buttonsRef}
className={`${styles["content__buttons"]} ${
isShowNavbar ? styles["content__buttons--hidden"] : ""
}`}
>
<Onboarding
targetRef={buttonsRef.current as HTMLDivElement}
isShow={isShowOnboardingHome}
>
<Onboarding
targetRef={buttonsRef.current as HTMLDivElement}
isShow={isShowOnboardingHome}
>
<TextWithFinger
text={t("au.web_onbording.start")}
crossClickHandler={() => setIsShowOnboardingHome(false)}
/>
</Onboarding>
<BlurringSubstrate
style={{ color: "#fa71ea" }}
className={styles["content__buttons-item"]}
clickHandler={handleCompatibility}
>
{buttonTextFormatter(t("aura-money_compatibility-button"))}
</BlurringSubstrate>
<BlurringSubstrate
style={{ color: "#00f0ff" }}
className={styles["content__buttons-item"]}
clickHandler={handleBreath}
>
{buttonTextFormatter(t("aura-10_breath-button"))}
</BlurringSubstrate>
<div className={`${styles["content__aura"]}`} onClick={handleMagicBall}>
<p className={styles["content__aura-text"]}>{"Get an answer"}</p>
</div>
<TextWithFinger
text={t("au.web_onbording.start")}
crossClickHandler={() => setIsShowOnboardingHome(false)}
/>
</Onboarding>
<BlurringSubstrate
style={{ color: "#fa71ea" }}
className={styles["content__buttons-item"]}
clickHandler={handleCompatibility}
>
{buttonTextFormatter(t("aura-money_compatibility-button"))}
</BlurringSubstrate>
<BlurringSubstrate
style={{ color: "#00f0ff" }}
className={styles["content__buttons-item"]}
clickHandler={handleBreath}
>
{buttonTextFormatter(t("aura-10_breath-button"))}
</BlurringSubstrate>
</div>
<div className={`${styles["content__buttons"]}`}>
<div
className={`${styles["content__aura"]}`}
onClick={handleMagicBall}
>
<p className={styles["content__aura-text"]}>{"Get an answer"}</p>
</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"]}>
{dailyForecast &&
dailyForecast.forecasts.map((forecast, index) => (

View File

@ -149,6 +149,7 @@
background-repeat: no-repeat;
background-position: center center;
animation: pulse 1s alternate infinite;
cursor: pointer;
}
.content__aura-text {
@ -157,6 +158,24 @@
color: #fff;
font-size: 16px;
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 {

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 (
<div className={`${styles.page} page`}>
<img
className={`${styles.cross}`}
src="/cross.png"
alt="Cross"
onClick={() => navigate(routes.client.home())}
/>
{isLoading ? (
<div className={styles["payment-loader"]}>
<Loader />

View File

@ -1,5 +1,6 @@
.page {
position: relative;
/* position: relative; */
position: static;
/* height: calc(100vh - 50px);
max-height: -webkit-fill-available; */
flex: auto;
@ -14,3 +15,13 @@
justify-content: 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);
return;
}
const canVibrate = !!window.navigator.vibrate;
if (canVibrate) window.navigator.vibrate(100);
setProcessState((prev) => prev + 1);
},
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";
import status, { actions as userStatusActions, selectStatus } from "./status";
import compatibility, {
actions as compatibilityActions, selectSelfName,
actions as compatibilityActions,
selectSelfName,
} from "./compatibility";
import compatibilities, {
actions as compatibilitiesActions,
selectCompatibilities,
} from "./compatibilities";
import userCallbacks, {
actions as userCallbacksActions,
} from "./userCallbacks";
@ -57,6 +62,7 @@ export const actions = {
aura: auraActions,
siteConfig: siteConfigActions,
compatibility: compatibilityActions,
compatibilities: compatibilitiesActions,
payment: paymentActions,
userCallbacks: userCallbacksActions,
onboardingConfig: onboardingConfigActions,
@ -82,6 +88,7 @@ export const selectors = {
selectOnboardingCompatibility,
selectOnboardingBreath,
selectOnboardingNavbarFooter,
selectCompatibilities,
...formSelectors,
};
@ -94,6 +101,7 @@ export const reducer = combineReducers({
aura,
payment,
compatibility,
compatibilities,
userCallbacks,
siteConfig,
onboardingConfig,