w-aura/src/components/App/index.tsx
Денис Катаев 37833a888f Questionnaire
2023-12-31 00:33:55 +00:00

482 lines
15 KiB
TypeScript

import { useCallback, useEffect, useMemo, useState } from "react";
import {
Routes,
Route,
Navigate,
Outlet,
useLocation,
useNavigate,
} from "react-router-dom";
import { useAuth } from "@/auth";
import { useDispatch, useSelector } from "react-redux";
import { actions, selectors } from "@/store";
import routes, {
hasNavigation,
getRouteBy,
hasNoFooter,
hasNoHeader,
hasNavbarFooter,
hasFullDataModal,
} from "@/routes";
import BirthdayPage from "../BirthdayPage";
import BirthtimePage from "../BirthtimePage";
import CreateProfilePage from "../CreateProfilePage";
import EmailEnterPage from "../EmailEnterPage";
import SubscriptionPage from "../SubscriptionPage";
import PaymentPage from "../PaymentPage";
import WallpaperPage from "../WallpaperPage";
import StaticPage from "../StaticPage";
import NotFoundPage from "../NotFoundPage";
import Header from "../Header";
import Navbar from "../Navbar";
import Footer from "../Footer";
import "./styles.css";
import DidYouKnowPage from "../DidYouKnowPage";
import FreePeriodInfoPage from "../FreePeriodInfoPage";
import AttentionPage from "../AttentionPage";
import FeedbackPage from "../FeedbackPage";
import CompatibilityPage from "../Compatibility";
import BreathPage from "../BreathPage";
import PriceListPage from "../PriceListPage";
import CompatResultPage from "../CompatResultPage";
import HomePage from "../HomePage";
import UserCallbacksPage from "../UserCallbacksPage";
import NavbarFooter, { INavbarHomeItems } from "../NavbarFooter";
import { EPathsFromHome } from "@/store/siteConfig";
import parseAPNG, { APNG } from "apng-js";
import { useApi, useApiCall } from "@/api";
import { Asset } from "@/api/resources/Assets";
import PaymentResultPage from "../PaymentPage/results";
import PaymentSuccessPage from "../PaymentPage/results/SuccessPage";
import PaymentFailPage from "../PaymentPage/results/ErrorPage";
import { StripePage } from "../StripePage";
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";
import GenderPage from "../pages/Gender";
import QuestionnairePage from "../pages/Questionnaire";
import GoalSetupPage from "../pages/GoalSetup";
import HyperPersonalizedAstrologyPage from "../pages/HyperPersonalizedAstrologyPage";
import NoBirthtimePage from "../pages/NoBirthtime";
import LoadingInRelationshipPage from "../pages/LoadingInRelationship";
import WorksForUsPage from "../pages/WorksForUs";
import RelationshipAlmostTherePage from "../pages/RelationshipAlmostThere";
import Modal from "../Modal";
import FullDataModal from "../FullDataModal";
function App(): JSX.Element {
const [isSpecialOfferOpen, setIsSpecialOfferOpen] = useState<boolean>(false);
const [leoApng, setLeoApng] = useState<Error | APNG>(Error);
const [padLockApng, setPadLockApng] = useState<Error | APNG>(Error);
const navigate = useNavigate();
const api = useApi();
const dispatch = useDispatch();
const { token, user } = useAuth();
const closeSpecialOfferAttention = () => {
setIsSpecialOfferOpen(false);
navigate(routes.client.auth());
};
const assetsData = useCallback(async () => {
const { assets } = await api.getAssets({
category: String("au"),
});
return assets;
}, [api]);
const { data } = useApiCall<Asset[]>(assetsData);
useEffect(() => {
(async () => {
if (!token.length || !user) return;
const {
user: { has_subscription },
} = await api.getSubscriptionStatus({
token,
});
if (has_subscription && user) {
return dispatch(actions.status.update("subscribed"));
}
if (!has_subscription && user) {
return dispatch(actions.status.update("unsubscribed"));
}
if (!user) {
return dispatch(actions.status.update("lead"));
}
})();
}, [dispatch, api, token, user]);
useEffect(() => {
async function getApng() {
if (!data) return;
const response = await fetch(
data.find((item) => item.key === "au.apng.leo")?.url || ""
);
const arrayBuffer = await response.arrayBuffer();
setLeoApng(parseAPNG(arrayBuffer));
}
getApng();
}, [data]);
useEffect(() => {
(async () => {
const response = await fetch("/padlock_icon_animation_closing.png");
const arrayBuffer = await response.arrayBuffer();
setPadLockApng(parseAPNG(arrayBuffer));
})();
}, []);
useEffect(() => {
if (!user) return;
dispatch(actions.form.addEmail(user.email));
}, []);
return (
<Routes>
<Route element={<Layout setIsSpecialOfferOpen={setIsSpecialOfferOpen} />}>
{/* Test Routes Start */}
<Route path={routes.client.notFound()} element={<NotFoundPage />} />
<Route path={routes.client.gender()} element={<GenderPage />} />
<Route
path={routes.client.questionnaire()}
element={<QuestionnairePage />}
>
<Route path=":stepId" element={<QuestionnairePage />}>
<Route path=":question" element={<QuestionnairePage />} />
</Route>
</Route>
<Route path={routes.client.goalSetup()} element={<GoalSetupPage />} />
<Route
path={routes.client.hyperPersonalizedAstrology()}
element={<HyperPersonalizedAstrologyPage />}
/>
<Route path={routes.client.noTime()} element={<NoBirthtimePage />} />
<Route
path={routes.client.loadingInRelationship()}
element={<LoadingInRelationshipPage />}
/>
<Route path={routes.client.worksForUs()} element={<WorksForUsPage />} />
<Route
path={routes.client.relationshipAlmostThere()}
element={<RelationshipAlmostTherePage />}
/>
{/* Test Routes End */}
<Route
path={routes.client.paymentResult()}
element={<PaymentResultPage />}
/>
<Route
path={routes.client.paymentSuccess()}
element={<PaymentSuccessPage />}
/>
<Route
path={routes.client.paymentFail()}
element={<PaymentFailPage />}
/>
<Route element={<AuthorizedUserOutlet />}>
<Route path={routes.client.root()} element={<MainPage />} />
<Route path={routes.client.birthday()} element={<BirthdayPage />} />
<Route
path={routes.client.didYouKnow()}
element={<DidYouKnowPage />}
/>
<Route
path={routes.client.freePeriodInfo()}
element={<FreePeriodInfoPage />}
/>
<Route
path={routes.client.attention()}
element={
<AttentionPage
isOpenModal={isSpecialOfferOpen}
onCloseSpecialOffer={closeSpecialOfferAttention}
/>
}
/>
<Route path={routes.client.feedback()} element={<FeedbackPage />} />
<Route path={routes.client.birthtime()} element={<BirthtimePage />} />
<Route path={routes.client.createProfile()} element={<SkipStep />} />
<Route
path={routes.client.emailEnter()}
element={<EmailEnterPage />}
/>
<Route
path={routes.client.auth()}
element={<AuthPage padLockApng={padLockApng} />}
/>
<Route
path={routes.client.authResult()}
element={<AuthResultPage />}
/>
<Route path={routes.client.static()} element={<StaticPage />} />
<Route path={routes.client.priceList()} element={<PriceListPage />} />
{/* <Route
path={routes.client.wallpaper()}
element={<ProtectWallpaperPage />}
/> */}
</Route>
<Route element={<AuthorizedUserOutlet />}>
<Route
path={routes.client.subscription()}
element={<SubscriptionPage />}
>
<Route path=":subPlan" element={<SubscriptionPage />} />
</Route>
</Route>
{/* <Route element={<PrivateOutlet />}> */}
<Route element={<AuthorizedUserOutlet />}>
{/* <Route
path={routes.client.subscription()}
element={<SubscriptionPage />}
/> */}
<Route
path={routes.client.paymentMethod()}
element={<PaymentPage />}
/>
<Route
path={routes.client.paymentStripe()}
element={<StripePage />}
/>
</Route>
{/* <Route element={<PrivateSubscriptionOutlet />}> */}
<Route path={routes.client.home()} element={<HomePage />} />
<Route
path={routes.client.compatibility()}
element={<CompatibilityPage />}
/>
<Route
path={routes.client.compatibilityResult()}
element={<CompatResultPage />}
/>
<Route
path={routes.client.breath()}
element={<BreathPage leoApng={leoApng} />}
/>
<Route
path={routes.client.breathResult()}
element={<UserCallbacksPage />}
/>
<Route path={routes.client.wallpaper()} element={<WallpaperPage />} />
<Route path={routes.client.magicBall()} element={<MagicBallPage />} />
<Route
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 />} />
</Route>
</Routes>
);
}
interface LayoutProps {
setIsSpecialOfferOpen: React.Dispatch<React.SetStateAction<boolean>>;
}
function Layout({ setIsSpecialOfferOpen }: LayoutProps): JSX.Element {
const location = useLocation();
const navigate = useNavigate();
const dispatch = useDispatch();
const showNavbar = hasNavigation(location.pathname);
const showFooter = hasNoFooter(location.pathname);
const showHeader = hasNoHeader(location.pathname);
const isRouteFullDataModal = hasFullDataModal(location.pathname);
const [isMenuOpen, setIsMenuOpen] = useState<boolean>(false);
const changeIsSpecialOfferOpen = () => setIsSpecialOfferOpen(true);
const homeConfig = useSelector(selectors.selectHome);
const showNavbarFooter = homeConfig.isShowNavbar;
const birthdate = useSelector(selectors.selectBirthdate);
const dataItems = useMemo(() => [birthdate], [birthdate]);
const [isShowFullDataModal, setIsShowFullDataModal] =
useState<boolean>(false);
useEffect(() => {
setIsShowFullDataModal(getIsShowFullDataModal(dataItems));
}, [dataItems]);
const onCloseFullDataModal = (_birthDate: string) => {
console.log("onCloseFullDataModal", _birthDate);
dispatch(actions.form.addDate(_birthDate));
setIsShowFullDataModal(getIsShowFullDataModal(dataItems));
};
const handleCompatibility = () => {
dispatch(
actions.siteConfig.update({
home: {
pathFromHome: EPathsFromHome.navbar,
isShowNavbar: showNavbarFooter,
},
})
);
navigate(routes.client.compatibility());
};
const handleBreath = () => {
dispatch(
actions.siteConfig.update({
home: {
pathFromHome: EPathsFromHome.navbar,
isShowNavbar: showNavbarFooter,
},
})
);
navigate(routes.client.breath());
};
const navbarItems: INavbarHomeItems[] = [
{
title: "Breathing",
path: routes.client.breath(),
paths: [routes.client.breath(), routes.client.breathResult()],
image: "Breath.svg",
onClick: handleBreath,
},
{
title: "Aura",
path: routes.client.home(),
paths: [routes.client.home()],
image: "Aura.svg",
active: true,
onClick: () => null,
},
{
title: "Compatibility",
path: routes.client.compatibility(),
paths: [
routes.client.compatibility(),
routes.client.compatibilityResult(),
],
image: "Compatibility.svg",
onClick: handleCompatibility,
},
{
title: "My Moon",
path: routes.client.wallpaper(),
paths: [routes.client.wallpaper()],
image: "moon.svg",
onClick: () => null,
},
];
return (
<div className="container">
{showHeader ? (
<Header
openMenu={() => setIsMenuOpen(true)}
clickCross={changeIsSpecialOfferOpen}
/>
) : null}
{isRouteFullDataModal && (
<Modal open={isShowFullDataModal} isCloseButtonVisible={false}>
<FullDataModal onClose={onCloseFullDataModal} />
</Modal>
)}
<main className="content">
<Outlet />
</main>
{showFooter ? <Footer color={showNavbar ? "black" : "white"} /> : null}
{showNavbar ? (
<Navbar isOpen={isMenuOpen} closeMenu={() => setIsMenuOpen(false)} />
) : null}
{showNavbarFooter && hasNavbarFooter(location.pathname) ? (
<NavbarFooter items={navbarItems} />
) : null}
</div>
);
}
function AuthorizedUserOutlet(): JSX.Element {
const status = useSelector(selectors.selectStatus);
const { user } = useAuth();
return user && status === "subscribed" ? (
<Navigate to={routes.client.home()} replace={true} />
) : (
<Outlet />
);
}
// function PrivateOutlet(): JSX.Element {
// const { user } = useAuth();
// return user ? (
// <Outlet />
// ) : (
// <Navigate to={routes.client.root()} replace={true} />
// );
// }
// function PrivateSubscriptionOutlet(): JSX.Element {
// // const isProduction = import.meta.env.MODE === "production";
// const isProduction = false;
// const status = useSelector(selectors.selectStatus);
// return status === "subscribed" || !isProduction ? (
// <Outlet />
// ) : (
// <Navigate to={getRouteBy(status)} replace={true} />
// );
// }
function getIsShowFullDataModal(dataItems: Array<unknown> = []): boolean {
let hasNoDataItem = false;
for (const item of dataItems) {
if (!item) {
hasNoDataItem = true;
break;
}
}
return hasNoDataItem;
}
function SkipStep(): JSX.Element {
const { user } = useAuth();
return user ? (
<Navigate to={routes.client.emailEnter()} replace={true} />
) : (
<CreateProfilePage />
);
}
function MainPage(): JSX.Element {
const status = useSelector(selectors.selectStatus);
return <Navigate to={getRouteBy(status)} replace={true} />;
}
export default App;