feat: add modal with required data
This commit is contained in:
parent
35c2120ca2
commit
e9e35f81d3
@ -1,4 +1,4 @@
|
|||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Routes,
|
Routes,
|
||||||
Route,
|
Route,
|
||||||
@ -16,6 +16,7 @@ import routes, {
|
|||||||
hasNoFooter,
|
hasNoFooter,
|
||||||
hasNoHeader,
|
hasNoHeader,
|
||||||
hasNavbarFooter,
|
hasNavbarFooter,
|
||||||
|
hasFullDataModal,
|
||||||
} from "@/routes";
|
} from "@/routes";
|
||||||
import BirthdayPage from "../BirthdayPage";
|
import BirthdayPage from "../BirthdayPage";
|
||||||
import BirthtimePage from "../BirthtimePage";
|
import BirthtimePage from "../BirthtimePage";
|
||||||
@ -59,6 +60,8 @@ import ThermalResult from "../pages/ThermalResult";
|
|||||||
import MoonPhaseTrackerResult from "../pages/MoonPhaseTrackerResult";
|
import MoonPhaseTrackerResult from "../pages/MoonPhaseTrackerResult";
|
||||||
import EnergyVampirismResult from "../pages/EnergyVampirismResult";
|
import EnergyVampirismResult from "../pages/EnergyVampirismResult";
|
||||||
import NameHoroscopeResult from "../pages/NameHoroscopeResult";
|
import NameHoroscopeResult from "../pages/NameHoroscopeResult";
|
||||||
|
import Modal from "../Modal";
|
||||||
|
import FullDataModal from "../FullDataModal";
|
||||||
|
|
||||||
function App(): JSX.Element {
|
function App(): JSX.Element {
|
||||||
const [isSpecialOfferOpen, setIsSpecialOfferOpen] = useState<boolean>(false);
|
const [isSpecialOfferOpen, setIsSpecialOfferOpen] = useState<boolean>(false);
|
||||||
@ -282,11 +285,27 @@ function Layout({ setIsSpecialOfferOpen }: LayoutProps): JSX.Element {
|
|||||||
const showNavbar = hasNavigation(location.pathname);
|
const showNavbar = hasNavigation(location.pathname);
|
||||||
const showFooter = hasNoFooter(location.pathname);
|
const showFooter = hasNoFooter(location.pathname);
|
||||||
const showHeader = hasNoHeader(location.pathname);
|
const showHeader = hasNoHeader(location.pathname);
|
||||||
|
const isRouteFullDataModal = hasFullDataModal(location.pathname);
|
||||||
const [isMenuOpen, setIsMenuOpen] = useState<boolean>(false);
|
const [isMenuOpen, setIsMenuOpen] = useState<boolean>(false);
|
||||||
const changeIsSpecialOfferOpen = () => setIsSpecialOfferOpen(true);
|
const changeIsSpecialOfferOpen = () => setIsSpecialOfferOpen(true);
|
||||||
const homeConfig = useSelector(selectors.selectHome);
|
const homeConfig = useSelector(selectors.selectHome);
|
||||||
const showNavbarFooter = homeConfig.isShowNavbar;
|
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 = () => {
|
const handleCompatibility = () => {
|
||||||
dispatch(
|
dispatch(
|
||||||
actions.siteConfig.update({
|
actions.siteConfig.update({
|
||||||
@ -353,6 +372,11 @@ function Layout({ setIsSpecialOfferOpen }: LayoutProps): JSX.Element {
|
|||||||
clickCross={changeIsSpecialOfferOpen}
|
clickCross={changeIsSpecialOfferOpen}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
{isRouteFullDataModal && (
|
||||||
|
<Modal open={isShowFullDataModal} isCloseButtonVisible={false}>
|
||||||
|
<FullDataModal onClose={onCloseFullDataModal} />
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
<main className="content">
|
<main className="content">
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</main>
|
</main>
|
||||||
@ -397,6 +421,19 @@ function PrivateSubscriptionOutlet(): JSX.Element {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
function SkipStep(): JSX.Element {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
return user ? (
|
return user ? (
|
||||||
|
|||||||
42
src/components/FullDataModal/index.tsx
Normal file
42
src/components/FullDataModal/index.tsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { useSelector } from "react-redux";
|
||||||
|
import { DatePicker } from "../DateTimePicker";
|
||||||
|
import Title from "../Title";
|
||||||
|
import styles from "./styles.module.css";
|
||||||
|
import { selectors } from "@/store";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import MainButton from "../MainButton";
|
||||||
|
|
||||||
|
interface IFullDataModalProps {
|
||||||
|
onClose: (birthDate: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function FullDataModal({ onClose }: IFullDataModalProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const birthDateFromStore = useSelector(selectors.selectBirthdate);
|
||||||
|
const [birthDate, setBirthDate] = useState(birthDateFromStore);
|
||||||
|
const [isDisabled, setIsDisabled] = useState(true);
|
||||||
|
|
||||||
|
const handleValid = (_birthDate: string) => {
|
||||||
|
setBirthDate(_birthDate);
|
||||||
|
setIsDisabled(_birthDate === "");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<Title variant="h2">{t("date_of_birth")}</Title>
|
||||||
|
<DatePicker
|
||||||
|
name="birthDate"
|
||||||
|
value={birthDate}
|
||||||
|
onValid={handleValid}
|
||||||
|
onInvalid={() => setIsDisabled(true)}
|
||||||
|
inputClassName="date-picker-input"
|
||||||
|
/>
|
||||||
|
<MainButton disabled={isDisabled} onClick={() => onClose(birthDate)}>
|
||||||
|
Save
|
||||||
|
</MainButton>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FullDataModal;
|
||||||
0
src/components/FullDataModal/styles.module.css
Normal file
0
src/components/FullDataModal/styles.module.css
Normal file
@ -148,7 +148,7 @@ function HomePage(): JSX.Element {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getMoonsImages();
|
getMoonsImages();
|
||||||
}, []);
|
}, [api]);
|
||||||
|
|
||||||
const getMoonsImages = async () => {
|
const getMoonsImages = async () => {
|
||||||
const assets = (
|
const assets = (
|
||||||
@ -288,6 +288,7 @@ function HomePage(): JSX.Element {
|
|||||||
|
|
||||||
{/* SLIDERS */}
|
{/* SLIDERS */}
|
||||||
<div className={styles.sliders}>
|
<div className={styles.sliders}>
|
||||||
|
{!!compatibilities.length && (
|
||||||
<div className={styles["slider"]}>
|
<div className={styles["slider"]}>
|
||||||
<Title variant="h2" className={styles["sliders__title"]}>
|
<Title variant="h2" className={styles["sliders__title"]}>
|
||||||
{"Your Besties' Horoscope"}
|
{"Your Besties' Horoscope"}
|
||||||
@ -304,6 +305,7 @@ function HomePage(): JSX.Element {
|
|||||||
))}
|
))}
|
||||||
</Slider>
|
</Slider>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
<div className={styles["slider"]}>
|
<div className={styles["slider"]}>
|
||||||
<Title variant="h2" className={styles["sliders__title"]}>
|
<Title variant="h2" className={styles["sliders__title"]}>
|
||||||
{"Prediction Based on Your Moons"}
|
{"Prediction Based on Your Moons"}
|
||||||
@ -357,6 +359,7 @@ function HomePage(): JSX.Element {
|
|||||||
|
|
||||||
{/* SLIDERS */}
|
{/* SLIDERS */}
|
||||||
<div className={styles.sliders}>
|
<div className={styles.sliders}>
|
||||||
|
{!!compatibilities.length && (
|
||||||
<div className={styles["slider"]}>
|
<div className={styles["slider"]}>
|
||||||
<Title variant="h2" className={styles["sliders__title"]}>
|
<Title variant="h2" className={styles["sliders__title"]}>
|
||||||
{t("au.thermal_compatibility.result_title")}
|
{t("au.thermal_compatibility.result_title")}
|
||||||
@ -373,6 +376,7 @@ function HomePage(): JSX.Element {
|
|||||||
))}
|
))}
|
||||||
</Slider>
|
</Slider>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{/* END SLIDERS */}
|
{/* END SLIDERS */}
|
||||||
|
|
||||||
|
|||||||
@ -1,26 +1,34 @@
|
|||||||
import { ReactNode } from 'react'
|
import { ReactNode } from "react";
|
||||||
import './styles.css'
|
import styles from "./styles.module.css";
|
||||||
|
|
||||||
interface ModalProps {
|
interface ModalProps {
|
||||||
children: ReactNode
|
children: ReactNode;
|
||||||
open?: boolean
|
open?: boolean;
|
||||||
onClose?: () => void
|
isCloseButtonVisible?: boolean;
|
||||||
|
onClose?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Modal({ open, children, onClose }: ModalProps): JSX.Element {
|
function Modal({
|
||||||
|
open,
|
||||||
|
children,
|
||||||
|
isCloseButtonVisible = true,
|
||||||
|
onClose,
|
||||||
|
}: ModalProps): JSX.Element {
|
||||||
const handleClose = (event: React.MouseEvent) => {
|
const handleClose = (event: React.MouseEvent) => {
|
||||||
if (event.target !== event.currentTarget) return
|
if (event.target !== event.currentTarget) return;
|
||||||
onClose?.()
|
onClose?.();
|
||||||
}
|
};
|
||||||
if (!open) return <></>
|
if (!open) return <></>;
|
||||||
return (
|
return (
|
||||||
<div className='modal' onClick={handleClose}>
|
<div className={styles.modal} onClick={handleClose}>
|
||||||
<div className='modal-content'>
|
<div className={styles["modal-content"]}>
|
||||||
<button className='modal-close-btn' onClick={handleClose} />
|
{isCloseButtonVisible && (
|
||||||
|
<button className={styles["modal-close-btn"]} onClick={handleClose} />
|
||||||
|
)}
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Modal
|
export default Modal;
|
||||||
|
|||||||
@ -27,6 +27,10 @@
|
|||||||
transform: translate(-50%,-50%);
|
transform: translate(-50%,-50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-content::-webkit-scrollbar {
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.modal-close-btn {
|
.modal-close-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import styles from "./styles.module.css";
|
import styles from "./styles.module.css";
|
||||||
import {
|
import {
|
||||||
getCategoryIdByZodiacSign,
|
getCategoryIdByZodiacSign,
|
||||||
@ -28,7 +28,7 @@ function NameHoroscopeSlider({
|
|||||||
const { i18n } = useTranslation();
|
const { i18n } = useTranslation();
|
||||||
const locale = i18n.language;
|
const locale = i18n.language;
|
||||||
const birthDate = useSelector(selectors.selectBirthdate);
|
const birthDate = useSelector(selectors.selectBirthdate);
|
||||||
const zodiacSign = getZodiacSignByDate(birthDate);
|
const zodiacSign = useMemo(() => getZodiacSignByDate(birthDate), [birthDate]);
|
||||||
const [backgroundUrl, setBackgroundUrl] = useState("");
|
const [backgroundUrl, setBackgroundUrl] = useState("");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -48,7 +48,7 @@ function NameHoroscopeSlider({
|
|||||||
console.error("Error: ", error);
|
console.error("Error: ", error);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}, []);
|
}, [api, locale, zodiacSign]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -42,7 +42,7 @@ function ThermalSlider({ data, onClick }: ThermalProps): JSX.Element {
|
|||||||
console.error("Error: ", error);
|
console.error("Error: ", error);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}, []);
|
}, [api, locale, zodiacSign]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useAuth } from "@/auth";
|
|
||||||
import { useApi, Assets } from "@/api";
|
import { useApi, Assets } from "@/api";
|
||||||
import { saveFile, buildFilename } from "../WallpaperPage/utils";
|
import { saveFile, buildFilename } from "../WallpaperPage/utils";
|
||||||
import styles from "./styles.module.css";
|
import styles from "./styles.module.css";
|
||||||
@ -18,13 +17,8 @@ function WallpapersZodiacSign(): JSX.Element {
|
|||||||
const locale = i18n.language;
|
const locale = i18n.language;
|
||||||
const [asset, setAsset] = useState<Assets.Asset>();
|
const [asset, setAsset] = useState<Assets.Asset>();
|
||||||
|
|
||||||
const {
|
|
||||||
user,
|
|
||||||
// token
|
|
||||||
} = useAuth();
|
|
||||||
const birthdate = useSelector(selectors.selectBirthdate);
|
const birthdate = useSelector(selectors.selectBirthdate);
|
||||||
const zodiacSign = getZodiacSignByDate(birthdate);
|
const zodiacSign = useMemo(() => getZodiacSignByDate(birthdate), [birthdate]);
|
||||||
const category = user?.profile.sign?.sign || "";
|
|
||||||
|
|
||||||
const getZodiacWallpaper = async () => {
|
const getZodiacWallpaper = async () => {
|
||||||
const { asset_categories } = await api.getAssetCategories({ locale });
|
const { asset_categories } = await api.getAssetCategories({ locale });
|
||||||
@ -38,11 +32,14 @@ function WallpapersZodiacSign(): JSX.Element {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getZodiacWallpaper();
|
getZodiacWallpaper();
|
||||||
}, []);
|
}, [api, locale, zodiacSign]);
|
||||||
|
|
||||||
const saveImage = () =>
|
const saveImage = () =>
|
||||||
asset &&
|
asset &&
|
||||||
saveFile(asset.url.replace("http://", "https://"), buildFilename(category));
|
saveFile(
|
||||||
|
asset.url.replace("http://", "https://"),
|
||||||
|
buildFilename(zodiacSign)
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -198,6 +198,11 @@ export const hasNoHeader = (path: string) => {
|
|||||||
return !withoutHeaderRoutes.includes(`/${path.split("/")[1]}`);
|
return !withoutHeaderRoutes.includes(`/${path.split("/")[1]}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const withFullDataModalRoutes = [routes.client.home()];
|
||||||
|
export const hasFullDataModal = (path: string) => {
|
||||||
|
return withFullDataModalRoutes.includes(`/${path.split("/")[1]}`);
|
||||||
|
};
|
||||||
|
|
||||||
export const getRouteBy = (status: UserStatus): string => {
|
export const getRouteBy = (status: UserStatus): string => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case "lead":
|
case "lead":
|
||||||
|
|||||||
@ -28,7 +28,7 @@ export const getCategoryIdByZodiacSign = (
|
|||||||
categories: AssetCategory[]
|
categories: AssetCategory[]
|
||||||
) => {
|
) => {
|
||||||
const categoryId = categories.find(
|
const categoryId = categories.find(
|
||||||
(category) => category.slug === zodiacSign.toLowerCase()
|
(category) => category.slug === zodiacSign?.toLowerCase()
|
||||||
)?.id;
|
)?.id;
|
||||||
return categoryId;
|
return categoryId;
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user