Epe short path

This commit is contained in:
Денис Катаев 2024-04-12 22:52:44 +00:00 committed by Daniil Chemerkin
parent 79966d3b4e
commit e9afdd802d
8 changed files with 316 additions and 127 deletions

View File

@ -120,6 +120,7 @@ import { useSchemeColorByElement } from "@/hooks/useSchemeColorByElement";
import GetInformationPartnerPage from "../pages/GetInformationPartner";
import BirthPlacePage from "../pages/BirthPlacePage";
import LoadingPage from "../pages/LoadingPage";
import { EProductKeys, productUrls } from "@/data/products";
const isProduction = import.meta.env.MODE === "production";
@ -137,6 +138,24 @@ function App(): JSX.Element {
const { token, user, signUp, logout } = useAuth();
const [searchParams] = useSearchParams();
const jwtToken = searchParams.get("token");
const isForce = searchParams.get("force");
if (isForce === "true") {
dispatch(actions.userConfig.addIsForceShortPath(true));
}
if (isForce === "false") {
dispatch(actions.userConfig.addIsForceShortPath(false));
}
const isForceShortPath = useSelector(selectors.selectIsForceShortPath);
const { gender: genderFromStore } = useSelector(
selectors.selectQuestionnaire
);
const birthdateFromStore = useSelector(selectors.selectBirthdate);
const { birthPlace: birthPlaceFromStore } = useSelector(
selectors.selectQuestionnaire
);
const gender = user?.profile?.gender || genderFromStore;
const birthdate = user?.profile?.birthday || birthdateFromStore;
const birthPlace = user?.profile?.birthplace || birthPlaceFromStore;
useEffect(() => {
// api.getAppConfig({ bundleId: "auraweb" }),
@ -239,26 +258,6 @@ function App(): JSX.Element {
}
}, [dispatch]);
// useEffect(() => {
// const motion = window.matchMedia("(prefers-reduced-motion: no-preference)");
// if (motion.matches) {
// const scheme = document.querySelector('meta[name="theme-color"]');
// console.log(document.querySelectorAll("section.page")[0]);
// let hue = 0;
// let color;
// const backgroundColor =
// window.getComputedStyle(document.querySelectorAll("section.page")[0])
// .backgroundColor || "#ffffff";
// scheme?.setAttribute("content", backgroundColor);
// setInterval(() => {
// color = `hsl(${(hue += 5)} 50% 30%)`;
// document.body.style.background = color;
// scheme?.setAttribute("content", color);
// }, 50);
// }
// }, []);
return (
<Routes>
<Route element={<Layout setIsSpecialOfferOpen={setIsSpecialOfferOpen} />}>
@ -266,28 +265,73 @@ function App(): JSX.Element {
{/* Email - Pay - Email */}
<Route
element={
<CheckIsAuthOutlet
redirectUrl={routes.client.singlePaymentShortPath(
"moons.pdf.aura"
)}
pageType={EIsAuthPageType.public}
<ShortPathOutlet
productKey={EProductKeys["moons.pdf.aura"]}
redirectUrls={{
user: {
force: routes.client.epeBirthdate(),
},
purchasedProduct: {
no: routes.client.singlePaymentShortPath("moons.pdf.aura"),
},
}}
requiredParameters={[]}
/>
}
>
<Route
path={routes.client.epeGender()}
element={<GenderPage productKey={EProductKeys["moons.pdf.aura"]} />}
/>
</Route>
<Route
element={
<ShortPathOutlet
productKey={EProductKeys["moons.pdf.aura"]}
redirectUrls={{
data: {
no: routes.client.epeGender(),
},
purchasedProduct: {
no: routes.client.singlePaymentShortPath("moons.pdf.aura"),
},
}}
requiredParameters={[isForceShortPath || gender]}
/>
}
>
<Route path={routes.client.epeGender()} element={<GenderPage />} />
<Route
path={routes.client.epeBirthdate()}
element={<BirthdayPage />}
/>
</Route>
{/* <Route
path={routes.client.epePayment()}
element={<PaymentWithEmailPage />}
/> */}
<Route
path={routes.client.epeSuccessPayment()}
element={<SuccessPaymentPage />}
/>
element={
<ShortPathOutlet
productKey={EProductKeys["moons.pdf.aura"]}
redirectUrls={{
user: {
no: routes.client.epeGender(),
force: routes.client.epeBirthdate(),
},
data: {
no: routes.client.epeGender(),
force: routes.client.epeBirthdate(),
},
purchasedProduct: {
no: routes.client.singlePaymentShortPath("moons.pdf.aura"),
},
}}
requiredParameters={[isForceShortPath || gender, birthdate]}
isProductPage={true}
/>
}
>
<Route
path={routes.client.epeSuccessPayment()}
element={<SuccessPaymentPage />}
/>
</Route>
<Route
path={routes.client.epeFailPayment()}
element={<FailPaymentPage />}
@ -297,40 +341,89 @@ function App(): JSX.Element {
{/* Advisor short path */}
<Route
element={
<CheckPurchasedSingleProductOutlet
productKey="chat.aura"
isProductPage={false}
failedUrl={routes.client.advisorChatPrivate(
"asst_WWkAlT4Ovs6gKRy6VEn9LqNS"
)}
<ShortPathOutlet
productKey={EProductKeys["chat.aura"]}
redirectUrls={{
user: {
force: routes.client.advisorChatBirthdate(),
},
purchasedProduct: {
no: routes.client.singlePaymentShortPath("chat.aura"),
},
}}
requiredParameters={[]}
/>
}
>
<Route
element={
<CheckIsAuthOutlet
redirectUrl={routes.client.singlePaymentShortPath("chat.aura")}
pageType={EIsAuthPageType.public}
/>
}
>
<Route
path={routes.client.advisorChatGender()}
element={<GenderPage />}
path={routes.client.advisorChatGender()}
element={<GenderPage productKey={EProductKeys["chat.aura"]} />}
/>
</Route>
<Route
element={
<ShortPathOutlet
productKey={EProductKeys["chat.aura"]}
redirectUrls={{
data: {
no: routes.client.advisorChatGender(),
},
purchasedProduct: {
no: routes.client.singlePaymentShortPath("chat.aura"),
},
}}
requiredParameters={[isForceShortPath || gender]}
/>
<Route
path={routes.client.advisorChatBirthdate()}
element={<BirthdayPage />}
}
>
<Route
path={routes.client.advisorChatBirthdate()}
element={<BirthdayPage />}
/>
</Route>
<Route
element={
<ShortPathOutlet
productKey={EProductKeys["chat.aura"]}
redirectUrls={{
data: {
no: routes.client.advisorChatGender(),
force: routes.client.advisorChatBirthdate(),
},
purchasedProduct: {
no: routes.client.singlePaymentShortPath("chat.aura"),
},
}}
requiredParameters={[birthdate, isForceShortPath || gender]}
/>
<Route
path={routes.client.advisorChatBirthtime()}
element={<BirthtimePage />}
}
>
<Route
path={routes.client.advisorChatBirthtime()}
element={<BirthtimePage />}
/>
</Route>
<Route
element={
<ShortPathOutlet
productKey={EProductKeys["chat.aura"]}
redirectUrls={{
data: {
no: routes.client.advisorChatGender(),
force: routes.client.advisorChatBirthdate(),
},
purchasedProduct: {
no: routes.client.singlePaymentShortPath("chat.aura"),
},
}}
requiredParameters={[birthdate, isForceShortPath || gender]}
/>
<Route
path={routes.client.advisorChatBirthPlace()}
element={<BirthPlacePage />}
/>
</Route>
}
>
<Route
path={routes.client.advisorChatBirthPlace()}
element={<BirthPlacePage />}
/>
</Route>
<Route
path={routes.client.advisorChatSuccessPayment()}
@ -340,13 +433,29 @@ function App(): JSX.Element {
path={routes.client.advisorChatFailPayment()}
element={<FailPaymentPage />}
/>
<Route
element={
<CheckPurchasedSingleProductOutlet
<ShortPathOutlet
productKey={EProductKeys["chat.aura"]}
redirectUrls={{
user: {
no: routes.client.advisorChatGender(),
force: routes.client.advisorChatBirthdate(),
},
data: {
no: routes.client.advisorChatGender(),
force: routes.client.advisorChatBirthdate(),
},
purchasedProduct: {
no: routes.client.singlePaymentShortPath("chat.aura"),
},
}}
requiredParameters={[
birthdate,
birthPlace,
isForceShortPath || gender,
]}
isProductPage={true}
failedUrl={routes.client.advisorChatGender()}
productKey="chat.aura"
/>
}
>
@ -358,10 +467,29 @@ function App(): JSX.Element {
{/* Single Payment Page Short Path */}
<Route
path={routes.client.singlePaymentShortPath()}
element={<PaymentWithEmailPage />}
element={
<ShortPathOutlet
productKey={EProductKeys["chat.aura"]}
redirectUrls={{
data: {
no: routes.client.advisorChatGender(),
force: routes.client.advisorChatBirthdate(),
},
}}
requiredParameters={[
birthdate,
birthPlace,
isForceShortPath || gender,
]}
/>
}
>
<Route path=":productId" element={<PaymentWithEmailPage />} />
<Route
path={routes.client.singlePaymentShortPath()}
element={<PaymentWithEmailPage />}
>
<Route path=":productId" element={<PaymentWithEmailPage />} />
</Route>
</Route>
{/* Single Payment Page Short Path */}
@ -668,18 +796,9 @@ function Layout({ setIsSpecialOfferOpen }: LayoutProps): JSX.Element {
const homeConfig = useSelector(selectors.selectHome);
const showNavbarFooter = homeConfig.isShowNavbar;
const mainRef = useRef<HTMLDivElement>(null);
// console.log(
// mainRef.current?.querySelectorAll("section.page, .page, section")
// );
useSchemeColorByElement(mainRef.current, "section.page, .page, section", [
location,
]);
// useEffect(() => {
// console.log(
// "###$",
// mainRef.current?.querySelectorAll("section.page, .page, section")[0]
// );
// }, [location]);
const birthdate = useSelector(selectors.selectBirthdate);
const dataItems = useMemo(() => [birthdate], [birthdate]);
@ -788,43 +907,63 @@ function Layout({ setIsSpecialOfferOpen }: LayoutProps): JSX.Element {
);
}
enum EIsAuthPageType {
private,
public,
// enum EIsAuthPageType {
// private,
// public,
// }
// interface ICheckIsAuthOutletProps {
// redirectUrl: string;
// pageType: EIsAuthPageType;
// }
// function CheckIsAuthOutlet({
// redirectUrl,
// pageType,
// }: ICheckIsAuthOutletProps): JSX.Element {
// const { user } = useAuth();
// if (user && pageType === EIsAuthPageType.public) {
// return <Navigate to={redirectUrl} replace={true} />;
// }
// if (!user && pageType === EIsAuthPageType.private) {
// return <Navigate to={redirectUrl} replace={true} />;
// }
// return <Outlet />;
// }
interface IShortPathOutletProps {
productKey: EProductKeys;
requiredParameters: unknown[];
isProductPage?: boolean;
redirectUrls: {
user?: {
yes?: string;
no?: string;
force?: string;
};
data?: {
yes?: string;
no?: string;
force?: string;
};
purchasedProduct?: {
yes?: string;
no?: string;
force?: string;
};
force?: {
yes?: string;
no?: string;
force?: string;
};
};
}
interface ICheckIsAuthOutletProps {
redirectUrl: string;
pageType: EIsAuthPageType;
}
function CheckIsAuthOutlet({
redirectUrl,
pageType,
}: ICheckIsAuthOutletProps): JSX.Element {
const { user } = useAuth();
if (user && pageType === EIsAuthPageType.public) {
return <Navigate to={redirectUrl} replace={true} />;
}
if (!user && pageType === EIsAuthPageType.private) {
return <Navigate to={redirectUrl} replace={true} />;
}
return <Outlet />;
}
interface ICheckPurchasedSingleProductOutletProps {
productKey: string;
isProductPage: boolean;
failedUrl: string;
}
function CheckPurchasedSingleProductOutlet({
productKey,
isProductPage,
failedUrl,
}: ICheckPurchasedSingleProductOutletProps): JSX.Element {
function ShortPathOutlet(props: IShortPathOutletProps): JSX.Element {
const { productKey, requiredParameters, redirectUrls, isProductPage } = props;
const { user, token } = useAuth();
const api = useApi();
const isForce = useSelector(selectors.selectIsForceShortPath);
const loadData = useCallback(async () => {
if (!token?.length || !user?.email || !productKey?.length)
@ -851,22 +990,48 @@ function CheckPurchasedSingleProductOutlet({
const { data, isPending } = useApiCall(loadData);
if (!data || isPending) {
if (isPending) {
return <LoadingPage />;
}
if (
isProductPage &&
(!("active" in data) || !data.active || !token.length || !user?.email)
) {
return <Navigate to={failedUrl} replace={true} />;
}
const isPurchasedProduct = !!(data && "active" in data && data.active);
if (!isProductPage && data && "active" in data && data.active) {
return <Navigate to={failedUrl} replace={true} />;
}
const isUser = !!user && !!token.length;
const isFullData = requiredParameters.every((item) => !!item);
return <Outlet />;
if (!isFullData) {
if (isForce && redirectUrls.data?.force) {
return <Navigate to={redirectUrls.data.force} replace={true} />;
}
if (redirectUrls.data?.no && !isForce) {
return <Navigate to={redirectUrls.data.no} replace={true} />;
}
return <Outlet />;
}
if (!isUser) {
if (isForce && redirectUrls.user?.force) {
return <Navigate to={redirectUrls.user.force} replace={true} />;
}
if (redirectUrls.user?.no && !isForce) {
return <Navigate to={redirectUrls.user.no} replace={true} />;
}
return <Outlet />;
}
if (!isPurchasedProduct) {
if (isForce && redirectUrls.purchasedProduct?.force) {
return (
<Navigate to={redirectUrls.purchasedProduct.force} replace={true} />
);
}
if (redirectUrls.purchasedProduct?.no && !isForce) {
return <Navigate to={redirectUrls.purchasedProduct.no} replace={true} />;
}
return <Outlet />;
}
if (isProductPage) {
return <Outlet />;
}
return <Navigate to={productUrls[productKey]} replace={true} />;
}
function AuthorizedUserOutlet(): JSX.Element {

View File

@ -111,7 +111,7 @@ function AdvisorChatPage() {
const setExternalChatIdAssistant = async (threadId: string) => {
await api.setExternalChatIdAssistant({
token,
chatId: String(id),
chatId: String(assistant?.id || 1),
ai_assistant_chat: {
external_id: threadId,
},

View File

@ -1,17 +1,21 @@
import styles from "./styles.module.css";
import Title from "@/components/Title";
import { Gender, genders } from "@/data";
import { EProductKeys } from "@/data/products";
import routes from "@/routes";
import { actions } from "@/store";
import { useEffect } from "react";
import { useDispatch } from "react-redux";
import { useNavigate, useParams } from "react-router-dom";
function GenderPage(): JSX.Element {
interface IGenderPageProps {
productKey?: EProductKeys;
}
function GenderPage({ productKey }: IGenderPageProps): JSX.Element {
const dispatch = useDispatch();
const navigate = useNavigate();
const { targetId } = useParams();
const pathName = window.location.pathname;
useEffect(() => {
const isShowTryApp = targetId === "i";
@ -20,10 +24,10 @@ function GenderPage(): JSX.Element {
const selectGender = (gender: Gender) => {
dispatch(actions.questionnaire.update({ gender: gender.id }));
if (pathName.includes("/epe/gender")) {
if (productKey === EProductKeys["moons.pdf.aura"]) {
return navigate(routes.client.epeBirthdate());
}
if (pathName.includes("/advisor-chat/gender")) {
if (productKey === EProductKeys["chat.aura"]) {
return navigate(routes.client.advisorChatBirthdate());
}
navigate(`/questionnaire/profile/flowChoice`);

View File

@ -147,6 +147,7 @@ function PaymentWithEmailPage() {
if (!tokenFromStore.length || !userFromStore) {
return;
}
await createSinglePayment({
user: userFromStore,
token: tokenFromStore,
@ -163,7 +164,8 @@ function PaymentWithEmailPage() {
useEffect(() => {
handleAuthUser();
}, [handleAuthUser]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<div className={`${styles.page} page`}>

View File

@ -1,5 +1,11 @@
import routes from "@/routes";
export enum EProductKeys {
"chat.aura" = "chat.aura",
"moons.pdf.aura" = "moons.pdf.aura",
"default" = "default",
}
interface IProductUrls {
[key: string]: string;
}

View File

@ -74,8 +74,8 @@ export const useSinglePayment = () => {
}
return false;
} catch (error) {
return false;
console.error(error);
return false;
}
},
[api]

View File

@ -46,6 +46,7 @@ import userConfig, {
actions as userConfigActions,
selectUserDeviceType,
selectIsShowTryApp,
selectIsForceShortPath,
} from "./userConfig";
import compatibilities, {
actions as compatibilitiesActions,
@ -106,6 +107,7 @@ export const selectors = {
selectQuestionnaire,
selectUserDeviceType,
selectIsShowTryApp,
selectIsForceShortPath,
selectOpenAiToken,
...formSelectors,
};

View File

@ -9,11 +9,13 @@ export enum EUserDeviceType {
interface IUserConfig {
deviceType: EUserDeviceType;
isShowTryApp: boolean;
isForceShortPath: boolean;
}
const initialState: IUserConfig = {
deviceType: EUserDeviceType.ios,
isShowTryApp: false,
isForceShortPath: false,
};
const userConfigSlice = createSlice({
@ -31,6 +33,10 @@ const userConfigSlice = createSlice({
state.isShowTryApp = action.payload;
return state;
},
addIsForceShortPath(state, action: PayloadAction<boolean>) {
state.isForceShortPath = action.payload;
return state;
},
},
extraReducers: (builder) => builder.addCase("reset", () => initialState),
});
@ -44,4 +50,8 @@ export const selectIsShowTryApp = createSelector(
(state: { userConfig: IUserConfig }) => state.userConfig.isShowTryApp,
(userConfig) => userConfig
);
export const selectIsForceShortPath = createSelector(
(state: { userConfig: IUserConfig }) => state.userConfig.isForceShortPath,
(userConfig) => userConfig
);
export default userConfigSlice.reducer;