fix: paths from home page, reviews, profile create, attention page

This commit is contained in:
gofnnp 2023-09-21 00:23:14 +04:00
parent 7fec68157f
commit 22d6c9e1fe
20 changed files with 700 additions and 149 deletions

View File

@ -3,8 +3,9 @@ import { useTranslation } from 'react-i18next'
import Title from '../Title'
import routes from '@/routes'
import styles from './styles.module.css'
import CheckboxWithText from '../CheckboxWithText'
// import CheckboxWithText from '../CheckboxWithText'
import SpecialWelcomeOffer from '../SpecialWelcomeOffer'
import MainButton from '../MainButton'
interface AttentionPageProps {
isOpenModal: boolean
@ -16,20 +17,21 @@ function AttentionPage({ isOpenModal, onCloseSpecialOffer }: AttentionPageProps)
const navigate = useNavigate()
const handleNext = () => navigate(routes.client.feedback())
const onChangeCheckbox = (e: React.FormEvent<HTMLInputElement>) => {
if (e.currentTarget.checked) {
handleNext()
}
}
// const onChangeCheckbox = (e: React.FormEvent<HTMLInputElement>) => {
// if (e.currentTarget.checked) {
// handleNext()
// }
// }
return (
<section className={`${styles.page} page`}>
<SpecialWelcomeOffer open={isOpenModal} onClose={onCloseSpecialOffer} />
<img className={styles.icon} src="/stop-icon.png" alt="stop" />
<Title variant='h2'>{t('attention')}</Title>
<p className={styles.text}>{t('attention_page_text')}</p>
<Title variant='h2'>{t('aura.attention.title')}</Title>
<p className={styles.text}>{t('aura.warming_up.body')}</p>
<div className={styles['checkbox-container']}>
<CheckboxWithText text={t('not_ready_for_information')} onChange={onChangeCheckbox} />
{/* <CheckboxWithText text={t('not_ready_for_information')} onChange={onChangeCheckbox} /> */}
<MainButton className={styles.button} onClick={handleNext}>{t('aura.warming_up.button')}</MainButton>
</div>
</section>
)

View File

@ -1,23 +1,27 @@
.page {
position: relative;
flex: auto;
height: calc(100vh - 50px);
max-height: -webkit-fill-available;
justify-content: center;
gap: 16px;
position: relative;
flex: auto;
height: calc(100vh - 50px);
max-height: -webkit-fill-available;
justify-content: center;
gap: 16px;
}
.icon {
width: 96px;
width: 96px;
}
.text {
text-align: center;
line-height: 1.2;
font-weight: 700;
text-align: center;
line-height: 1.2;
font-weight: 700;
}
.checkbox-container {
width: 80%;
margin: 64px auto 0;
width: 80%;
margin: 64px auto 0;
}
.button {
white-space: pre;
}

View File

@ -37,8 +37,6 @@ function BreathPage(): JSX.Element {
if (isOpenModal) return;
const previewTimeOut = setTimeout(() => {
setIsShowPreview(false);
console.log(apngPlayer);
apngPlayer?.play()
}, 10_000);
@ -54,26 +52,17 @@ function BreathPage(): JSX.Element {
useEffect(() => {
async function test() {
console.log(data);
if (!data) return;
console.log(1);
const response = await fetch(
data.find((item) => item.key === "au.apng.leo")?.url || ""
);
console.log(2);
const arrayBuffer = await response.arrayBuffer();
console.log(3);
const apng = parseAPNG(arrayBuffer);
console.log(4);
const context = leoCanvasRef.current?.getContext("2d");
console.log("context: ", context);
if (context && !(apng instanceof Error)) {
context.canvas.height = apng.height;
context.canvas.width = apng.width;
const _apngPlayer = await apng.getPlayer(context);
console.log(5);
setApngPlayer(_apngPlayer);
if (apngPlayer) {
apngPlayer.stop();

View File

@ -5,6 +5,7 @@
justify-content: center;
align-items: center;
background-color: #01010b;
padding-bottom: 60px;
flex: auto;
}

View File

@ -75,7 +75,9 @@ function CompatResultPage(): JSX.Element {
return (
<section className={`${styles.page} page`}>
{text !== "Loading..." && <div className={styles.cross} onClick={handleNext}></div>}
{text !== "Loading..." && (
<div className={styles.cross} onClick={handleNext}></div>
)}
<div className={styles["title-container"]}>
<Title variant="h2">{t("you_and", { user: rightUser.name })}</Title>
</div>
@ -85,19 +87,26 @@ function CompatResultPage(): JSX.Element {
</Title>
<p className={styles["result-container__text"]}>{text}</p>
</div>
{text !== "Loading..." && (
<div className={styles["button-container"]}>
<p className={styles["button-container__text"]}>
{t("now-you-know")}
</p>
<button
className={styles["button-container__button"]}
onClick={handleNext}
>
{t("go-through")}
{text !== "Loading..." &&
homeConfig.pathFromHome === EPathsFromHome.compatibility && (
<div className={styles["button-container"]}>
<p className={styles["button-container__text"]}>
{t("now-you-know")}
</p>
<button
className={styles["button-container__button"]}
onClick={handleNext}
>
{t("go-through")}
</button>
</div>
)}
{text !== "Loading..." &&
homeConfig.pathFromHome === EPathsFromHome.breath && (
<button className={styles['button-green']} onClick={handleNext}>
{t("use-all-power")}
</button>
</div>
)}
)}
</section>
);
}

View File

@ -67,6 +67,21 @@
color: #fff;
}
.button-green {
position: fixed;
font-weight: 500;
border: none;
bottom: 24px;
width: calc(100% - 64px);
max-width: 496px;
border-radius: 32px;
padding: 24px 0;
background: -moz-linear-gradient(to bottom, #01d400, #196e17);
background: -webkit-linear-gradient(to bottom, #01d400, #196e17);
background: linear-gradient(to bottom, #01d400, #196e17);
color: #fff;
}
.cross {
position: absolute;
top: 24px;

View File

@ -0,0 +1,118 @@
/* DatePicker.css */
/* Container for the entire date picker */
.date-picker-container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
margin: 0 auto;
color: white;
/* background: transparent; */
/* box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); */
}
.date-picker-viewport {
flex: 1;
position: relative;
height: 160px; /* Adjust the max height as needed */
overflow: hidden;
padding: 0;
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
.date-picker-viewport::-webkit-scrollbar {
display: none; /* Chrome, Safari and Opera */
}
.date-picker-viewport:first-child .date-picker-wheel {
border-bottom-left-radius: 10px;
border-top-left-radius: 10px;
}
.date-picker-viewport:last-child .date-picker-wheel {
border-bottom-right-radius: 10px;
border-top-right-radius: 10px;
}
.date-picker-viewport::after {
content: "";
position: absolute;
z-index: 2;
top: 0;
right: 0;
bottom: 0;
left: 0;
pointer-events: none;
/* background: linear-gradient(
#f7f7f7,
rgba(245, 245, 245, 0) 52%,
rgba(245, 245, 245, 0) 48%,
#f7f7f7
); */
}
.date-picker-wheel {
position: absolute;
height: 40px;
top: 50%;
background: #7a7979;
margin-top: -20px;
width: 100%;
display: block;
}
/* Scrollable components for day, month, and year */
.date-picker-scroll {
padding: 0;
touch-action: none;
}
/* Individual items in the scrollable components */
.date-picker-item {
padding: 10px 0;
cursor: pointer;
transition: background-color 0.2s;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
color: #a09b9b;
}
.date-picker-item.selected {
color: white;
}
/* Header and confirm button */
.date-picker-header {
display: flex;
justify-content: flex-end;
margin-top: 10px;
}
.date-picker-confirm {
background-color: #007aff;
color: #ffffff;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.2s;
}
.date-picker-confirm:hover {
background-color: #0056b3;
}
/* Display selected date */
.date-picker-selected-date {
margin-top: 10px;
text-align: center;
font-size: 16px;
color: #007aff; /* Change the color to your desired style */
white-space: nowrap; /* Prevent selected date from wrapping */
text-overflow: ellipsis; /* Show ellipsis for long selected date */
width: 100%; /* Ensure the width is 100% for centering */
position: absolute; /* Position it absolutely for centering */
left: 50%; /* Center horizontally */
transform: translateX(-50%); /* Center horizontally */
}

View File

@ -0,0 +1,82 @@
import React, { useEffect, useState } from "react";
import "./DatePicker.css";
import DatePickerItem from "./DatePickerItem";
import { IDate, getDateAsString } from "@/services/date";
interface DatePickerProps {
onDateChange: (selectedDate: string | IDate) => void;
}
const DatePicker: React.FC<DatePickerProps> = ({ onDateChange }) => {
const currentDate = new Date();
const [selectedDate, setSelectedDate] = useState<string | IDate>(getDateAsString(currentDate));
const days = Array.from({ length: 31 }, (_, index) => (index + 1).toString());
const months = Array.from({ length: 12 }, (_, index) =>
new Date(0, index).toLocaleDateString(undefined, { month: "long" })
);
const years = Array.from({ length: 81 }, (_, index) =>
(currentDate.getFullYear() - 80 + index).toString()
);
const handleDaySelect = (day: string) => {
const newDate = new Date(getDateAsString(selectedDate));
newDate.setDate(parseInt(day));
setSelectedDate(getDateAsString(newDate));
};
const handleMonthSelect = (month: string) => {
const newDate = new Date(getDateAsString(selectedDate));
newDate.setMonth(months.indexOf(month));
setSelectedDate(getDateAsString(newDate));
};
const handleYearSelect = (year: string) => {
const newDate = new Date(getDateAsString(selectedDate));
newDate.setFullYear(parseInt(year));
setSelectedDate(getDateAsString(newDate));
};
useEffect(() => {
if (onDateChange) {
onDateChange(selectedDate); // Call the callback when selectedDate changes
}
}, [selectedDate, onDateChange]);
return (
<>
<div className="date-picker-container">
<DatePickerItem
data={days}
selectedValue={new Date(getDateAsString(selectedDate)).getDate().toString()}
onSelect={handleDaySelect}
unit="day"
/>
<DatePickerItem
data={months}
selectedValue={new Date(
0,
new Date(getDateAsString(selectedDate)).getMonth()
).toLocaleDateString(undefined, { month: "long" })}
onSelect={handleMonthSelect}
unit="month"
/>
<DatePickerItem
data={years}
selectedValue={new Date(getDateAsString(selectedDate)).getFullYear().toString()}
onSelect={handleYearSelect}
unit="year"
/>
</div>
<div className="date-picker-selected-date">
{/* {selectedDate.toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
})} */}
</div>
</>
);
};
export default DatePicker;

View File

@ -0,0 +1,148 @@
import React, { useEffect, useRef, useState } from "react";
const ITEM_HEIGHT = 40; // Height of each date item
interface DatePickerItemProps {
data: string[];
selectedValue: string;
onSelect: (value: string) => void;
unit: string;
}
function useIsMobile() {
const [isMobile, setIsMobile] = useState<boolean>(false);
useEffect(() => {
setIsMobile(window.matchMedia("(max-width: 600px)").matches);
}, []);
return isMobile;
}
const DatePickerItem: React.FC<DatePickerItemProps> = ({
data,
selectedValue,
onSelect,
unit,
}) => {
const isMobile = useIsMobile();
const scrollRef = useRef<HTMLDivElement | null>(null);
const [touchY, setTouchY] = useState<number>(0);
const [translateY, setTranslateY] = useState<number>(
data.indexOf(selectedValue) * -ITEM_HEIGHT
);
const handleTouchStart = (event: React.TouchEvent<HTMLDivElement>) => {
setTouchY(event.touches[0].clientY);
};
const handleTouchMove = (event: React.TouchEvent<HTMLDivElement>) => {
if (isMobile && touchY !== null) {
const deltaY = event.touches[0].clientY - touchY;
wheelScroll(deltaY);
setTouchY(event.touches[0].clientY);
}
};
const handleTouchEnd = () => {
if (isMobile && scrollRef.current) {
const selectedIndex = Math.round(-translateY / ITEM_HEIGHT);
onSelect(data[selectedIndex]);
// Limit the translateY to ensure it aligns with a valid item
setTranslateY(-selectedIndex * ITEM_HEIGHT);
setTouchY(0);
}
};
const wheelScroll = (deltaY: number) => {
const newTranslateY = translateY + deltaY;
// Calculate the maximum and minimum translateY values based on the data length
const minTranslateY = -ITEM_HEIGHT * (data.length - 1);
const maxTranslateY = 0;
// Ensure the newTranslateY stays within the valid range
if (newTranslateY < minTranslateY) {
setTranslateY(minTranslateY);
} else if (newTranslateY > maxTranslateY) {
setTranslateY(maxTranslateY);
} else {
setTranslateY(newTranslateY);
}
};
// const handleMouseDown = (event: React.MouseEvent<HTMLDivElement>) => {
// if (!isMobile) {
// setTouchY(event.clientY);
// document.addEventListener("mousemove", handleMouseMove);
// document.addEventListener("mouseup", handleMouseUp);
// }
// };
// const handleMouseMove = (event: MouseEvent) => {
// const deltaY = event.clientY - touchY;
// handleScroll(deltaY);
// setTouchY(event.clientY);
// };
// const handleMouseUp = () => {
// resetMouseState();
// };
// const resetTouchState = () => {
// if (isMobile && scrollRef.current) {
// const selectedIndex = Math.round(-translateY / ITEM_HEIGHT);
// onSelect(data[selectedIndex]);
// // Limit the translateY to ensure it aligns with a valid item
// setTranslateY(-selectedIndex * ITEM_HEIGHT);
// setTouchY(0);
// }
// };
// const resetMouseState = () => {
// document.removeEventListener("mousemove", handleMouseMove);
// document.removeEventListener("mouseup", handleMouseUp);
// resetTouchState();
// };
// useEffect(() => {
// // Clean up mouse event listeners when the component unmounts
// return () => {
// resetMouseState();
// };
// }, []);
return (
<div className="date-picker-viewport">
<div className="date-picker-wheel">
<div
className="date-picker-scroll"
onTouchStart={handleTouchStart}
onTouchMove={handleTouchMove}
onTouchEnd={handleTouchEnd}
// onMouseDown={handleMouseDown}
ref={scrollRef}
style={{
transform: `translateY(${translateY}px)`,
}}
>
{data.map((item, index) => (
<div
className={`date-picker-item ${
item === selectedValue ? "selected" : ""
}`}
key={`${unit}-${index}`}
>
{item}
</div>
))}
</div>
</div>
</div>
);
};
export default DatePickerItem;

View File

@ -4,8 +4,8 @@ import Title from "../Title";
import styles from "./styles.module.css";
import { useCallback, useState } from "react";
import NameInput from "./nameInput";
import { DatePicker } from "../DateTimePicker";
import { IDate, getDateAsString } from "@/services/date";
import DatePicker from "./DatePicker";
import { IDate } from "@/services/date";
import { AICompatCategories, useApi, useApiCall } from "@/api";
import { useNavigate } from "react-router-dom";
import routes from "@/routes";
@ -14,57 +14,61 @@ import { actions } from "@/store";
function CompatibilityPage(): JSX.Element {
const { t, i18n } = useTranslation();
const navigate = useNavigate()
const dispatch = useDispatch()
const navigate = useNavigate();
const dispatch = useDispatch();
const [isDisabled, setIsDisabled] = useState(true);
const [isDisabledName, setIsDisabledName] = useState(true);
const [isDisabledDate, setIsDisabledDate] = useState(true);
const [name, setName] = useState<string>('');
const [date, setDate] = useState<string | IDate>('');
const [name, setName] = useState<string>("");
const [selectedDate, setSelectedDate] = useState<string | IDate>("");
const [compatCategory, setCompatCategory] = useState(1);
const handleNext = () => {
dispatch(actions.compatibility.update({
rightUser: {
name,
birthDate: date
},
categoryId: compatCategory
}))
navigate(routes.client.compatibilityResult())
if (isDisabled) return;
dispatch(
actions.compatibility.update({
rightUser: {
name,
birthDate: selectedDate,
},
categoryId: compatCategory,
})
);
navigate(routes.client.compatibilityResult());
};
const api = useApi()
const locale = i18n.language
const api = useApi();
const locale = i18n.language;
const loadData = useCallback(() => {
return api.getAiCompatCategories({ locale })
.then((resp: AICompatCategories.Response) => resp.compat_categories)
}, [api, locale])
const { data } = useApiCall<AICompatCategories.CompatCategory[]>(loadData)
return api
.getAiCompatCategories({ locale })
.then((resp: AICompatCategories.Response) => resp.compat_categories);
}, [api, locale]);
const { data } = useApiCall<AICompatCategories.CompatCategory[]>(loadData);
const handleValidName = (name: string) => {
setIsDisabledName(!name.length);
setName(name)
checkAllDisabled()
}
setName(name);
checkAllDisabled();
};
const handleValidDate = (date: IDate | string) => {
const handleValidDate = (date: string | IDate) => {
setIsDisabledDate(date === '');
setDate(date)
checkAllDisabled()
}
setSelectedDate(date);
checkAllDisabled();
};
const checkAllDisabled = () => {
setIsDisabled(isDisabledName || isDisabledDate);
}
};
const changeCompatCategory = (event: React.ChangeEvent<HTMLInputElement>) => {
setCompatCategory(parseInt(event.target.value))
}
setCompatCategory(parseInt(event.target.value));
};
return (
<section className={`${styles.page} page`}>
<div className={styles.cross} onClick={handleNext}></div>
<Title variant="h1" className={styles.title}>
{t("compatibility")}
</Title>
@ -75,47 +79,47 @@ function CompatibilityPage(): JSX.Element {
<Title variant="h3" className={styles.plus}>
+
</Title>
<div className={styles['inputs-container']}>
<div className={styles['input-container__name-container']}>
<div className={styles["inputs-container"]}>
<div className={styles["input-container__name-container"]}>
<NameInput
name="name"
value={name}
placeholder={t('name')}
placeholder={t("name")}
onValid={handleValidName}
onInvalid={() => setIsDisabledName(true)}
/>
</div>
<div className={styles['input-container__date-container']}>
<DatePicker
name='birthdate'
value={getDateAsString(date)}
inputClassName={styles['date-input']}
onValid={handleValidDate}
onInvalid={() => setIsDisabledDate(true)}
/>
<div className={styles["input-container__date-container"]}>
<DatePicker onDateChange={handleValidDate} />
</div>
</div>
{data && data.length && (
<div className={styles['compatibility-categories']}>
{
data.map((item, index) => (
<div className="compatibility-categories__item" key={index}>
<input className={`${styles["compatibility-categories__input"]} ${compatCategory === item.id ? styles["compatibility-categories__input--checked"] : ''}`}
type="radio"
name="compatCategory"
id={String(item.id)}
value={item.id}
checked={compatCategory === item.id}
onChange={changeCompatCategory} />
<label htmlFor={String(item.id)}>
{item.name}
</label>
</div>
))
}
<div className={styles["compatibility-categories"]}>
{data.map((item, index) => (
<div className="compatibility-categories__item" key={index}>
<input
className={`${styles["compatibility-categories__input"]} ${
compatCategory === item.id
? styles["compatibility-categories__input--checked"]
: ""
}`}
type="radio"
name="compatCategory"
id={String(item.id)}
value={item.id}
checked={compatCategory === item.id}
onChange={changeCompatCategory}
/>
<label htmlFor={String(item.id)}>{item.name}</label>
</div>
))}
</div>
)}
<MainButton className={styles['check-btn']} onClick={handleNext} disabled={isDisabled}>
<MainButton
className={styles["check-btn"]}
onClick={handleNext}
disabled={isDisabled}
>
{t("check")}
</MainButton>
</div>

View File

@ -6,8 +6,42 @@
align-items: flex-start;
}
.cross {
position: absolute;
top: 24px;
right: 24px;
width: 24px;
height: 24px;
border: solid 2px #bdbdbd;
border-radius: 100%;
rotate: 45deg;
cursor: pointer;
}
.cross::before {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 10px;
height: 2px;
background-color: #bdbdbd;
}
.cross::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 2px;
height: 10px;
background-color: #bdbdbd;
}
.content {
width: 100%;
width: 100%;
}
.title {
@ -84,10 +118,10 @@
}
.check-btn {
border-radius: 30px;
background-color: #ea445a;
max-width: 200px;
margin: 48px auto;
border-radius: 30px;
background-color: #ea445a;
max-width: 200px;
margin: 48px auto;
}
.compatibility-categories {

View File

@ -34,10 +34,10 @@ function CreateProfilePage(): JSX.Element {
}, [progressbarRef])
const processItems = [
{ task: () => sleep(3300).then(() => setProgress(23)), label: t('money_energy') },
{ task: () => sleep(2550).then(() => setProgress(48)), label: t('sexual_energy') },
{ task: () => sleep(3789).then(() => setProgress(65)), label: t('black_energy') },
{ task: () => sleep(3789).then(() => setProgress(98)), label: t('relations_energy') },
{ task: () => sleep(3300).then(() => setProgress(23)), label: t('aura.1.loading') },
{ task: () => sleep(2550).then(() => setProgress(48)), label: t('aura.2.loading') },
{ task: () => sleep(3789).then(() => setProgress(65)), label: t('aura.3.loading') },
{ task: () => sleep(3789).then(() => setProgress(98)), label: t('aura.4.loading') },
]
const handleDone = () => Promise.resolve()
.then(() => setProgress(100))

View File

@ -1,26 +1,65 @@
import { useNavigate } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import routes from '@/routes'
import styles from './styles.module.css'
import MainButton from '../MainButton'
import { useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next";
import routes from "@/routes";
import styles from "./styles.module.css";
import MainButton from "../MainButton";
import Title from "../Title";
import { useApi, useApiCall } from "@/api";
import { useCallback } from "react";
import { Asset } from "@/api/resources/Assets";
function FeedbackPage(): JSX.Element {
const { t } = useTranslation()
const navigate = useNavigate()
const handleNext = () => navigate(routes.client.emailEnter())
const { t } = useTranslation();
const navigate = useNavigate();
const api = useApi();
const handleNext = () => navigate(routes.client.emailEnter());
const assetsData = useCallback(async () => {
const { assets } = await api.getAssets({ category: String("au") });
return assets;
}, [api]);
const {
data: assets,
// isPending
} = useApiCall<Asset[]>(assetsData);
const reviews = [
{
title: t("aura.name_1.review"),
text: t("aura.review_1.content"),
imageKey: "au.1.avatar",
},
{
title: t("aura.name_2.review"),
text: t("aura.review_2.content"),
imageKey: "au.2.avatar",
},
];
return (
<section className={`${styles.page} page`}>
<div className={styles.images}>
<img className={styles['profile-picture']} src="/profile-picture-feedback.png" alt="profile picture" />
<img className={styles.stars} src="/5-stars.png" alt="stop" />
<div className={styles.reviews}>
{reviews.map(({ title, text, imageKey }, index) => (
<div className={styles.review} key={index}>
<div className={styles.images}>
<img
className={styles["profile-picture"]}
src={assets?.find((asset) => asset.key === imageKey)?.url}
alt="profile picture"
/>
<div className={styles["header-container"]}>
<Title variant="h3">{title}</Title>
<img className={styles.stars} src="/5-stars.png" alt="stop" />
</div>
</div>
<p className={styles.text}>{text}</p>
</div>
))}
</div>
<p className={styles.text}>{t('feedback')}</p>
<MainButton onClick={handleNext}>
{t('next')}
</MainButton>
<MainButton onClick={handleNext}>{t("next")}</MainButton>
</section>
)
);
}
export default FeedbackPage
export default FeedbackPage;

View File

@ -6,6 +6,23 @@
gap: 16px;
}
.reviews {
display: flex;
flex-direction: row;
overflow-x: scroll;
width: 100vw;
max-width: 560px;
padding: 0 32px;
gap: 24px;
}
.review {
display: flex;
flex-direction: column;
gap: 16px;
min-width: 300px;
}
.images {
display: flex;
align-items: flex-end;
@ -16,6 +33,9 @@
.profile-picture {
width: 96px;
border-radius: 100%;
object-fit: cover;
object-position: center;
}
.stars {
@ -31,3 +51,8 @@
border-radius: 24px;
margin-bottom: 8px;
}
.header-container {
display: flex;
flex-direction: column;
}

View File

@ -81,7 +81,7 @@
flex-direction: column;
gap: 12px;
align-items: center;
margin-top: calc(100vh - 432px);
margin-top: calc(100vh - 478px);
}
.content__buttons {

View File

@ -13,23 +13,40 @@ function StartBreathModalChild({
return (
<section className={`${styles["start-breath"]} page`}>
<div className={styles.cross} onClick={handleBegin}></div>
<div className={styles.text}>
<Title variant="h4" className={styles["breathe-title"]}>
{t("breathe-title").split("").map((symbol, index) => (
<span className={styles["symbol"]} style={{ animationDelay: `${index * 0.05}s` }} key={index}>{symbol}</span>
))}
{t("breathe-title")
.split("")
.map((symbol, index) => (
<span
className={styles["symbol"]}
style={{ animationDelay: `${index * 0.05}s` }}
key={index}
>
{symbol}
</span>
))}
</Title>
<Title variant="h4" className={styles["breathe-subtitle"]}>
{t("breathe-subtitle").split("").map((symbol, index) => (
<span className={styles["symbol"]} style={{ animationDelay: `${(t("breathe-title").split("").length + index) * 0.05}s` }} key={index}>{symbol}</span>
))}
{t("breathe-subtitle")
.split("")
.map((symbol, index) => (
<span
className={styles["symbol"]}
style={{
animationDelay: `${
(t("breathe-title").split("").length + index) * 0.05
}s`,
}}
key={index}
>
{symbol}
</span>
))}
</Title>
</div>
<button
type="button"
className={styles.begin}
onClick={handleBegin}
>
<button type="button" className={styles.begin} onClick={handleBegin}>
{t("aura-begin_breathe-button")}
</button>
</section>

View File

@ -29,10 +29,44 @@
will-change: opacity;
animation-name: appearance;
animation-timing-function: ease;
animation-duration: .3s;
animation-duration: 0.3s;
animation-fill-mode: forwards;
}
.cross {
position: absolute;
top: 24px;
right: 24px;
width: 24px;
height: 24px;
border: solid 2px #bdbdbd;
border-radius: 100%;
rotate: 45deg;
cursor: pointer;
}
.cross::before {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 10px;
height: 2px;
background-color: #bdbdbd;
}
.cross::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 2px;
height: 10px;
background-color: #bdbdbd;
}
@keyframes appearance {
0% {
opacity: 0;

View File

@ -16,7 +16,11 @@ function UserCallbacksPage(): JSX.Element {
const homeConfig = useSelector(selectors.selectHome);
const handleNext = () => {
dispatch(actions.siteConfig.update({ home: { pathFromHome: homeConfig.pathFromHome, isShowNavbar: true } }));
dispatch(
actions.siteConfig.update({
home: { pathFromHome: homeConfig.pathFromHome, isShowNavbar: true },
})
);
if (homeConfig.pathFromHome === EPathsFromHome.compatibility) {
return navigate(routes.client.home());
}
@ -55,9 +59,16 @@ function UserCallbacksPage(): JSX.Element {
</div>
<p className={styles["result-container__text"]}>{text}</p>
</div>
<button className={styles.button} onClick={handleNext}>
{t("use-all-power")}
</button>
{homeConfig.pathFromHome === EPathsFromHome.breath && (
<button className={`${styles.button} ${styles['button-red']}`} onClick={handleNext}>
{t("aura.breath_compatibility.button")}
</button>
)}
{homeConfig.pathFromHome === EPathsFromHome.compatibility && (
<button className={styles.button} onClick={handleNext}>
{t("use-all-power")}
</button>
)}
</section>
);
}

View File

@ -52,6 +52,13 @@
color: #fff;
}
.button-red {
padding: 12px 0;
background: -moz-linear-gradient(to bottom, #FF003D, #6B174A);
background: -webkit-linear-gradient(to bottom, #FF003D, #6B174A);
background: linear-gradient(to bottom, #FF003D, #6B174A);
}
.cross {
position: absolute;
top: 24px;

View File

@ -89,5 +89,17 @@ export default {
"use-all-power": "Use all the power of your Aura",
"go-through": "Go through practicing recovery",
"now-you-know": "Now you know who`s causing your financial energy loss.",
"aura.breath_compatibility.button": "Discover who is causing your financial energy loss.",
"aura.attention.title": "ATTENTION",
"aura.warming_up.body": "The analysis of your Aura revealed a negative energy influence on you and a partial positive one. Such a combination is very rare! Which one would you like to start with?",
"aura.warming_up.button": "GOOD BAD",
"aura.1.loading": "MONEY energy test1",
"aura.2.loading": "SEXUAL energy test",
"aura.3.loading": "BLACK energy",
"aura.4.loading": "RELATIONS energy",
"aura.name_1.review": "Samantha Green",
"aura.name_2.review": "James Wilson",
"aura.review_1.content": "As for me, money just doesn't stick with me at all. It turned out that it wasn't because I was bad or irresponsible, but it was because of my partner. We delved deeply into this issue thanks to Aura, and what do you think? Everything changed the very next day. Now we are happy and wealthy.",
"aura.review_2.content": "I don't know why, but I always had bad experiences in relationships and couldn't find the one who would understand and love me. So, I took a special extended test and immediately figured everything out. It turns out that the birth date of the chosen one and number coincidences are very important in relationships. Now I consider this in all areas, and it helps me a lot."
},
}