diff --git a/public/locales/email-marketing-comp-v1/en/male_en.json b/public/locales/email-marketing-comp-v1/en/male_en.json new file mode 100644 index 0000000..bc527a1 --- /dev/null +++ b/public/locales/email-marketing-comp-v1/en/male_en.json @@ -0,0 +1,62 @@ +{ + "marketing-landing": { + "title": "Special Offer!", + "description": "Everything for free. Trial include!", + "title-hey": "Hey, Sun 👋", + "description-hey": "Your wellness and happiness are key for us!", + "title-highlights": "Highlights of your plan:", + "button-continue": "Continue", + "plan-includes-title": "Your plan also includes:", + "plan-includes-unlimited-horoscopes": "Unlimited daily / weekly / monthly / yearly horoscopes", + "plan-includes-astrology-lessons": "Astrology lessons and articles inside the app", + "plan-includes-lifestyle-calendars": "Beauty / health / travel and more calendars", + "plan-includes-compatibility-check": "Compatibility check with zodiac signs inside the app", + "personalized-plan-title": "So we decided to give you your personalized plan and access to the trial of our app", + "personalized-plan-free": "FOR FREE!", + "personal-astrologer-advice": "1:1 Advice from your personal astrologer", + "finding-compatible-partner": "Finding the most compatible partner", + "relationship-patterns-insights": "Insights into your relationship patterns, and emotional and sexual needs", + "better-understanding-yourself": "Better understanding of yourself and your needs", + "old-price-label": "OLD PRICE", + "new-price-label": "NEW PRICE", + "review-1": "Horoscope tells realistic facts about day to day life, which can be easily relatable. It shows direction.", + "review-2": "It makes me feel safe, seeing, warm and smart.", + "review-3": "I love that we have the \"my profile\" option. I love learning about myself.", + "circular-text-image": "circular-text-en.png", + "statistics-banner-text": "Last week alone got this relationship guide", + "statistics-banner-count": "+ people", + "money-back-guarantee-title": "Money-back guarantee", + "money-back-guarantee-text": "We are convinced that we will help you get a deeper understanding of your partner and how you can improve your relationship. After all of our stellar customer reviews, we are ready to return your money if you feel that this report doesn't provide any value. Find more about applicable limitations in our Money-back policy.", + "guaranteed-security-payments": "Guaranteed security payments" + }, + "special-offer": { + "title": "Special Offer!", + "start-trial": "Start your -day trial", + "cancel-anytime": "No pressure. Cancel anytime", + "policy": "By continuing you agree that if you don't cancel prior to the end of the -days trial, you will automatically be charged every 2 weeks until you cancel in settings. Learn more about cancellation and refund policy in Subscription terms", + "button-continue": "Continue", + "pricing-summary-total-today": "Total today:", + "pricing-summary-code-applied": "Code applied!", + "pricing-summary-cost-after-trial": "Your cost per 2 weeks after trial", + "pricing-summary-trial-description": "You will be charged only for your -day trial. Subscription renews automatically until cancelled. You can cancel at any time before the end of the trial." + }, + "save-off": { + "title": "SAVE % OFF!", + "instead": " instead ", + "instead-old-price": "of ", + "trial-duration": "-day trial", + "discount-offer": "% off on your personalized plan", + "button-trial": "GET -day trial" + }, + "secret-discount": { + "title": "You get a secret discount!", + "button-trial": "GET -DAY TRIAL", + "policy": "By continuing you agree that if you don't cancel prior to the end of the -days trial, you will automatically be charged for the introductory period of 14 days thereafter the standard rate of every 14 days until you cancel in settings. Learn more about cancellation and refund policy in Subscription terms.", + "secret-discount-table_title": "You get a secret discount!", + "secret-discount-table_subtitle": "No pressure. Cancel anytime.", + "secret-discount-table_discount-applied": "Secret discount applied!", + "secret-discount-table_cost-after-trial": "Your cost per days after trial:", + "secret-discount-table_you-save": "You save ", + "secret-discount-table_total-today": "Total today" + } +} \ No newline at end of file diff --git a/public/locales/email-marketing-palmistry-v2/en/male_en.json b/public/locales/email-marketing-palmistry-v2/en/male_en.json new file mode 100644 index 0000000..c28a80c --- /dev/null +++ b/public/locales/email-marketing-palmistry-v2/en/male_en.json @@ -0,0 +1,80 @@ +{ + "trial-payment": { + "transform_your_life": "Transform your\nlife with the Power\nof Palmistry — Get your\npersonalized plan today", + "get_trial_days": "GET -day trial", + "personalized_reading_ready": "Personalized Palmistry\nReading is ready!", + "hands_reveal_title": "What your hands and fingers can reveal about you", + "hands_reveal_description": "Your hands and fingers are like a personal storybook, with each line representing a chapter of your life.", + "prepare_personalized_plan": "We will prepare your\npersonalized plan", + "aura_users_stories": "Here are a few stories from\nAURA Users", + "as_featured_in": "As featured in", + "discount_expires": "Discount expires", + "min": "min", + "sec": "sec", + "payment_table_special_offer": "Special offer", + "payment_table_title": "Personalized plan for ", + "payment_table_total_today": "Total today", + "payment_table_cost": "Including 1-week trial personal reading", + "guaranteed_security_payments": "Guaranteed security payments", + "policy_link": "Subscription policy", + "subscription_policy": "You are enrolling in 1 week subscription. By continuing you agree that if you don't cancel prior to the end of the -day trial for the you will automatically be charged every 1 week until you cancel in settings. Learn more about cancellation and refund policy in ", + "money_back_guarantee_title": "100% Money-back Guarantee", + "money_back_guarantee_text": "We are convinced that we will help you get a deeper understanding of your partner and how you can improve your relationship. After all of our stellar customer reviews, we are ready to return your money if you feel that this report doesn't provide any value. Find more about applicable limitations in our Money-back policy.", + "palms_say_about_point5": " is a symbol of vitality, holds clues about your health, energy, and passion for life", + "palms_say_about_point5_color": "Life line", + "palms_say_about_point3": " reflects intellectual pursuits and mental strengths", + "palms_say_about_point3_color": "Head line", + "palms_say_about_point7": " reveals insights into your financial potential and approach towards wealth", + "palms_say_about_point7_color": "Fate line", + "palms_say_about_point1": " can reveal insights into your romantic journey, mapping your heart's desires", + "palms_say_about_point1_color": "Love line", + "palms_say_about_point9": "Each finger is a pillar of your personality, from leadership and ambition to creativity and self- expression", + "zodiac_sign": "Zodiac sign", + "zodiac_signs_aries": "Aries", + "zodiac_signs_taurus": "Taurus", + "zodiac_signs_gemini": "Gemini", + "zodiac_signs_cancer": "Cancer", + "zodiac_signs_leo": "Leo", + "zodiac_signs_virgo": "Virgo", + "zodiac_signs_libra": "Libra", + "zodiac_signs_scorpio": "Scorpio", + "zodiac_signs_sagittarius": "Sagittarius", + "zodiac_signs_capricorn": "Capricorn", + "zodiac_signs_aquarius": "Aquarius", + "zodiac_signs_pisces": "Pisces", + "gender": "Gender", + "male": "Male", + "female": "Female", + "date_of_birth": "Date of birth", + "place_of_birth": "Place of birth", + "reviews_username1": "Rebecca Bauman", + "reviews_tagline1": "\"It’s changed my life!\"", + "reviews_text1": "I'm thankful for this app and Akho! She's an excellent palm reader and astrologer—clear, thorough, and reassuring. I eagerly look forward to more sessions with her!", + "reviews_username2": "Mika Ryan", + "reviews_tagline2": "\"After years of seeking, I’ve finally found a true love.\"", + "reviews_text2": "I was hesitant about whether it was really worth trying, but now I have no regrets and I'm enjoying my new relationships!", + "reviews_username3": "Amanda Holmes", + "reviews_tagline3": "\"I’ve found a job I really enjoy.\"", + "reviews_text3": "Thanks to Vladana, I've finally discovered a clue about what my life's purpose really is and what kind of job resonates with me better!", + "copyright": ", Wit Apps LLC,
2108 N ST STE 5446 SACRAMENTO, CA 95816, US" + }, + "save-off": { + "title": "SAVE % OFF!", + "instead": " instead ", + "instead-old-price": "of ", + "trial-duration": "-day trial", + "discount-offer": "% off on your personalized plan", + "button-trial": "GET -day trial" + }, + "secret-discount": { + "title": "You get a secret discount!", + "button-trial": "GET -DAY TRIAL", + "policy": "By continuing you agree that if you don't cancel prior to the end of the -days trial, you will automatically be charged for the introductory period of 14 days thereafter the standard rate of every 14 days until you cancel in settings. Learn more about cancellation and refund policy in Subscription terms.", + "secret-discount-table_title": "You get a secret discount!", + "secret-discount-table_subtitle": "No pressure. Cancel anytime.", + "secret-discount-table_discount-applied": "Secret discount applied!", + "secret-discount-table_cost-after-trial": "Your cost per days after trial:", + "secret-discount-table_you-save": "You save ", + "secret-discount-table_total-today": "Total today" + } +} \ No newline at end of file diff --git a/public/locales/palmistry-v1.1/de/female_de.json b/public/locales/palmistry-v1_1/de/female_de.json similarity index 100% rename from public/locales/palmistry-v1.1/de/female_de.json rename to public/locales/palmistry-v1_1/de/female_de.json diff --git a/public/locales/palmistry-v1.1/de/male_de.json b/public/locales/palmistry-v1_1/de/male_de.json similarity index 100% rename from public/locales/palmistry-v1.1/de/male_de.json rename to public/locales/palmistry-v1_1/de/male_de.json diff --git a/public/locales/palmistry-v1.1/en/female_en.json b/public/locales/palmistry-v1_1/en/female_en.json similarity index 100% rename from public/locales/palmistry-v1.1/en/female_en.json rename to public/locales/palmistry-v1_1/en/female_en.json diff --git a/public/locales/palmistry-v1.1/en/male_en.json b/public/locales/palmistry-v1_1/en/male_en.json similarity index 100% rename from public/locales/palmistry-v1.1/en/male_en.json rename to public/locales/palmistry-v1_1/en/male_en.json diff --git a/public/locales/palmistry-v1.1/es/female_es.json b/public/locales/palmistry-v1_1/es/female_es.json similarity index 100% rename from public/locales/palmistry-v1.1/es/female_es.json rename to public/locales/palmistry-v1_1/es/female_es.json diff --git a/public/locales/palmistry-v1.1/es/male_es.json b/public/locales/palmistry-v1_1/es/male_es.json similarity index 100% rename from public/locales/palmistry-v1.1/es/male_es.json rename to public/locales/palmistry-v1_1/es/male_es.json diff --git a/public/locales/palmistry-v1.1/fr/female_fr.json b/public/locales/palmistry-v1_1/fr/female_fr.json similarity index 100% rename from public/locales/palmistry-v1.1/fr/female_fr.json rename to public/locales/palmistry-v1_1/fr/female_fr.json diff --git a/public/locales/palmistry-v1.1/fr/male_fr.json b/public/locales/palmistry-v1_1/fr/male_fr.json similarity index 100% rename from public/locales/palmistry-v1.1/fr/male_fr.json rename to public/locales/palmistry-v1_1/fr/male_fr.json diff --git a/public/locales/palmistry-v1.1/hi/female_hi.json b/public/locales/palmistry-v1_1/hi/female_hi.json similarity index 100% rename from public/locales/palmistry-v1.1/hi/female_hi.json rename to public/locales/palmistry-v1_1/hi/female_hi.json diff --git a/public/locales/palmistry-v1.1/hi/male_hi.json b/public/locales/palmistry-v1_1/hi/male_hi.json similarity index 100% rename from public/locales/palmistry-v1.1/hi/male_hi.json rename to public/locales/palmistry-v1_1/hi/male_hi.json diff --git a/public/locales/palmistry-v1.1/pt-br/female_pt-br.json b/public/locales/palmistry-v1_1/pt-br/female_pt-br.json similarity index 100% rename from public/locales/palmistry-v1.1/pt-br/female_pt-br.json rename to public/locales/palmistry-v1_1/pt-br/female_pt-br.json diff --git a/public/locales/palmistry-v1.1/pt-br/male_pt-br.json b/public/locales/palmistry-v1_1/pt-br/male_pt-br.json similarity index 100% rename from public/locales/palmistry-v1.1/pt-br/male_pt-br.json rename to public/locales/palmistry-v1_1/pt-br/male_pt-br.json diff --git a/public/locales/palmistry-v1.1/pt-pt/female_pt-pt.json b/public/locales/palmistry-v1_1/pt-pt/female_pt-pt.json similarity index 100% rename from public/locales/palmistry-v1.1/pt-pt/female_pt-pt.json rename to public/locales/palmistry-v1_1/pt-pt/female_pt-pt.json diff --git a/public/locales/palmistry-v1.1/pt-pt/male_pt-pt.json b/public/locales/palmistry-v1_1/pt-pt/male_pt-pt.json similarity index 100% rename from public/locales/palmistry-v1.1/pt-pt/male_pt-pt.json rename to public/locales/palmistry-v1_1/pt-pt/male_pt-pt.json diff --git a/public/locales/palmistry-v1.1/ru/female_ru.json b/public/locales/palmistry-v1_1/ru/female_ru.json similarity index 100% rename from public/locales/palmistry-v1.1/ru/female_ru.json rename to public/locales/palmistry-v1_1/ru/female_ru.json diff --git a/public/locales/palmistry-v1.1/ru/male_ru.json b/public/locales/palmistry-v1_1/ru/male_ru.json similarity index 100% rename from public/locales/palmistry-v1.1/ru/male_ru.json rename to public/locales/palmistry-v1_1/ru/male_ru.json diff --git a/public/v1/email-marketing/circular-text-en.png b/public/v1/email-marketing/circular-text-en.png new file mode 100644 index 0000000..8605ac0 Binary files /dev/null and b/public/v1/email-marketing/circular-text-en.png differ diff --git a/public/v1/email-marketing/fire.png b/public/v1/email-marketing/fire.png new file mode 100644 index 0000000..1966e9a Binary files /dev/null and b/public/v1/email-marketing/fire.png differ diff --git a/public/v1/email-marketing/gift.png b/public/v1/email-marketing/gift.png new file mode 100644 index 0000000..bf58560 Binary files /dev/null and b/public/v1/email-marketing/gift.png differ diff --git a/public/v1/email-marketing/gift.svg b/public/v1/email-marketing/gift.svg new file mode 100644 index 0000000..1bfccec --- /dev/null +++ b/public/v1/email-marketing/gift.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/api/resources/Paywall.ts b/src/api/resources/Paywall.ts index 16a1cfe..605e948 100644 --- a/src/api/resources/Paywall.ts +++ b/src/api/resources/Paywall.ts @@ -19,7 +19,8 @@ export enum EPlacementKeys { "aura.placement.palmistry.redesign" = "aura.placement.palmistry.redesign", "aura.placement.chat" = "aura.placement.chat", "aura.placement.email.palmistry" = "aura.placement.email.palmistry", - "aura.placement.email.palmistry.discount" = "aura.placement.email.palmistry.discount" + "aura.placement.email.palmistry.discount" = "aura.placement.email.palmistry.discount", + "aura.placement.email.compatibility.discount" = "aura.placement.email.compatibility.discount" } export interface ResponseGetSuccess { diff --git a/src/auth/AuthContext.ts b/src/auth/AuthContext.ts index e7c16f6..35af7a7 100644 --- a/src/auth/AuthContext.ts +++ b/src/auth/AuthContext.ts @@ -1,11 +1,12 @@ import { createContext } from 'react' import { AuthToken, User } from '../api' +import { IUser } from '@/api/resources/User' export interface AuthContextValue { user: User.User | null token: AuthToken logout: () => void - signUp: (token: AuthToken, user: User.User) => AuthToken + signUp: (token: AuthToken, user: User.User, newUser?: IUser) => AuthToken } export const AuthContext = createContext({} as AuthContextValue) diff --git a/src/auth/AuthProvider.tsx b/src/auth/AuthProvider.tsx index 3e85add..9d87b99 100644 --- a/src/auth/AuthProvider.tsx +++ b/src/auth/AuthProvider.tsx @@ -3,6 +3,7 @@ import { useDispatch, useSelector } from "react-redux"; import { actions, selectors } from "../store"; import { AuthToken, User } from "../api"; import { AuthContext } from "./AuthContext"; +import { IUser } from "@/api/resources/User"; export function AuthProvider({ children, @@ -11,7 +12,7 @@ export function AuthProvider({ const token = useSelector(selectors.selectToken); const user = useSelector(selectors.selectUser); const signUp = useCallback( - (token: AuthToken, user: User.User): AuthToken => { + (token: AuthToken, user: User.User, newUser?: IUser): AuthToken => { dispatch(actions.token.update(token)); dispatch(actions.user.update(user)); dispatch(actions.form.addEmail(user.email)); @@ -23,6 +24,20 @@ export function AuthProvider({ ) ); } + if (newUser) { + dispatch(actions.questionnaire.update({ + gender: newUser.profile.gender ?? undefined, + birthPlace: newUser.profile.birthplace?.address ?? undefined, + birthdate: newUser.profile.birthdate ?? undefined, + partnerBirthPlace: newUser.partner?.birthplace?.address ?? undefined, + partnerBirthdate: newUser.partner?.birthdate ?? undefined, + partnerGender: newUser.partner?.gender ?? undefined, + })) + + dispatch(actions.user.update({ + username: newUser.profile.name ?? undefined, + })); + } return token; }, [dispatch] diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index 386a128..926b591 100755 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -242,21 +242,7 @@ function App(): JSX.Element { const { token } = await api.getRealToken({ token: jwtToken }); const { user } = await api.getUser({ token }); const { user: userMe } = await api.getMe({ token }); - signUp(token, user); - - dispatch(actions.questionnaire.update({ - gender: userMe.profile.gender ?? undefined, - birthPlace: userMe.profile.birthplace?.address ?? undefined, - birthdate: userMe.profile.birthdate ?? undefined, - partnerBirthPlace: userMe.partner?.birthplace?.address ?? undefined, - partnerBirthdate: userMe.partner?.birthdate ?? undefined, - partnerGender: userMe.partner?.gender ?? undefined, - })) - - dispatch(actions.user.update({ - username: userMe.profile.name ?? undefined, - })); - + signUp(token, user, userMe); } catch (error) { console.log("Error of get real token or get user: "); console.error(error); @@ -331,7 +317,7 @@ function App(): JSX.Element { } > - } /> + } /> } /> } /> diff --git a/src/components/ChatsPath/pages/ExpertChat/styles.module.scss b/src/components/ChatsPath/pages/ExpertChat/styles.module.scss index 1b87453..dcfa415 100644 --- a/src/components/ChatsPath/pages/ExpertChat/styles.module.scss +++ b/src/components/ChatsPath/pages/ExpertChat/styles.module.scss @@ -13,10 +13,14 @@ .modal { max-height: calc(100dvh - 32px); - height: 100%; - top: auto; - bottom: 0; - transform: translate(-50%, 0); + // height: 100%; + // top: auto; + // bottom: 0; + // transform: translate(-50%, 0); +} + +.modal-title { + color: #2f2e37; } .header-container { diff --git a/src/components/EmailMarketing/v1/components/AdviceFromAstrologer/index.tsx b/src/components/EmailMarketing/v1/components/AdviceFromAstrologer/index.tsx index 56f4a55..9196b35 100644 --- a/src/components/EmailMarketing/v1/components/AdviceFromAstrologer/index.tsx +++ b/src/components/EmailMarketing/v1/components/AdviceFromAstrologer/index.tsx @@ -1,12 +1,23 @@ import { images } from "../../data"; import TextWithEmoji from "../TextWithEmoji"; import styles from "./styles.module.scss"; +import { useTranslations } from "@/hooks/translations"; +import { ELocalesPlacement } from "@/locales"; function AdviceFromAstrologer() { + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingCompatibilityV1); + return (
- - messages + + messages
) } diff --git a/src/components/EmailMarketing/v1/components/CustomerCounter/index.tsx b/src/components/EmailMarketing/v1/components/CustomerCounter/index.tsx index 98ff065..37804ee 100644 --- a/src/components/EmailMarketing/v1/components/CustomerCounter/index.tsx +++ b/src/components/EmailMarketing/v1/components/CustomerCounter/index.tsx @@ -1,11 +1,15 @@ +import { useTranslations } from '@/hooks/translations'; import { images } from '../../data'; import styles from './styles.module.scss'; +import { ELocalesPlacement } from '@/locales'; interface CustomerCounterProps { count: number; } function CustomerCounter({ count }: CustomerCounterProps) { + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingCompatibilityV1); + return (
{/*
@@ -27,7 +31,7 @@ function CustomerCounter({ count }: CustomerCounterProps) {
*/} - +
{count}
); diff --git a/src/components/EmailMarketing/v1/components/FindingPartner/index.tsx b/src/components/EmailMarketing/v1/components/FindingPartner/index.tsx index 7a816a7..c9f8095 100644 --- a/src/components/EmailMarketing/v1/components/FindingPartner/index.tsx +++ b/src/components/EmailMarketing/v1/components/FindingPartner/index.tsx @@ -1,11 +1,18 @@ import { images } from "../../data"; import TextWithEmoji from "../TextWithEmoji"; import styles from "./styles.module.scss"; +import { useTranslations } from "@/hooks/translations"; +import { ELocalesPlacement } from "@/locales"; function FindingPartner() { + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingCompatibilityV1); + return (
- + smartphone
) diff --git a/src/components/EmailMarketing/v1/components/GivePersonalizedPlan/index.tsx b/src/components/EmailMarketing/v1/components/GivePersonalizedPlan/index.tsx index 650277f..ed86046 100644 --- a/src/components/EmailMarketing/v1/components/GivePersonalizedPlan/index.tsx +++ b/src/components/EmailMarketing/v1/components/GivePersonalizedPlan/index.tsx @@ -1,14 +1,17 @@ import Title from "@/components/Title"; import styles from "./styles.module.scss"; import { images } from "../../data"; +import { useTranslations } from "@/hooks/translations"; +import { ELocalesPlacement } from "@/locales"; function GivePersonalizedPlan() { + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingCompatibilityV1); + return (
- So we decided to give you your - personalized plan and access to - the trial of our app <span>FOR FREE!</span> + {translate("marketing-landing.personalized-plan-title")} + <span> {translate("marketing-landing.personalized-plan-free")}</span> stars stars diff --git a/src/components/EmailMarketing/v1/components/GuaranteedSecurityPayments/index.tsx b/src/components/EmailMarketing/v1/components/GuaranteedSecurityPayments/index.tsx index 9169882..42d7e56 100644 --- a/src/components/EmailMarketing/v1/components/GuaranteedSecurityPayments/index.tsx +++ b/src/components/EmailMarketing/v1/components/GuaranteedSecurityPayments/index.tsx @@ -1,11 +1,15 @@ import { images } from "../../data"; import styles from "./styles.module.scss"; +import { useTranslations } from "@/hooks/translations"; +import { ELocalesPlacement } from "@/locales"; function GuaranteedSecurityPayments() { + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingCompatibilityV1); + return (
guaranteed -

Guaranteed security payments

+

{translate("marketing-landing.guaranteed-security-payments")}

) } diff --git a/src/components/EmailMarketing/v1/components/InsightsRelationship/index.tsx b/src/components/EmailMarketing/v1/components/InsightsRelationship/index.tsx index 6116232..d2ac48d 100644 --- a/src/components/EmailMarketing/v1/components/InsightsRelationship/index.tsx +++ b/src/components/EmailMarketing/v1/components/InsightsRelationship/index.tsx @@ -1,12 +1,16 @@ import { images } from "../../data"; import TextWithEmoji from "../TextWithEmoji"; import styles from "./styles.module.scss"; +import { useTranslations } from "@/hooks/translations"; +import { ELocalesPlacement } from "@/locales"; function InsightsRelationship() { + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingCompatibilityV1); + return (
relationships diff --git a/src/components/EmailMarketing/v1/components/MoneyBackGuarantee/index.tsx b/src/components/EmailMarketing/v1/components/MoneyBackGuarantee/index.tsx index b3abb35..5975ebb 100644 --- a/src/components/EmailMarketing/v1/components/MoneyBackGuarantee/index.tsx +++ b/src/components/EmailMarketing/v1/components/MoneyBackGuarantee/index.tsx @@ -1,22 +1,22 @@ import TextWithEmoji from "../TextWithEmoji"; import styles from "./styles.module.scss"; +import { useTranslations } from "@/hooks/translations"; +import { ELocalesPlacement } from "@/locales"; -function UnderstandingYourself() { +function MoneyBackGuarantee() { + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingCompatibilityV1); + return (

- We are convinced that we will help you get a deeper understanding of - your partner and how you can improve your relationship. - After all of our stellar customer reviews, we are ready to return your money - if you feel that this report doesn’t provide any value. Find more - about applicable limitations in our Money-back policy. + {translate("marketing-landing.money-back-guarantee-text")}

) } -export default UnderstandingYourself \ No newline at end of file +export default MoneyBackGuarantee \ No newline at end of file diff --git a/src/components/EmailMarketing/v1/components/PriceComparison/index.tsx b/src/components/EmailMarketing/v1/components/PriceComparison/index.tsx index 9de0e74..44fa738 100644 --- a/src/components/EmailMarketing/v1/components/PriceComparison/index.tsx +++ b/src/components/EmailMarketing/v1/components/PriceComparison/index.tsx @@ -1,5 +1,7 @@ import { combineStyles } from "@/services/styles"; import styles from "./styles.module.scss"; +import { useTranslations } from "@/hooks/translations"; +import { ELocalesPlacement } from "@/locales"; interface PriceComparisonProps { oldPrice: number | string; @@ -7,11 +9,13 @@ interface PriceComparisonProps { } function PriceComparison({ oldPrice, newPrice }: PriceComparisonProps) { + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingCompatibilityV1); + return (
- OLD PRICE + {translate("marketing-landing.old-price-label")}
{oldPrice}
@@ -20,7 +24,7 @@ function PriceComparison({ oldPrice, newPrice }: PriceComparisonProps) {
- NEW PRICE + {translate("marketing-landing.new-price-label")}
${newPrice}
diff --git a/src/components/EmailMarketing/v1/components/PricingSummary/index.tsx b/src/components/EmailMarketing/v1/components/PricingSummary/index.tsx index 22c92a1..d4a6533 100644 --- a/src/components/EmailMarketing/v1/components/PricingSummary/index.tsx +++ b/src/components/EmailMarketing/v1/components/PricingSummary/index.tsx @@ -1,6 +1,9 @@ import { combineStyles } from '@/services/styles'; import CountdownTimer from '../CountdownTimer'; import styles from './styles.module.scss'; +import { useTranslations } from "@/hooks/translations"; +import { addCurrency, ELocalesPlacement } from "@/locales"; +import { Currency } from '@/components/PaymentTable'; interface PricingSummaryProps { totalToday: number | string; @@ -8,6 +11,7 @@ interface PricingSummaryProps { discountedPrice: number | string; trialDuration: number | string; saveText: string; + currency: Currency; } function PricingSummary({ @@ -15,21 +19,24 @@ function PricingSummary({ originalPrice, discountedPrice, trialDuration, - saveText + saveText, + currency }: PricingSummaryProps) { + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingCompatibilityV1); + return (
- Total today: + {translate("special-offer.pricing-summary-total-today")} ${totalToday}
- Code applied! + {translate("special-offer.pricing-summary-code-applied")}
- Your cost per 2 weeks after trial + {translate("special-offer.pricing-summary-cost-after-trial")}
${originalPrice} ${discountedPrice} @@ -40,7 +47,10 @@ function PricingSummary({

- You will be charged only ${totalToday} for your {trialDuration}-day trial. Subscription renews automatically until cancelled. You can cancel at any time before the end of the trial. + {translate("special-offer.pricing-summary-trial-description", { + totalToday: addCurrency(totalToday, currency), + trialDuration: trialDuration + })}

); diff --git a/src/components/EmailMarketing/v1/components/Reviews/index.tsx b/src/components/EmailMarketing/v1/components/Reviews/index.tsx index 16083c0..9b08275 100644 --- a/src/components/EmailMarketing/v1/components/Reviews/index.tsx +++ b/src/components/EmailMarketing/v1/components/Reviews/index.tsx @@ -6,7 +6,7 @@ import { ELocalesPlacement } from "@/locales"; import { images } from "../../data"; function Reviews() { - const { translate } = useTranslations(ELocalesPlacement.PalmistryV1); + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingCompatibilityV1); const reviews: IReviewProps[] = useMemo( () => [ { @@ -14,21 +14,21 @@ function Reviews() { username: "@andi36_11", date: "06/05/2024", gender: "male", - text: "Horoscope tells realistic facts about day to day life, which can be easily relatable. It shows direction.", + text: translate("marketing-landing.review-1"), }, { avatar: images("aramaska.png"), username: "@aramaska", date: "04/17/2024", gender: "female", - text: "It makes me feel safe, seeing, warm and smart.", + text: translate("marketing-landing.review-2"), }, { avatar: images("patterso.png"), username: "@patterso", date: "03/01/2024", gender: "female", - text: "I love that we have the “my profile” option. I love learning about myself.", + text: translate("marketing-landing.review-3"), }, ], [translate] diff --git a/src/components/EmailMarketing/v1/components/SecretDiscountTable/index.tsx b/src/components/EmailMarketing/v1/components/SecretDiscountTable/index.tsx new file mode 100644 index 0000000..62657f5 --- /dev/null +++ b/src/components/EmailMarketing/v1/components/SecretDiscountTable/index.tsx @@ -0,0 +1,67 @@ +import Title from "@/components/Title"; +import styles from "./styles.module.scss"; +import { images } from "../../data"; +import { usePaywall } from "@/hooks/paywall/usePaywall"; +import { addCurrency, ELocalesPlacement } from "@/locales"; +import { EPlacementKeys } from "@/api/resources/Paywall"; +import { Currency } from "@/components/PaymentTable"; +import { useTranslations } from "@/hooks/translations"; + +const placementKey = EPlacementKeys["aura.placement.email.compatibility.discount"] + +const getPrice = (price: number, currency: Currency) => { + if (price % 100 === 0) { + return addCurrency(price / 100, currency); + } + return addCurrency( + (price / 100).toFixed(2), + currency + ); +} + +function SecretDiscountTable() { + const { products, currency, getText } = usePaywall({ + placementKey, + localesPlacement: ELocalesPlacement.EmailMarketingCompatibilityV1, + }); + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingCompatibilityV1); + + const activeProduct = products[0]; + const price = activeProduct?.price || 0; + const trialPrice = activeProduct?.trialPrice || 0; + const trialDuration = activeProduct?.trialDuration || 7; + + return ( +
+ + {translate("secret-discount.secret-discount-table_title")} + +

+ {translate("secret-discount.secret-discount-table_subtitle")} +

+
+ Gift + + {translate("secret-discount.secret-discount-table_discount-applied")} + + {getText("old.discount")} + {getText("new.discount")} +
+
+

{translate("secret-discount.secret-discount-table_cost-after-trial", { days: trialDuration })}

+ {addCurrency(Number(getText("old.price")), currency)} + {getPrice(price, currency)} +
+
+

{translate("secret-discount.secret-discount-table_you-save", { amount: addCurrency(Number(getText("save")), currency) })}

+
+
+
+

{translate("secret-discount.secret-discount-table_total-today")}

+ {getPrice(trialPrice, currency)} +
+
+ ) +} + +export default SecretDiscountTable \ No newline at end of file diff --git a/src/components/EmailMarketing/v1/components/SecretDiscountTable/styles.module.scss b/src/components/EmailMarketing/v1/components/SecretDiscountTable/styles.module.scss new file mode 100644 index 0000000..b3d981e --- /dev/null +++ b/src/components/EmailMarketing/v1/components/SecretDiscountTable/styles.module.scss @@ -0,0 +1,110 @@ +.container { + background-color: #fff; + border-radius: 13px; + width: calc(100% + 24px); + padding: 16px 0 22px; + box-shadow: 2px 11px 17px -1px rgba(0, 0, 0, 0.13); + margin-top: 42px; + color: #363636; +} + +.title { + font-size: 20px; + font-weight: 600; + line-height: 24px; + margin-bottom: 0; +} + +.subtitle { + font-size: 13px; + font-weight: 400; + line-height: 16px; + margin-top: 5px; + text-align: center; +} + +.applied { + width: 100%; + background-color: #293D68; + padding: 7px 10px; + margin-top: 12px; + display: flex; + align-items: center; + justify-content: start; + gap: 10px; + color: #fff; + + &>img { + width: 17px; + } + + &>.title { + font-size: 15px; + font-weight: 500; + line-height: 19px; + } + + &>.old-discount { + font-size: 15px; + color: #B2B2B2; + text-decoration: line-through; + margin-left: 4px; + } + + &>.new-discount { + color: #fff; + font-size: 20px; + font-weight: 600; + line-height: 19px; + margin-left: 4px; + } +} + +.grid-line { + display: grid; + grid-template-columns: 1fr 22px 22px; + align-items: center; + gap: 28px; + margin-top: 8px; + padding: 0 24px 0 10px; + + &>p { + font-size: 12px; + font-weight: 400; + line-height: 130%; + margin-bottom: 0; + } + + &.days-14>span { + font-size: 12px; + font-weight: 400; + line-height: 130%; + + &.old-price { + text-decoration: line-through; + } + } + + &.save { + margin-top: 2px; + } + + &.total-today { + + &>p, + span { + font-size: 16px; + font-weight: 500; + line-height: 130%; + margin-top: 8px; + } + } +} + +hr { + display: block; + width: 100%; + margin: 0; + background-color: #363636; + margin-top: 6px; +} \ No newline at end of file diff --git a/src/components/EmailMarketing/v1/components/StatisticsBanner/index.tsx b/src/components/EmailMarketing/v1/components/StatisticsBanner/index.tsx index 4732fe0..28bc253 100644 --- a/src/components/EmailMarketing/v1/components/StatisticsBanner/index.tsx +++ b/src/components/EmailMarketing/v1/components/StatisticsBanner/index.tsx @@ -1,15 +1,19 @@ import styles from './styles.module.scss'; +import { useTranslations } from "@/hooks/translations"; +import { ELocalesPlacement } from "@/locales"; interface StatisticsBannerProps { count: number; } function StatisticsBanner({ count }: StatisticsBannerProps) { + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingCompatibilityV1); + return (
- Last week alone {count}+ people got this relationship guide + {translate("marketing-landing.statistics-banner-text", { b: {translate("marketing-landing.statistics-banner-count", { count })} })}
diff --git a/src/components/EmailMarketing/v1/components/UnderstandingYourself/index.tsx b/src/components/EmailMarketing/v1/components/UnderstandingYourself/index.tsx index 509dd64..90c0fcf 100644 --- a/src/components/EmailMarketing/v1/components/UnderstandingYourself/index.tsx +++ b/src/components/EmailMarketing/v1/components/UnderstandingYourself/index.tsx @@ -1,12 +1,16 @@ import { images } from "../../data"; import TextWithEmoji from "../TextWithEmoji"; import styles from "./styles.module.scss"; +import { useTranslations } from "@/hooks/translations"; +import { ELocalesPlacement } from "@/locales"; function UnderstandingYourself() { + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingCompatibilityV1); + return (
hand with eye diff --git a/src/components/EmailMarketing/v1/images/SVG/Blob/index.tsx b/src/components/EmailMarketing/v1/images/SVG/Blob/index.tsx new file mode 100644 index 0000000..6273fff --- /dev/null +++ b/src/components/EmailMarketing/v1/images/SVG/Blob/index.tsx @@ -0,0 +1,18 @@ +import { SVGProps } from "react" + +function Blob(props: SVGProps) { + return ( + + + + + + + + + + + ) +} + +export default Blob \ No newline at end of file diff --git a/src/components/EmailMarketing/v1/images/SVG/Blob2/index.tsx b/src/components/EmailMarketing/v1/images/SVG/Blob2/index.tsx new file mode 100644 index 0000000..6403d80 --- /dev/null +++ b/src/components/EmailMarketing/v1/images/SVG/Blob2/index.tsx @@ -0,0 +1,17 @@ +import { SVGProps } from "react" + +function Blob2(props: SVGProps) { + return ( + + + + + + + + + + ) +} + +export default Blob2 \ No newline at end of file diff --git a/src/components/EmailMarketing/v1/images/SVG/Blob3/index.tsx b/src/components/EmailMarketing/v1/images/SVG/Blob3/index.tsx new file mode 100644 index 0000000..dd7c6ca --- /dev/null +++ b/src/components/EmailMarketing/v1/images/SVG/Blob3/index.tsx @@ -0,0 +1,18 @@ +import { SVGProps } from "react" + +function Blob3(props: SVGProps) { + return ( + + + + + + + + + + + ) +} + +export default Blob3 \ No newline at end of file diff --git a/src/components/EmailMarketing/v1/images/SVG/Blob4/index.tsx b/src/components/EmailMarketing/v1/images/SVG/Blob4/index.tsx new file mode 100644 index 0000000..6001c5c --- /dev/null +++ b/src/components/EmailMarketing/v1/images/SVG/Blob4/index.tsx @@ -0,0 +1,21 @@ +import { SVGProps } from "react" + +function Blob4(props: SVGProps) { + const width = props.width ? Number(props.width) : 419; + const height = props.height ? Number(props.height) : 193; + return ( + + + + + + + + + + + + ) +} + +export default Blob4 \ No newline at end of file diff --git a/src/components/EmailMarketing/v1/pages/MarketingLanding/index.tsx b/src/components/EmailMarketing/v1/pages/MarketingLanding/index.tsx index 0e11329..40f3663 100644 --- a/src/components/EmailMarketing/v1/pages/MarketingLanding/index.tsx +++ b/src/components/EmailMarketing/v1/pages/MarketingLanding/index.tsx @@ -21,23 +21,11 @@ import routes from "@/routes"; import { usePaywall } from "@/hooks/paywall/usePaywall"; import { EPlacementKeys } from "@/api/resources/Paywall"; import BlurComponent from "@/components/BlurComponent"; - -const features = [ - { - text: "Unlimited daily / weekly / monthly / yearly horoscopes" - }, - { - text: "Astrology lessons and articles inside the app" - }, - { - text: "Beauty / health / travel and more calendars" - }, - { - text: "Compatibility check with zodiac signs inside the app" - } -]; +import { useTranslations } from "@/hooks/translations"; +import { ELocalesPlacement } from "@/locales"; function MarketingLanding() { + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingCompatibilityV1); const navigate = useNavigate(); const { products, getText } = usePaywall({ placementKey: EPlacementKeys["aura.placement.email.marketing"], @@ -47,6 +35,21 @@ function MarketingLanding() { navigate(routes.client.emailMarketingV1SpecialOffer()); } + const features = [ + { + text: translate("marketing-landing.plan-includes-unlimited-horoscopes") + }, + { + text: translate("marketing-landing.plan-includes-astrology-lessons") + }, + { + text: translate("marketing-landing.plan-includes-lifestyle-calendars") + }, + { + text: translate("marketing-landing.plan-includes-compatibility-check") + } + ]; + return (
{/* Background elements */} @@ -58,25 +61,27 @@ function MarketingLanding() { <> <img className={combineStyles(styles.backgroundElement, styles.backgroundElement3)} src={images("gift-small.png")} alt="Gift" /> - Special Offer! + {translate("marketing-landing.title")} </>

- Everything for free. Trial include! + {translate("marketing-landing.description")}

- Hey, Sun <span>👋</span> + {translate("marketing-landing.title-hey")} -

Your wellness and happiness are key for us!

+

+ {translate("marketing-landing.description-hey")} +

<svg className={combineStyles(styles.backgroundElement, styles.backgroundElement5)} width="31" height="31" viewBox="0 0 31 31" fill="none" xmlns="http://www.w3.org/2000/svg"> <circle cx="15.5" cy="15.5" r="15.5" fill="#DEBA00" /> </svg> - Highlights of your plan: + {translate("marketing-landing.title-highlights")}
@@ -125,7 +130,10 @@ function MarketingLanding() {
- + @@ -175,7 +183,7 @@ function MarketingLanding() {
diff --git a/src/components/EmailMarketing/v1/pages/SaveOff/index.tsx b/src/components/EmailMarketing/v1/pages/SaveOff/index.tsx new file mode 100644 index 0000000..950d4a7 --- /dev/null +++ b/src/components/EmailMarketing/v1/pages/SaveOff/index.tsx @@ -0,0 +1,71 @@ +import styles from "./styles.module.scss"; +import Blob from "../../images/SVG/Blob"; +import { images } from "../../data"; +import Title from "@/components/Title"; +import Button from "../../components/Button"; +import Blob2 from "../../images/SVG/Blob2"; +import { useNavigate } from "react-router-dom"; +import routes from "@/routes"; +import { usePaywall } from "@/hooks/paywall/usePaywall"; +import { EPlacementKeys } from "@/api/resources/Paywall"; +import { addCurrency, ELocalesPlacement } from "@/locales"; +import { useTranslations } from "@/hooks/translations"; +import Header from "@/components/pages/ABDesign/v1/components/Header"; + +const placementKey = EPlacementKeys["aura.placement.email.compatibility.discount"] + +function SaveOff() { + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingCompatibilityV1); + const { products, currency, getText } = usePaywall({ + placementKey, + localesPlacement: ELocalesPlacement.EmailMarketingCompatibilityV1, + }); + const activeProduct = products[0] + const price = (activeProduct?.price || 0) / 100 + const trialDuration = activeProduct?.trialDuration || 7 + + const navigate = useNavigate(); + + const handleNext = () => { + navigate(routes.client.emailMarketingV1SecretDiscount()); + } + + return ( +
+
+ + + gift + + {translate("save-off.title", { discount: getText("discount") })} + +

+ {translate("save-off.instead", { + price: {addCurrency(price, currency)}, + oldPrice: + {translate("save-off.instead-old-price", { + oldPrice: addCurrency(getText("full.price") as string, currency) + })} + + })} +

+

+ fire + {translate("save-off.trial-duration", { days: trialDuration })} +

+

+ gift + {translate("save-off.discount-offer", { discount: getText("discount") })} +

+ +
+ ) +} + +export default SaveOff \ No newline at end of file diff --git a/src/components/EmailMarketing/v1/pages/SaveOff/styles.module.scss b/src/components/EmailMarketing/v1/pages/SaveOff/styles.module.scss new file mode 100644 index 0000000..8a04a7a --- /dev/null +++ b/src/components/EmailMarketing/v1/pages/SaveOff/styles.module.scss @@ -0,0 +1,85 @@ +.container { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + padding: 20px 26px; + min-height: 100dvh; + max-width: 560px; + margin: 0 auto; +} + +.header { + padding: 8px 0 30px; + + &>button { + margin-left: -12px; + } +} + +.blob { + position: absolute; + top: 0; + right: 0; + z-index: -1; +} + +.blob2 { + position: absolute; + bottom: 0; + right: 0; + z-index: -1; +} + +.gift { + margin-top: 24px; +} + +.title { + margin-top: 32px; + margin-bottom: 14px; + font-size: 32px; + line-height: 26px; + font-weight: 600; + color: #275CA7; +} + +.description { + font-size: 18px; + line-height: 24px; + font-weight: 400; + color: #363636; + + &>.price { + font-weight: 600; + background: linear-gradient(90deg, #FFA1BA 0%, #9A55FF 100%); + background-clip: text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + } + + &>.discount { + text-decoration: line-through; + } +} + +.point { + width: 100%; + display: flex; + align-items: center; + justify-content: start; + gap: 8px; + font-size: 14px; + line-height: 21px; + font-weight: 600; + color: #2c2c2c; + margin-top: 6px; +} + +.button { + height: 54px; + margin-top: 16px; + font-size: 18px; + line-height: 21px; + font-weight: 600; +} \ No newline at end of file diff --git a/src/components/EmailMarketing/v1/pages/SecretDiscount/index.tsx b/src/components/EmailMarketing/v1/pages/SecretDiscount/index.tsx new file mode 100644 index 0000000..6ac9f81 --- /dev/null +++ b/src/components/EmailMarketing/v1/pages/SecretDiscount/index.tsx @@ -0,0 +1,109 @@ +import styles from "./styles.module.scss"; +import Blob3 from "../../images/SVG/Blob3"; +import Blob4 from "../../images/SVG/Blob4"; +import Title from "@/components/Title"; +import SecretDiscountTable from "../../components/SecretDiscountTable"; +import Button from "../../components/Button"; +import { usePaywall } from "@/hooks/paywall/usePaywall"; +import { EPlacementKeys } from "@/api/resources/Paywall"; +import { addCurrency, ELocalesPlacement } from "@/locales"; +import Modal from "@/components/Modal"; +import { useEffect, useState } from "react"; +import PaymentForm from "@/components/Payment/nmi/PaymentForm"; +import { useNavigate } from "react-router-dom"; +import routes from "@/routes"; +import { useDispatch } from "react-redux"; +import { actions } from "@/store"; +import { useTranslations } from "@/hooks/translations"; +import Header from "@/components/pages/ABDesign/v1/components/Header"; +import { useDynamicSize } from "@/hooks/useDynamicSize"; + +const placementKey = EPlacementKeys["aura.placement.email.compatibility.discount"] + +function SecretDiscount() { + const { width, elementRef } = useDynamicSize({ defaultWidth: 560 }); + const { height, elementRef: policyContainerRef } = useDynamicSize({ defaultWidth: 560, defaultHeight: 193 }); + const dispatch = useDispatch(); + const navigate = useNavigate(); + const { products, currency } = usePaywall({ + placementKey, + localesPlacement: ELocalesPlacement.EmailMarketingCompatibilityV1, + }); + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingCompatibilityV1); + + const activeProduct = products[0]; + const price = (activeProduct?.price || 0) / 100; + const trialDuration = activeProduct?.trialDuration || 7; + + useEffect(() => { + if (!activeProduct) return; + dispatch(actions.payment.update({ + activeProduct + })) + }, [activeProduct]) + + const [isPaymentModalOpen, setIsPaymentModalOpen] = useState(false); + + + const onPaymentSuccess = () => { + return navigate(routes.client.paymentSuccess()) + } + + const onModalClosed = () => { + setIsPaymentModalOpen(false); + } + + const onPaymentError = () => { + return navigate(routes.client.paymentFail()) + } + + const openPaymentModal = () => { + setIsPaymentModalOpen(true); + }; + + return ( +
+
+ {activeProduct && ( + + + + )} + + + {translate("secret-discount.title")} + + + + +
+

+ {translate("secret-discount.policy", { + days: trialDuration, + price: addCurrency(price, currency) + })} +

+ +
+
+ ) +} + +export default SecretDiscount \ No newline at end of file diff --git a/src/components/EmailMarketing/v1/pages/SecretDiscount/styles.module.scss b/src/components/EmailMarketing/v1/pages/SecretDiscount/styles.module.scss new file mode 100644 index 0000000..8454dba --- /dev/null +++ b/src/components/EmailMarketing/v1/pages/SecretDiscount/styles.module.scss @@ -0,0 +1,75 @@ +.container { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + padding: 20px 26px; + min-height: 100dvh; + max-width: 560px; + margin: 0 auto; + position: relative; + overflow: hidden; +} + +.header { + padding: 8px 0 30px; + + &>button { + margin-left: -12px; + } +} + +.blob3 { + position: absolute; + top: 0; + left: 0; + z-index: -1; +} + +.title { + padding: 15px 0; + background-color: #F096C4; + margin: 0; + margin-top: 32px; + line-height: 100%; + width: calc(100% + 52px); + font-size: 20px; + font-weight: 600; + color: #fff; + text-transform: uppercase; + white-space: nowrap; +} + +.button { + font-size: 18px; + font-weight: 600; + padding: 16px 0; + margin-top: 30px; +} + +.policy-container { + position: absolute; + width: calc(100%); + max-width: 560px; + height: fit-content; + bottom: 0; + left: 50%; + transform: translateX(-50%); + + &>.policy { + width: 100%; + margin: 34px 0; + padding: 0 14px; + font-size: 13px; + font-weight: 400; + line-height: 130%; + color: #fff; + } + + .blob4 { + position: absolute; + bottom: 0; + left: 0; + z-index: -1; + } +} \ No newline at end of file diff --git a/src/components/EmailMarketing/v1/pages/SpecialOffer/index.tsx b/src/components/EmailMarketing/v1/pages/SpecialOffer/index.tsx index 7c6115d..22f8cec 100644 --- a/src/components/EmailMarketing/v1/pages/SpecialOffer/index.tsx +++ b/src/components/EmailMarketing/v1/pages/SpecialOffer/index.tsx @@ -12,6 +12,8 @@ import PaymentForm from "@/components/Payment/nmi/PaymentForm"; import routes from "@/routes"; import { useNavigate } from "react-router-dom"; import BlurComponent from "@/components/BlurComponent"; +import { useTranslations } from "@/hooks/translations"; +import { addCurrency, ELocalesPlacement } from "@/locales"; const placementKey = EPlacementKeys["aura.placement.email.marketing"]; @@ -20,8 +22,9 @@ function SpecialOffer() { const navigate = useNavigate(); const [isOpenPaymentModal, setIsOpenPaymentModal] = useState(false); const activeProduct = useSelector(selectors.selectActiveProduct); + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingCompatibilityV1); - const { products, getText } = usePaywall({ + const { products, currency, getText } = usePaywall({ placementKey, }); @@ -39,6 +42,7 @@ function SpecialOffer() { const handleCloseModal = () => { setIsOpenPaymentModal(false); + return navigate(routes.client.emailMarketingV1SaveOff()) }; const onPaymentError = () => { @@ -67,14 +71,14 @@ function SpecialOffer() { )}
- Special Offer! + {translate("special-offer.title")}
- Start your {trialDuration}-day trial + {translate("special-offer.start-trial", { days: trialDuration })}

- No pressure. Cancel anytime + {translate("special-offer.cancel-anytime")}

- By continuing you agree that if you don't cancel prior to the end of the {trialDuration}-days trial, you will automatically be charged ${price} every 2 weeks until you cancel in settings. Learn more about cancellation and refund policy in Subscription terms + {translate("special-offer.policy", { + days: trialDuration, + price: addCurrency(price, currency) + })}

diff --git a/src/components/PalmistryV1/components/PalmIsReady/index.tsx b/src/components/PalmistryV1/components/PalmIsReady/index.tsx index d744f48..7d65a53 100644 --- a/src/components/PalmistryV1/components/PalmIsReady/index.tsx +++ b/src/components/PalmistryV1/components/PalmIsReady/index.tsx @@ -6,8 +6,11 @@ import { ELocalesPlacement } from "@/locales"; function PalmIsReady() { const { translate } = useTranslations(ELocalesPlacement.PalmistryV1); + return ( -
+
{translate("/trial-payment.palm_is_ready.title", { color: ( @@ -20,9 +23,6 @@ function PalmIsReady() { className={styles["girl-image"]} src={`${palmistryV1Prefix}/trial-payment/girl.png`} alt="Smile girl" - style={{ - shapeOutside: `url(${palmistryV1Prefix}/trial-payment/girl.png)`, - }} /> <p className={styles.description}> {translate("/trial-payment.palm_is_ready.description")} diff --git a/src/components/PalmistryV1/components/PalmIsReady/styles.module.scss b/src/components/PalmistryV1/components/PalmIsReady/styles.module.scss index b258da8..f7387f4 100644 --- a/src/components/PalmistryV1/components/PalmIsReady/styles.module.scss +++ b/src/components/PalmistryV1/components/PalmIsReady/styles.module.scss @@ -62,4 +62,10 @@ margin-top: 33px; margin-right: -10px; width: 191px; + shape-outside: var(--palmistry-prefix-girl-image); + -webkit-shape-outside: var(--palmistry-prefix-girl-image); + shape-image-threshold: 0; + -webkit-shape-image-threshold: 0; + shape-margin: 10px; + -webkit-shape-margin: 10px; } diff --git a/src/components/PalmistryV1/data/index.tsx b/src/components/PalmistryV1/data/index.tsx index c8620cd..d41cd2a 100644 --- a/src/components/PalmistryV1/data/index.tsx +++ b/src/components/PalmistryV1/data/index.tsx @@ -1 +1 @@ -export const answerTimeOut = 1000; +export const answerTimeOut = 600; diff --git a/src/components/PalmistryV1/pages/Birthdate/index.tsx b/src/components/PalmistryV1/pages/Birthdate/index.tsx index 3197bc7..16db291 100644 --- a/src/components/PalmistryV1/pages/Birthdate/index.tsx +++ b/src/components/PalmistryV1/pages/Birthdate/index.tsx @@ -38,12 +38,12 @@ function Birthdate() { return age; }; - const handleNext = async () => { + const handleNext = () => { const age = getAge(); metricService.userParams({ age, }); - await updateSession( + updateSession( { profile: { birthdate: `${birthdate} 00:00`, diff --git a/src/components/PalmistryV1/pages/ElementResonates/index.tsx b/src/components/PalmistryV1/pages/ElementResonates/index.tsx index f8fadb8..3f3ee23 100644 --- a/src/components/PalmistryV1/pages/ElementResonates/index.tsx +++ b/src/components/PalmistryV1/pages/ElementResonates/index.tsx @@ -61,7 +61,7 @@ function ElementResonates() { const handleClick = async (id: IAnswersSessionPalmistry["element_resonates"]) => { dispatch(actions.palmistryV1Answers.update({ elementResonates: id })); - await updateSession({ + updateSession({ answers: { element_resonates: id, }, diff --git a/src/components/PalmistryV1/pages/Email/index.tsx b/src/components/PalmistryV1/pages/Email/index.tsx index 2a4058f..0fd042b 100644 --- a/src/components/PalmistryV1/pages/Email/index.tsx +++ b/src/components/PalmistryV1/pages/Email/index.tsx @@ -74,7 +74,7 @@ function Email() { }; const authorize = async () => { - await updateSession( + updateSession( { profile: { name, diff --git a/src/components/PalmistryV1/pages/FavoriteColor/index.tsx b/src/components/PalmistryV1/pages/FavoriteColor/index.tsx index 79c0f61..07fdbaa 100644 --- a/src/components/PalmistryV1/pages/FavoriteColor/index.tsx +++ b/src/components/PalmistryV1/pages/FavoriteColor/index.tsx @@ -72,7 +72,7 @@ function FavoriteColor() { const handleClick = async (id: IAnswersSessionPalmistry["favorite_color"]) => { dispatch(actions.palmistryV1Answers.update({ favoriteColor: id })); - await updateSession({ + updateSession({ answers: { favorite_color: id, }, diff --git a/src/components/PalmistryV1/pages/GenderPalmistry/index.tsx b/src/components/PalmistryV1/pages/GenderPalmistry/index.tsx index fcf6b1c..38aa46d 100644 --- a/src/components/PalmistryV1/pages/GenderPalmistry/index.tsx +++ b/src/components/PalmistryV1/pages/GenderPalmistry/index.tsx @@ -1,6 +1,5 @@ import styles from "./styles.module.scss"; import Title from "@/components/Title"; -import ChooseGender from "@/components/pages/ABDesign/v1/components/ChooseGender"; import { useDispatch, useSelector } from "react-redux"; import { actions, selectors } from "@/store"; import { Gender } from "@/data"; @@ -19,6 +18,7 @@ import { ELottieKeys, useLottie } from "@/hooks/lottie/useLottie"; import { useSession } from "@/hooks/session/useSession"; import { EGender, ESourceAuthorization } from "@/api/resources/User"; import AlreadyHaveAccount from "@/components/ui/AlreadyHaveAccount"; +import Answer from "../../components/Answer"; function GenderPalmistry() { const { translate } = useTranslations(ELocalesPlacement.PalmistryV1); @@ -28,6 +28,8 @@ function GenderPalmistry() { const { checked: privacyPolicyChecked } = useSelector( selectors.selectPrivacyPolicy ); + console.log(privacyPolicyChecked); + const { gender } = useSelector(selectors.selectQuestionnaire); const [isSelected, setIsSelected] = useState(false); usePreloadImages(["/v1/palmistry/hand-with-eye.svg"]); @@ -35,13 +37,20 @@ function GenderPalmistry() { preloadKey: ELottieKeys.handSymbols, }); - const selectGender = async (_gender: Gender | null) => { + const localGenders = genders.map((gender) => ({ + id: gender.id, + title: translate(gender.id, undefined, ELocalesPlacement.V1), + })); + + const selectGender = (_gender: Gender | null) => { + dispatch(actions.privacyPolicy.updateChecked(true)); setIsSelected(true); dispatch(actions.questionnaire.update({ gender: _gender?.id })); }; const handleNext = useCallback(async () => { if (!gender) return; + dispatch(actions.privacyPolicy.updateChecked(true)); await sleep(1000); metricService.userParams({ gender: genders.find((g) => g.id === gender)?.name, @@ -50,7 +59,7 @@ function GenderPalmistry() { ESourceAuthorization["aura.palmistry.new"] ); if (session?.sessionId?.length) { - await updateSession( + updateSession( { profile: { gender: EGender[gender as keyof typeof EGender], @@ -76,9 +85,19 @@ function GenderPalmistry() { {translate("/gender.title")}

{translate("/gender.description")}

- + {/* */} + +
+ {localGenders.map((_gender, index) => ( + selectGender(genders.find((g) => g.id === _gender.id) ?? null)} + /> + ))} +
- {gender && !privacyPolicyChecked && ( {translate("/gender.toast", undefined, ELocalesPlacement.V1)} diff --git a/src/components/PalmistryV1/pages/GenderPalmistry/styles.module.scss b/src/components/PalmistryV1/pages/GenderPalmistry/styles.module.scss index d7f2660..92280b1 100644 --- a/src/components/PalmistryV1/pages/GenderPalmistry/styles.module.scss +++ b/src/components/PalmistryV1/pages/GenderPalmistry/styles.module.scss @@ -17,6 +17,7 @@ .privacy-policy { max-width: 316px; margin-top: 26px; + text-align: center; } .toast-container { @@ -26,3 +27,9 @@ max-width: 460px; padding: 0 24px; } + +.genders-container { + display: flex; + flex-direction: column-reverse; + width: 100%; +} diff --git a/src/components/PalmistryV1/pages/HeadOrHeart/index.tsx b/src/components/PalmistryV1/pages/HeadOrHeart/index.tsx index a180bad..30026c0 100644 --- a/src/components/PalmistryV1/pages/HeadOrHeart/index.tsx +++ b/src/components/PalmistryV1/pages/HeadOrHeart/index.tsx @@ -55,7 +55,7 @@ function HeadOrHeart() { const handleClick = async (id: IAnswersSessionPalmistry["head_or_heart"]) => { dispatch(actions.palmistryV1Answers.update({ headOrHeart: id })); - await updateSession( + updateSession( { answers: { head_or_heart: id, diff --git a/src/components/PalmistryV1/pages/RelateFollowing/index.tsx b/src/components/PalmistryV1/pages/RelateFollowing/index.tsx index 390e15a..0758c65 100644 --- a/src/components/PalmistryV1/pages/RelateFollowing/index.tsx +++ b/src/components/PalmistryV1/pages/RelateFollowing/index.tsx @@ -58,7 +58,7 @@ function RelateFollowing() { const handleClick = async (answerIndex: number) => { setActiveButton(answerIndex); - await updateSession( + updateSession( { answers: { [questions[parseInt(questionId) - 1].id]: answerIndex + 1, diff --git a/src/components/PalmistryV1/pages/RelationshipStatus/index.tsx b/src/components/PalmistryV1/pages/RelationshipStatus/index.tsx index 5a7a0cc..02bb577 100644 --- a/src/components/PalmistryV1/pages/RelationshipStatus/index.tsx +++ b/src/components/PalmistryV1/pages/RelationshipStatus/index.tsx @@ -46,7 +46,7 @@ function RelationshipStatus() { const handleClick = async (id: IAnswersSessionPalmistry["relationship_status"]) => { dispatch(actions.palmistryV1Answers.update({ relationshipStatus: id })); - await updateSession({ + updateSession({ answers: { relationship_status: id, }, diff --git a/src/components/PalmistryV1/pages/TrialPayment/styles.module.scss b/src/components/PalmistryV1/pages/TrialPayment/styles.module.scss index d801f16..2daa132 100644 --- a/src/components/PalmistryV1/pages/TrialPayment/styles.module.scss +++ b/src/components/PalmistryV1/pages/TrialPayment/styles.module.scss @@ -45,7 +45,7 @@ .paywall__get-prediction { position: fixed; - bottom: 0; + bottom: 0dvh; left: 0; align-items: center; background: #eff2fd; diff --git a/src/components/PalmistryV1/pages/WhatAspects/index.tsx b/src/components/PalmistryV1/pages/WhatAspects/index.tsx index 2161c9d..dfba1a1 100644 --- a/src/components/PalmistryV1/pages/WhatAspects/index.tsx +++ b/src/components/PalmistryV1/pages/WhatAspects/index.tsx @@ -46,7 +46,7 @@ function WhatAspects() { const handleClick = async (id: IAnswersSessionPalmistry["what_aspects"]) => { dispatch(actions.palmistryV1Answers.update({ whatAspects: id })); - await updateSession( + updateSession( { answers: { what_aspects: id, diff --git a/src/components/PalmistryV2/components/Address/index.tsx b/src/components/PalmistryV2/components/Address/index.tsx index 946aa70..dd005da 100644 --- a/src/components/PalmistryV2/components/Address/index.tsx +++ b/src/components/PalmistryV2/components/Address/index.tsx @@ -1,10 +1,16 @@ +import { useTranslations } from "@/hooks/translations"; import styles from "./styles.module.scss"; +import { ELocalesPlacement } from "@/locales"; function Address() { + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingPalmistryV2); + return (

- 2024, Wit Apps LLC,
- 2108 N ST STE 5446 SACRAMENTO, CA 95816, US + {translate("trial-payment.copyright", { + year: new Date().getFullYear(), + br: "\n", + })}

); } diff --git a/src/components/PalmistryV2/components/Address/styles.module.scss b/src/components/PalmistryV2/components/Address/styles.module.scss index af4bf2c..f9a48be 100644 --- a/src/components/PalmistryV2/components/Address/styles.module.scss +++ b/src/components/PalmistryV2/components/Address/styles.module.scss @@ -4,4 +4,5 @@ text-align: center; line-height: 16px; margin-top: 16px; + white-space: pre-line; } \ No newline at end of file diff --git a/src/components/PalmistryV2/components/DiscountExpires/index.tsx b/src/components/PalmistryV2/components/DiscountExpires/index.tsx index 94bebf5..e8f3f01 100644 --- a/src/components/PalmistryV2/components/DiscountExpires/index.tsx +++ b/src/components/PalmistryV2/components/DiscountExpires/index.tsx @@ -7,7 +7,7 @@ import { ELocalesPlacement } from "@/locales"; type TDiscountExpiresProps = HTMLAttributes; function DiscountExpires({ className = "", ...props }: TDiscountExpiresProps) { - const { translate } = useTranslations(ELocalesPlacement.V1); + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingPalmistryV2); const [currentDate, setCurrentDate] = useState(new Date()); const endDate = useMemo( () => new Date().setMinutes(currentDate.getMinutes() + 10), @@ -43,17 +43,17 @@ function DiscountExpires({ className = "", ...props }: TDiscountExpiresProps) { return (
- {translate("/trial-payment.discount_expires")} + {translate("trial-payment.discount_expires")}
{getMinutes()} - {translate("min")} + {translate("trial-payment.min")}

:

{getSeconds()} - {translate("sec")} + {translate("trial-payment.sec")}
diff --git a/src/components/PalmistryV2/components/GuardPayments/index.tsx b/src/components/PalmistryV2/components/GuardPayments/index.tsx index 01f890d..269723f 100644 --- a/src/components/PalmistryV2/components/GuardPayments/index.tsx +++ b/src/components/PalmistryV2/components/GuardPayments/index.tsx @@ -4,11 +4,11 @@ import { ELocalesPlacement } from "@/locales"; import { images } from "../../data"; function GuardPayments() { - const { translate } = useTranslations(ELocalesPlacement.V1); + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingPalmistryV2); return (
Guaranteed security -

{translate("guaranteed_security_payments")}

+

{translate("trial-payment.guaranteed_security_payments")}

); } diff --git a/src/components/PalmistryV2/components/MoneyBackGuarantee/index.tsx b/src/components/PalmistryV2/components/MoneyBackGuarantee/index.tsx index 924fd5d..6ee3c23 100644 --- a/src/components/PalmistryV2/components/MoneyBackGuarantee/index.tsx +++ b/src/components/PalmistryV2/components/MoneyBackGuarantee/index.tsx @@ -5,19 +5,15 @@ import { ELocalesPlacement } from "@/locales"; import { images } from "../../data"; function MoneyBackGuarantee() { - const { translate } = useTranslations(ELocalesPlacement.PalmistryV1); + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingPalmistryV2); return (
Money back - {translate("/trial-payment.money_back_guarantee.title")} + {translate("trial-payment.money_back_guarantee_title")}

- We are convinced that this report will provide you with a deeper - understanding of your partner and suggest ways to enhance your - relationship. With a track record of stellar customer reviews, we are - fully prepared to refund your money if you find that this report does not - deliver any value. + {translate("trial-payment.money_back_guarantee_text")}

); diff --git a/src/components/PalmistryV2/components/PalmsSayAbout/index.tsx b/src/components/PalmistryV2/components/PalmsSayAbout/index.tsx index 36586f9..e6ede1d 100644 --- a/src/components/PalmistryV2/components/PalmsSayAbout/index.tsx +++ b/src/components/PalmistryV2/components/PalmsSayAbout/index.tsx @@ -4,7 +4,7 @@ import { useTranslations } from "@/hooks/translations"; import { images } from "../../data"; function PalmsSayAbout() { - const { translate } = useTranslations(ELocalesPlacement.PalmistryV1); + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingPalmistryV2); return (
@@ -17,16 +17,13 @@ function PalmsSayAbout() {

- {/* {translate("/trial-payment.palms_say_about.point5", { + {translate("trial-payment.palms_say_about_point5", { color: ( - {translate("/trial-payment.palms_say_about.point5_color")} + {translate("trial-payment.palms_say_about_point5_color")} ), - })} */} - - {translate("/trial-payment.palms_say_about.point5_color")} - is a symbol of vitality, holds clues about your health, energy, and passion for life + })}

@@ -39,16 +36,13 @@ function PalmsSayAbout() {

- {/* {translate("/trial-payment.palms_say_about.point3", { + {translate("trial-payment.palms_say_about_point3", { color: ( - {translate("/trial-payment.palms_say_about.point3_color")} + {translate("trial-payment.palms_say_about_point3_color")} ), - })} */} - - {translate("/trial-payment.palms_say_about.point3_color")} - reflects intellectual pursuits and mental strengths + })}

@@ -61,16 +55,13 @@ function PalmsSayAbout() {

- {/* {translate("/trial-payment.palms_say_about.point7", { + {translate("trial-payment.palms_say_about_point7", { color: ( - {translate("/trial-payment.palms_say_about.point7_color")} + {translate("trial-payment.palms_say_about_point7_color")} ), - })} */} - - {translate("/trial-payment.palms_say_about.point7_color")} -  reveals insights into your financial potential and approach towards wealth + })}

@@ -83,17 +74,13 @@ function PalmsSayAbout() {

- {/* {translate("/trial-payment.palms_say_about.point1", { + {translate("trial-payment.palms_say_about_point1", { color: ( - {translate("/trial-payment.palms_say_about.point1_color")} + {translate("trial-payment.palms_say_about_point1_color")} ), - })} */} - - {translate("/trial-payment.palms_say_about.point1_color")} -   can reveal insights - into your romantic journey, mapping your heart's desires + })}

@@ -106,9 +93,7 @@ function PalmsSayAbout() {

- {/* {translate("/trial-payment.palms_say_about.point9")} */} - Each finger is a pillar of your - personality, from leadership and ambition to creativity and self- expression + {translate("trial-payment.palms_say_about_point9")}

diff --git a/src/components/PalmistryV2/components/PaymentTable/index.tsx b/src/components/PalmistryV2/components/PaymentTable/index.tsx index 01986da..dc6bea4 100644 --- a/src/components/PalmistryV2/components/PaymentTable/index.tsx +++ b/src/components/PalmistryV2/components/PaymentTable/index.tsx @@ -22,10 +22,10 @@ function PaymentTable({ placementKey, buttonClick, }: IPaymentTableProps) { - const { translate } = useTranslations(ELocalesPlacement.V1); + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingPalmistryV2); const { getText, currency } = usePaywall({ placementKey, - localesPlacement: ELocalesPlacement.V1, + localesPlacement: ELocalesPlacement.EmailMarketingPalmistryV2, }); const [isOpenPrivacyModal, setIsOpenPrivacyModal] = useState(false); const handleSubscriptionPolicyClick = (event: React.MouseEvent) => { @@ -71,18 +71,17 @@ function PaymentTable({ // backgroundColor: gender === "male" ? "#85B6FF" : "#D1ACF2", }} > - {translate("/trial-payment.payment_table.special_offer")} + {translate("trial-payment.payment_table_special_offer")}
- {/* {translate("/trial-payment.payment_table.title", { - price: <span className={styles.purple}>{getPrice(product)}</span>, - })} */} - Personalized plan for <span className={styles.blue}>{getPrice(product.trialPrice || 0)}</span> + {translate("trial-payment.payment_table_title", { + price: <span className={styles.purple}>{getPrice(product.trialPrice || 0)}</span>, + })}

- {translate("/trial-payment.payment_table.total_today")} + {translate("trial-payment.payment_table_total_today")}

{getPrice(product.trialPrice || 0)}
@@ -90,8 +89,7 @@ function PaymentTable({
{/* {product.trialPrice !== 50 && ( */}

- {/* {translate("/trial-payment.payment_table.cost")} */} - Including 1-week trial personal reading + {translate("trial-payment.payment_table_cost")}

{/* )} */} {/* {product.trialPrice === 50 && ( @@ -117,14 +115,14 @@ function PaymentTable({

- {translate("/trial-payment.subscription_policy", { + {translate("trial-payment.subscription_policy", { policyLink: ( - {translate("/trial-payment.policy_link")} + {translate("trial-payment.policy_link")} ), trialDuration: product.trialDuration, diff --git a/src/components/PalmistryV2/components/PaymentTable/styles.module.css b/src/components/PalmistryV2/components/PaymentTable/styles.module.css index 7e57951..d6970aa 100644 --- a/src/components/PalmistryV2/components/PaymentTable/styles.module.css +++ b/src/components/PalmistryV2/components/PaymentTable/styles.module.css @@ -80,6 +80,7 @@ font-size: 18px; font-weight: 600; line-height: 21px; + text-transform: uppercase; } .policy { diff --git a/src/components/PalmistryV2/components/PersonalInformation/index.tsx b/src/components/PalmistryV2/components/PersonalInformation/index.tsx index 270555a..d8e3737 100644 --- a/src/components/PalmistryV2/components/PersonalInformation/index.tsx +++ b/src/components/PalmistryV2/components/PersonalInformation/index.tsx @@ -15,7 +15,7 @@ function PersonalInformation({ gender, birthPlace, }: IPersonalInformationProps) { - const { translate } = useTranslations(ELocalesPlacement.V1); + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingPalmistryV2); return (

  • -
    {translate("/trial-payment.zodiac_sign")}
    -

    {translate(`zodiac_signs.${zodiacSign?.toLowerCase()}`)}

    +
    {translate("trial-payment.zodiac_sign")}
    +

    {translate(`trial-payment.zodiac_signs_${zodiacSign?.toLowerCase()}`)}

  • -
    {translate("gender")}
    -

    {translate(gender?.toLowerCase())}

    +
    {translate("trial-payment.gender")}
    +

    {translate(`trial-payment.${gender?.toLowerCase()}`)}

  • -
    {translate("/trial-payment.date_of_birth")}
    +
    {translate("trial-payment.date_of_birth")}

    {birthdate}

  • -
    {translate("/trial-payment.place_of_birth")}
    +
    {translate("trial-payment.place_of_birth")}

    {birthPlace}

diff --git a/src/components/PalmistryV2/components/Reviews/index.tsx b/src/components/PalmistryV2/components/Reviews/index.tsx index d74cb79..eca354a 100644 --- a/src/components/PalmistryV2/components/Reviews/index.tsx +++ b/src/components/PalmistryV2/components/Reviews/index.tsx @@ -6,29 +6,29 @@ import { useTranslations } from "@/hooks/translations"; import { ELocalesPlacement } from "@/locales"; function Reviews() { - const { translate } = useTranslations(ELocalesPlacement.PalmistryV1); + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingPalmistryV2); const reviews: IReviewProps[] = useMemo( () => [ { avatar: `${palmistryV1Prefix}/reviews/rebecca.png`, - username: translate("/trial-payment.reviews.username1"), + username: translate("trial-payment.reviews_username1"), date: "01/12/2024", gender: "female", - text: translate("/trial-payment.reviews.text1"), + text: translate("trial-payment.reviews_text1"), }, { avatar: `${palmistryV1Prefix}/reviews/mika.png`, - username: translate("/trial-payment.reviews.username2"), + username: translate("trial-payment.reviews_username2"), date: "07/12/2024", gender: "female", - text: translate("/trial-payment.reviews.text2"), + text: translate("trial-payment.reviews_text2"), }, { avatar: `${palmistryV1Prefix}/reviews/amanda.png`, - username: translate("/trial-payment.reviews.username3"), + username: translate("trial-payment.reviews_username3"), date: "16/11/2024", gender: "female", - text: translate("/trial-payment.reviews.text3"), + text: translate("trial-payment.reviews_text3"), }, ], [translate] diff --git a/src/components/PalmistryV2/components/SecretDiscountTable/index.tsx b/src/components/PalmistryV2/components/SecretDiscountTable/index.tsx index 8487059..e688d63 100644 --- a/src/components/PalmistryV2/components/SecretDiscountTable/index.tsx +++ b/src/components/PalmistryV2/components/SecretDiscountTable/index.tsx @@ -5,6 +5,7 @@ import { usePaywall } from "@/hooks/paywall/usePaywall"; import { addCurrency, ELocalesPlacement } from "@/locales"; import { EPlacementKeys } from "@/api/resources/Paywall"; import { Currency } from "@/components/PaymentTable"; +import { useTranslations } from "@/hooks/translations"; const placementKey = EPlacementKeys["aura.placement.email.palmistry.discount"] @@ -21,8 +22,9 @@ const getPrice = (price: number, currency: Currency) => { function SecretDiscountTable() { const { products, currency, getText } = usePaywall({ placementKey, - localesPlacement: ELocalesPlacement.PalmistryV1, + localesPlacement: ELocalesPlacement.EmailMarketingPalmistryV2, }); + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingPalmistryV2); const activeProduct = products[0]; const price = activeProduct?.price || 0; @@ -32,28 +34,30 @@ function SecretDiscountTable() { return (
- You get a secret discount! + {translate("secret-discount.secret-discount-table_title")} -

No pressure. Cancel anytime.

+

+ {translate("secret-discount.secret-discount-table_subtitle")} +

Gift - Secret discount applied! + {translate("secret-discount.secret-discount-table_discount-applied")} {getText("old.discount")} {getText("new.discount")}
-

Your cost per {trialDuration} days after trial:

+

{translate("secret-discount.secret-discount-table_cost-after-trial", { days: trialDuration })}

{addCurrency(Number(getText("old.price")), currency)} {getPrice(price, currency)}
-

You save {addCurrency(Number(getText("save")), currency)}

+

{translate("secret-discount.secret-discount-table_you-save", { amount: addCurrency(Number(getText("save")), currency) })}


-

Total today

+

{translate("secret-discount.secret-discount-table_total-today")}

{getPrice(trialPrice, currency)}
diff --git a/src/components/PalmistryV2/components/WithPartnerInformation/index.tsx b/src/components/PalmistryV2/components/WithPartnerInformation/index.tsx index 0f09d89..54050e6 100644 --- a/src/components/PalmistryV2/components/WithPartnerInformation/index.tsx +++ b/src/components/PalmistryV2/components/WithPartnerInformation/index.tsx @@ -25,7 +25,7 @@ function WithPartnerInformation(props: IWithPartnerInformationProps) { partnerGender, partnerBirthPlace, } = props; - const { translate } = useTranslations(ELocalesPlacement.V1); + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingPalmistryV2); return (
  • -
    {translate("/trial-payment.zodiac_sign")}
    +
    {translate("trial-payment.zodiac_sign")}

    {zodiacSign?.length - ? translate(`zodiac_signs.${zodiacSign?.toLowerCase()}`) + ? translate(`trial-payment.zodiac_signs_${zodiacSign?.toLowerCase()}`) : "-"}

  • -
    {translate("gender")}
    -

    {gender.length ? translate(gender?.toLowerCase()) : "-"}

    +
    {translate("trial-payment.gender")}
    +

    {gender.length ? translate(`trial-payment.${gender?.toLowerCase()}`) : "-"}

  • -
    {translate("/trial-payment.date_of_birth")}
    +
    {translate("trial-payment.date_of_birth")}

    {birthdate.length ? birthdate : "-"}

  • -
    {translate("/trial-payment.place_of_birth")}
    +
    {translate("trial-payment.place_of_birth")}

    {birthPlace.length ? birthPlace : "-"}

  • -
    {translate("/trial-payment.zodiac_sign")}
    +
    {translate("trial-payment.zodiac_sign")}

    {partnerZodiacSign?.length - ? translate(`zodiac_signs.${partnerZodiacSign?.toLowerCase()}`) + ? translate(`trial-payment.zodiac_signs_${partnerZodiacSign?.toLowerCase()}`) : "-"}

  • -
    {translate("gender")}
    -

    {partnerGender.length ? translate(partnerGender?.toLowerCase()) : "-"}

    +
    {translate("trial-payment.gender")}
    +

    {partnerGender.length ? translate(`trial-payment.${partnerGender?.toLowerCase()}`) : "-"}

  • -
    {translate("/trial-payment.date_of_birth")}
    +
    {translate("trial-payment.date_of_birth")}

    {partnerBirthDate.length ? partnerBirthDate : "-"}

  • -
    {translate("/trial-payment.place_of_birth")}
    +
    {translate("trial-payment.place_of_birth")}

    {partnerBirthPlace.length ? partnerBirthPlace : "-"}

diff --git a/src/components/PalmistryV2/images/SVG/Blob4/index.tsx b/src/components/PalmistryV2/images/SVG/Blob4/index.tsx index 08e3d4e..6001c5c 100644 --- a/src/components/PalmistryV2/images/SVG/Blob4/index.tsx +++ b/src/components/PalmistryV2/images/SVG/Blob4/index.tsx @@ -1,11 +1,13 @@ import { SVGProps } from "react" function Blob4(props: SVGProps) { + const width = props.width ? Number(props.width) : 419; + const height = props.height ? Number(props.height) : 193; return ( - - + + - + diff --git a/src/components/PalmistryV2/pages/SaveOff/index.tsx b/src/components/PalmistryV2/pages/SaveOff/index.tsx index 8fa9fa0..163a138 100644 --- a/src/components/PalmistryV2/pages/SaveOff/index.tsx +++ b/src/components/PalmistryV2/pages/SaveOff/index.tsx @@ -8,14 +8,16 @@ import { useNavigate } from "react-router-dom"; import routes from "@/routes"; import { usePaywall } from "@/hooks/paywall/usePaywall"; import { EPlacementKeys } from "@/api/resources/Paywall"; -import { ELocalesPlacement } from "@/locales"; +import { addCurrency, ELocalesPlacement } from "@/locales"; +import { useTranslations } from "@/hooks/translations"; const placementKey = EPlacementKeys["aura.placement.email.palmistry.discount"] function SaveOff() { - const { products, getText } = usePaywall({ + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingPalmistryV2); + const { products, currency, getText } = usePaywall({ placementKey, - localesPlacement: ELocalesPlacement.PalmistryV1, + localesPlacement: ELocalesPlacement.EmailMarketingPalmistryV2, }); const activeProduct = products[0] const price = (activeProduct?.price || 0) / 100 @@ -33,19 +35,28 @@ function SaveOff() { gift - SAVE {getText("discount")}% OFF! + {translate("save-off.title", { discount: getText("discount") })}

- ${price} instead of ${getText("full.price")} + {translate("save-off.instead", { + price: {addCurrency(price, currency)}, + oldPrice: + {translate("save-off.instead-old-price", { + oldPrice: addCurrency(getText("full.price") as string, currency) + })} + + })}

- fire {trialDuration}-day trial + fire + {translate("save-off.trial-duration", { days: trialDuration })}

- gift {getText("discount")}% off on your personalized plan + gift + {translate("save-off.discount-offer", { discount: getText("discount") })}

) diff --git a/src/components/PalmistryV2/pages/SecretDiscount/index.tsx b/src/components/PalmistryV2/pages/SecretDiscount/index.tsx index 7c0d2c8..01341dc 100644 --- a/src/components/PalmistryV2/pages/SecretDiscount/index.tsx +++ b/src/components/PalmistryV2/pages/SecretDiscount/index.tsx @@ -6,7 +6,7 @@ import SecretDiscountTable from "../../components/SecretDiscountTable"; import Button from "../../components/Button"; import { usePaywall } from "@/hooks/paywall/usePaywall"; import { EPlacementKeys } from "@/api/resources/Paywall"; -import { ELocalesPlacement } from "@/locales"; +import { addCurrency, ELocalesPlacement } from "@/locales"; import Modal from "@/components/Modal"; import { useEffect, useState } from "react"; import PaymentForm from "@/components/Payment/nmi/PaymentForm"; @@ -14,16 +14,22 @@ import { useNavigate } from "react-router-dom"; import routes from "@/routes"; import { useDispatch } from "react-redux"; import { actions } from "@/store"; +import { useTranslations } from "@/hooks/translations"; +import { useDynamicSize } from "@/hooks/useDynamicSize"; +import Header from "@/components/pages/ABDesign/v1/components/Header"; const placementKey = EPlacementKeys["aura.placement.email.palmistry.discount"] function SecretDiscount() { + const { width, elementRef } = useDynamicSize({ defaultWidth: 560 }); + const { height, elementRef: policyContainerRef } = useDynamicSize({ defaultWidth: 560, defaultHeight: 193 }); const dispatch = useDispatch(); const navigate = useNavigate(); - const { products } = usePaywall({ + const { products, currency } = usePaywall({ placementKey, - localesPlacement: ELocalesPlacement.PalmistryV1, + localesPlacement: ELocalesPlacement.EmailMarketingPalmistryV2, }); + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingPalmistryV2); const activeProduct = products[0]; const price = (activeProduct?.price || 0) / 100; @@ -56,7 +62,14 @@ function SecretDiscount() { }; return ( - <> +
+
{activeProduct && ( - You get a secret discount! + {translate("secret-discount.title")} -
+

- By continuing you agree that if you don't cancel prior to the end of the {trialDuration}-days trial, you will automatically be charged ${price} for the introductory period of 14 days thereafter the standard rate of ${price} every 14 days until you cancel in settings. Learn more about cancellation and refund policy in Subscription terms. + {translate("secret-discount.policy", { + days: trialDuration, + price: addCurrency(price, currency) + })}

- +
- +
) } diff --git a/src/components/PalmistryV2/pages/SecretDiscount/styles.module.scss b/src/components/PalmistryV2/pages/SecretDiscount/styles.module.scss index c38b907..8454dba 100644 --- a/src/components/PalmistryV2/pages/SecretDiscount/styles.module.scss +++ b/src/components/PalmistryV2/pages/SecretDiscount/styles.module.scss @@ -1,3 +1,24 @@ +.container { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + padding: 20px 26px; + min-height: 100dvh; + max-width: 560px; + margin: 0 auto; + position: relative; + overflow: hidden; +} + +.header { + padding: 8px 0 30px; + + &>button { + margin-left: -12px; + } +} + .blob3 { position: absolute; top: 0; @@ -27,10 +48,13 @@ } .policy-container { - position: relative; - width: calc(100% + 52px); + position: absolute; + width: calc(100%); + max-width: 560px; height: fit-content; - bottom: -58px; + bottom: 0; + left: 50%; + transform: translateX(-50%); &>.policy { width: 100%; diff --git a/src/components/PalmistryV2/pages/TrialPayment/index.tsx b/src/components/PalmistryV2/pages/TrialPayment/index.tsx index 48a65f5..4defacc 100644 --- a/src/components/PalmistryV2/pages/TrialPayment/index.tsx +++ b/src/components/PalmistryV2/pages/TrialPayment/index.tsx @@ -3,7 +3,7 @@ import Title from "@/components/Title"; import Button from "../../components/Button"; import routes from "@/routes"; import { useNavigate } from "react-router-dom"; -// import { useTranslations } from "@/hooks/translations"; +import { useTranslations } from "@/hooks/translations"; import { ELocalesPlacement } from "@/locales"; import { images } from "../../data"; import DiscountExpires from "../../components/DiscountExpires"; @@ -30,7 +30,7 @@ function TrialPayment() { const api = useApi(); const token = useSelector(selectors.selectToken); const dispatch = useDispatch(); - // const { translate } = useTranslations(ELocalesPlacement.PalmistryV1); + const { translate } = useTranslations(ELocalesPlacement.EmailMarketingPalmistryV2); const { products } = usePaywall({ placementKey, localesPlacement: ELocalesPlacement.PalmistryV1, @@ -107,22 +107,18 @@ function TrialPayment() {
- Transform your <br /> - life with the Power <br /> - of Palmistry — Get your - personalized plan today + {translate("trial-payment.transform_your_life")} Hand
- Personalized Palmistry <br /> - Reading is ready! + {translate("trial-payment.personalized_reading_ready")} - What your hands and fingers can reveal about you + {translate("trial-payment.hands_reveal_title")}

- Your hands and fingers are like a personal storybook, with each line - representing a chapter of your life. + {translate("trial-payment.hands_reveal_description")}

- We will prepare your - personalized plan + {translate("trial-payment.prepare_personalized_plan")} {singleOrWithPartner === "partner" && ( )} - Here are a few stories from - AURA Users + {translate("trial-payment.aura_users_stories")} - As featured in + {translate("trial-payment.as_featured_in")}
Featured diff --git a/src/components/PalmistryV2/pages/TrialPayment/styles.module.scss b/src/components/PalmistryV2/pages/TrialPayment/styles.module.scss index 2be6fd6..30d3f3a 100644 --- a/src/components/PalmistryV2/pages/TrialPayment/styles.module.scss +++ b/src/components/PalmistryV2/pages/TrialPayment/styles.module.scss @@ -24,6 +24,7 @@ text-align: left; color: #2c2c2c; max-width: 215px; + white-space: pre-line } &>img { @@ -60,6 +61,7 @@ color: #2c2c2c; margin-top: 8px; margin-bottom: 8px; + white-space: pre-line; } .title-hands { @@ -87,6 +89,7 @@ text-align: center; color: #224e90; margin-bottom: 0; + white-space: pre-line; } .title-reviews { @@ -97,6 +100,7 @@ text-align: center; color: #224e90; margin-bottom: 0; + white-space: pre-line; } .title-featured { diff --git a/src/components/Payment/nmi/PaymentForm/index.tsx b/src/components/Payment/nmi/PaymentForm/index.tsx index be3f68a..b08a634 100644 --- a/src/components/Payment/nmi/PaymentForm/index.tsx +++ b/src/components/Payment/nmi/PaymentForm/index.tsx @@ -21,6 +21,7 @@ const getPrice = (product: IPaywallProduct | null) => { } interface IPaymentFormProps { + isSinglePayment?: boolean; className?: string; placementKey: EPlacementKeys; onPaymentError?: () => void; @@ -28,7 +29,7 @@ interface IPaymentFormProps { onModalClosed?: () => void; } -function PaymentForm({ className, placementKey, onPaymentError, onPaymentSuccess, onModalClosed }: IPaymentFormProps) { +function PaymentForm({ isSinglePayment = false, className, placementKey, onPaymentError, onPaymentSuccess, onModalClosed }: IPaymentFormProps) { const { translate } = useTranslations(ELocalesPlacement.V1); const currency = useSelector(selectors.selectCurrency); const activeProduct = useSelector(selectors.selectActiveProduct); @@ -48,15 +49,15 @@ function PaymentForm({ className, placementKey, onPaymentError, onPaymentSuccess
- + {!isSinglePayment && <Title variant="h3" className={styles.title}> {translate("payment_modal.title")} - + } { }} /> - {activeProduct && ( + {!isSinglePayment && activeProduct && (

{translate("payment_modal.description", { diff --git a/src/components/pages/ABDesign/v1/components/PrivacyPolicy/index.tsx b/src/components/pages/ABDesign/v1/components/PrivacyPolicy/index.tsx index f9f9288..388458e 100644 --- a/src/components/pages/ABDesign/v1/components/PrivacyPolicy/index.tsx +++ b/src/components/pages/ABDesign/v1/components/PrivacyPolicy/index.tsx @@ -7,9 +7,10 @@ import { ELocalesPlacement } from "@/locales"; interface IPrivacyPolicyProps { containerClassName?: string; + haveCheckbox?: boolean; } -function PrivacyPolicy({ containerClassName = "" }: IPrivacyPolicyProps) { +function PrivacyPolicy({ containerClassName = "", haveCheckbox = true }: IPrivacyPolicyProps) { const dispatch = useDispatch(); const { translate } = useTranslations(ELocalesPlacement.V1); const { checked } = useSelector(selectors.selectPrivacyPolicy); @@ -20,7 +21,7 @@ function PrivacyPolicy({ containerClassName = "" }: IPrivacyPolicyProps) { return (

- + {haveCheckbox && }

{translate("policy", { privacyPolicy: ( diff --git a/src/components/pages/ABDesign/v1/pages/TrialPayment/components/Header/index.tsx b/src/components/pages/ABDesign/v1/pages/TrialPayment/components/Header/index.tsx index 1a75670..601804a 100644 --- a/src/components/pages/ABDesign/v1/pages/TrialPayment/components/Header/index.tsx +++ b/src/components/pages/ABDesign/v1/pages/TrialPayment/components/Header/index.tsx @@ -1,8 +1,6 @@ -import { useSelector } from "react-redux"; import CustomButton from "../CustomButton"; import DiscountExpires from "../DiscountExpires"; import styles from "./styles.module.css"; -import { selectors } from "@/store"; interface IHeaderProps { buttonText?: string; @@ -15,12 +13,12 @@ function Header({ buttonText = "get my reading", buttonClassName = "", }: IHeaderProps) { - const { gender } = useSelector(selectors.selectQuestionnaire); + // const { gender } = useSelector(selectors.selectQuestionnaire); return (

diff --git a/src/components/pages/ABDesign/v1/pages/TrialPayment/components/Header/styles.module.css b/src/components/pages/ABDesign/v1/pages/TrialPayment/components/Header/styles.module.css index bd059bc..adbf58f 100644 --- a/src/components/pages/ABDesign/v1/pages/TrialPayment/components/Header/styles.module.css +++ b/src/components/pages/ABDesign/v1/pages/TrialPayment/components/Header/styles.module.css @@ -3,13 +3,15 @@ top: 0; z-index: 30; height: 62px; - width: 100%; + width: calc(100% + 64px); max-width: 560px; display: flex; -webkit-box-align: center; align-items: center; justify-content: space-between; - padding: 8px 15px; + padding: 8px 47px; + background-color: transparent; + backdrop-filter: blur(5px); } .button { diff --git a/src/components/pages/Auth/index.tsx b/src/components/pages/Auth/index.tsx index 490d411..4849adf 100644 --- a/src/components/pages/Auth/index.tsx +++ b/src/components/pages/Auth/index.tsx @@ -4,7 +4,7 @@ import { useTranslations } from "@/hooks/translations"; import { ELocalesPlacement } from "@/locales"; import { useDispatch, useSelector } from "react-redux"; import { useNavigate, useParams } from "react-router-dom"; -import { useEffect, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { useDynamicSize } from "@/hooks/useDynamicSize"; import { useAuthentication } from "@/hooks/authentication/use-authentication"; import { actions, selectors } from "@/store"; @@ -32,11 +32,17 @@ interface IAuthPage { } function Auth({ redirectUrl = routes.client.home() }: IAuthPage) { + const [passwordFromQuery, emailFromQuery] = useMemo(() => { + const url = window.location.href; + const [_password, _email] = url.split("?")?.[1]?.split("password=", 2)?.[1]?.split("&email=") || ["", ""] + return [decodeURIComponent(_password), decodeURIComponent(_email)] + }, [window.location.href]); + const { translate } = useTranslations(ELocalesPlacement.V1); const dispatch = useDispatch(); const navigate = useNavigate(); - const [email, setEmail] = useState(""); - const [password, setPassword] = useState(""); + const [email, setEmail] = useState(emailFromQuery || ""); + const [password, setPassword] = useState(passwordFromQuery || ""); const [isDisabled, setIsDisabled] = useState(true); const [isValidEmail, setIsValidEmail] = useState(false); const [isValidPassword, setIsValidPassword] = useState(false); @@ -78,6 +84,16 @@ function Auth({ redirectUrl = routes.client.home() }: IAuthPage) { } }, [subPlan, products]); + useEffect(() => { + if (emailFromQuery?.length) { + setIsValidEmail(true); + } + if (passwordFromQuery?.length) { + setIsValidPassword(true); + } + }, [emailFromQuery, passwordFromQuery]); + + const handleValidEmail = (email: string) => { dispatch(actions.form.addEmail(email)); setEmail(email); diff --git a/src/hooks/authentication/use-authentication.ts b/src/hooks/authentication/use-authentication.ts index 5b5e7a7..72dd281 100644 --- a/src/hooks/authentication/use-authentication.ts +++ b/src/hooks/authentication/use-authentication.ts @@ -42,26 +42,26 @@ export const useAuthentication = () => { const birthtimeFromForm = useSelector(selectors.selectBirthtime); const birthdate = useMemo(() => { - if (birthdateFromQuestionnaire.length) { + if (birthdateFromQuestionnaire?.length) { return birthdateFromQuestionnaire; } - if (birthdateFromForm.length) { + if (birthdateFromForm?.length) { return birthdateFromForm; } }, [birthdateFromForm, birthdateFromQuestionnaire]); const birthtime = useMemo(() => { - if (birthtimeFromQuestionnaire.length) { + if (birthtimeFromQuestionnaire?.length) { return birthtimeFromQuestionnaire; } - if (birthtimeFromForm.length) { + if (birthtimeFromForm?.length) { return birthtimeFromForm; } }, [birthtimeFromForm, birthtimeFromQuestionnaire]); const partnerBirthdate = useMemo(() => { const fromQuestionnaire = `${partnerBirthdateFromQuestionnaire} ${partnerBirthtime}` - if (partnerBirthdateFromQuestionnaire.length) { + if (partnerBirthdateFromQuestionnaire?.length) { return fromQuestionnaire; } return getDateAsString(partnerBirthdateFromForm) @@ -141,14 +141,15 @@ export const useAuthentication = () => { } } const { user } = await api.getUser({ token }); + const { user: userMe } = await api.getMe({ token }); if (userId?.length) { metricService.userParams({ - email: user.email, + email: user?.email, UserID: userId }) metricService.setUserID(userId); } - signUp(token, user); + signUp(token, user, userMe); setToken(token); dispatch(actions.status.update("registred")); } catch (error: unknown) { @@ -167,16 +168,17 @@ export const useAuthentication = () => { const payload = getAuthorizationPayload(email, source); const { token, userId, generatingVideo, videoId, authCode } = await api.authorization(payload); const { user } = await api.getUser({ token }); + const { user: userMe } = await api.getMe({ token }); if (userId?.length) { dispatch(actions.userId.update({ userId })); metricService.userParams({ hasPersonalVideo: generatingVideo || false, - email: user.email, + email: user?.email, UserID: userId }) metricService.setUserID(userId); } - signUp(token, user); + signUp(token, user, userMe); setToken(token); if (authCode?.length) { dispatch(actions.userConfig.setAuthCode(authCode)); diff --git a/src/hooks/chatsSocket/useChatsSocket.ts b/src/hooks/chatsSocket/useChatsSocket.ts index 6c0a605..a4dd699 100644 --- a/src/hooks/chatsSocket/useChatsSocket.ts +++ b/src/hooks/chatsSocket/useChatsSocket.ts @@ -126,15 +126,21 @@ const useChatSocket = (userId: string, chatId: string) => { }, [chatId, fetchBalance]) const receiveMessage = useCallback((message: IMessage[]) => { - if (message[0]?.role === "user") { + if (!message?.[0]) return; + + if (message[0].role === "user") { setIsLoadingSelfMessage(false); } - if (message[0]?.role === "assistant") { + if (message[0].role === "assistant") { setIsLoadingAdvisorMessage(false); } - setMessages((prev) => [...prev, message[0]]); - - }, []) + setMessages((prev) => { + if (prev.some(msg => msg.id === message[0].id)) { + return prev; + } + return [...prev, message[0]]; + }); + }, []); const currentBalance = useCallback((balance: IResponse) => { setBalance(balance?.data); @@ -208,11 +214,11 @@ const useChatSocket = (userId: string, chatId: string) => { init(); }, [init]); - useEffect(() => { - if (!socket) return setIsAvailableChatting(false); - joinChat(chatId); - fetchBalance(chatId); - }, [chatId, fetchBalance, joinChat, socket]); + // useEffect(() => { + // if (!socket) return setIsAvailableChatting(false); + // joinChat(chatId); + // fetchBalance(chatId); + // }, [chatId, fetchBalance, joinChat, socket]); useEffect(() => { const interval = setInterval(() => { @@ -258,6 +264,28 @@ const useChatSocket = (userId: string, chatId: string) => { } }, [dispatch, session]); + useEffect(() => { + if (!socket) return; + + const handleReconnect = () => { + setIsLoadingSelfMessage(false); + setIsLoadingAdvisorMessage(false); + joinChat(chatId); + fetchBalance(chatId); + }; + + socket.on('connect', handleReconnect); + socket.on('disconnect', () => { + setIsLoadingSelfMessage(false); + setIsLoadingAdvisorMessage(false); + }); + + return () => { + socket.off('connect', handleReconnect); + socket.off('disconnect'); + }; + }, [socket, chatId, joinChat, fetchBalance]); + // clean up useEffect(() => { const handleBeforeUnload = () => { diff --git a/src/hooks/paywall/defaultPaywalls.ts b/src/hooks/paywall/defaultPaywalls.ts index 813f398..8f8f0c7 100644 --- a/src/hooks/paywall/defaultPaywalls.ts +++ b/src/hooks/paywall/defaultPaywalls.ts @@ -762,5 +762,63 @@ export const defaultPaywalls: { [key in EPlacementKeys]: IPaywall } = { "currency": "usd" } ] + }, + "aura.placement.email.compatibility.discount": { + "_id": "678ed4d62f5ba6ddbc7dd318", + "key": "aura.paywall.email.compatibility.discount", + "name": "Email Compatibility Discount", + "properties": [ + { + "key": "full.price", + "value": "45", + "_id": "678be264aaa17756a1e517df" + }, + { + "key": "discount", + "value": "70", + "_id": "" + }, + { + "key": "old.discount", + "value": "-30%", + "_id": "678d4093783493141ac1e545" + }, + { + "key": "new.discount", + "value": "-50%", + "_id": "678d4093783493141ac1e546" + }, + { + "key": "old.price", + "value": "19", + "_id": "678d4093783493141ac1e547" + }, + { + "key": "save", + "value": "30", + "_id": "678d4093783493141ac1e548" + } + ], + "products": [ + { + "_id": "66589439ef0d180993cdb72f", + "key": "compatibility.secret.discount.trial.0", + "productId": "prod_PnStTEBzrPLgvL", + "name": "Сompatibility AURA Secret Discount | Trial $0.99", + "priceId": "price_1PpFlMIlX4lgwUxrUTeWDFoI", + "type": "subscription", + "description": "Description", + "discountPrice": null, + "discountPriceId": null, + "isDiscount": false, + "isFreeTrial": false, + "isTrial": true, + "price": 900, + "trialDuration": 3, + "trialPrice": 100, + "trialPriceId": "price_1PpFoNIlX4lgwUxrP4l0lbE5", + "currency": "usd" + } + ] } } \ No newline at end of file diff --git a/src/locales/index.ts b/src/locales/index.ts index 1654092..7d5f4c5 100644 --- a/src/locales/index.ts +++ b/src/locales/index.ts @@ -5,6 +5,8 @@ import locales from './locales.ts' import { Currency } from '@/components/PaymentTable/Price.ts' import { symbolByCurrency } from './currency.ts' +// const environments = import.meta.env; + // export const getClientLocale = () => { // return navigator.language // } @@ -71,7 +73,9 @@ export enum ELocalesPlacement { PalmistryV01 = "palmistry-v0_1", PalmistryV1 = "palmistry-v1", PalmistryV11 = "palmistry-v1_1", - Chats = "chats" + Chats = "chats", + EmailMarketingCompatibilityV1 = "email-marketing-comp-v1", + EmailMarketingPalmistryV2 = "email-marketing-palmistry-v2", } interface ITranslationJSON { @@ -86,6 +90,7 @@ export type TTranslationPlacements = Partial< export const getTranslationsJSON = async (language: string): Promise => { const api = createApi(); + // const isProduction = environments.MODE === "production" && window.location.hostname !== "localhost"; let defaultLanguage = getDefaultLocaleByLanguage(language).toLowerCase(); if (defaultLanguage === "pt") { defaultLanguage = "pt-pt" @@ -94,17 +99,32 @@ export const getTranslationsJSON = async (language: string): Promise placement !== ELocalesPlacement.V0); try { - const responses = await Promise.all( - placements.map(place => - api.getLocaleTranslations({ - funnel: place, - locale: defaultLanguage - }) - ) + const responses = await Promise.allSettled( + placements.map(async place => { + try { + // return isProduction + // ? + return await api.getLocaleTranslations({ + funnel: place, + locale: defaultLanguage + }) + // : await (await fetch(`/locales/${place}/${defaultLanguage}/male_${defaultLanguage}.json`)).json() + } catch (error) { + console.error(`Ошибка загрузки переводов для ${place}:`, error); + return null; // или можно вернуть пустой объект {} + } + }) ); - const result = responses.reduce((merged, current, index) => ({ + // Фильтруем успешные результаты + const successfulResponses = responses + .filter(result => result.status === 'fulfilled') + .map(result => (result as PromiseFulfilledResult).value) + .filter(Boolean); + + const result = successfulResponses.reduce((merged, current, index) => ({ ...merged, + // [placements[index]]: isProduction ? current : { male: current } [placements[index]]: current }), {}); diff --git a/src/routerComponents/ABDesign/v1/LayoutSession/index.tsx b/src/routerComponents/ABDesign/v1/LayoutSession/index.tsx index 85b2cb7..d1a5635 100644 --- a/src/routerComponents/ABDesign/v1/LayoutSession/index.tsx +++ b/src/routerComponents/ABDesign/v1/LayoutSession/index.tsx @@ -16,7 +16,7 @@ function LayoutSession() { ); useEffect(() => { - if (flowChoice.length) { + if (flowChoice?.length) { updateSession( { profile: { @@ -31,7 +31,7 @@ function LayoutSession() { }, [flowChoice]); useEffect(() => { - if (partnerGender.length) { + if (partnerGender?.length) { updateSession( { partner: { diff --git a/src/routerComponents/MarketingLanding/v1/index.tsx b/src/routerComponents/MarketingLanding/v1/index.tsx index 95fb43e..0351eb1 100644 --- a/src/routerComponents/MarketingLanding/v1/index.tsx +++ b/src/routerComponents/MarketingLanding/v1/index.tsx @@ -4,6 +4,8 @@ import NotFoundPage from "@/components/NotFoundPage"; import MarketingLanding from "@/components/EmailMarketing/v1/pages/MarketingLanding"; import styles from "./styles.module.scss"; import SpecialOffer from "@/components/EmailMarketing/v1/pages/SpecialOffer"; +import SecretDiscount from "@/components/EmailMarketing/v1/pages/SecretDiscount"; +import SaveOff from "@/components/EmailMarketing/v1/pages/SaveOff"; const removePrefix = (path: string) => path.replace(emailMarketingV1Prefix, ""); function MarketingLandingV1Routes() { @@ -19,6 +21,14 @@ function MarketingLandingV1Routes() { path={removePrefix(routes.client.emailMarketingV1SpecialOffer())} element={} /> + } + /> + } + /> } /> diff --git a/src/routerComponents/Palmistry/v2/index.tsx b/src/routerComponents/Palmistry/v2/index.tsx index b14c601..9c4705f 100644 --- a/src/routerComponents/Palmistry/v2/index.tsx +++ b/src/routerComponents/Palmistry/v2/index.tsx @@ -13,7 +13,7 @@ const removePrefix = (path: string) => path.replace(palmistryV2Prefix, ""); function PalmistryV2Routes() { const dispatch = useDispatch(); - + useEffect(() => { dispatch(actions.palmistry.update({ fromRedesign: true })); @@ -21,6 +21,10 @@ function PalmistryV2Routes() { return ( + } + /> }> {/* } > */} - } - /> - } - /> - } - /> - {/* } + /> + } + /> + {/* } /> */} - } /> - + } /> + {/* */} ); diff --git a/src/routes.ts b/src/routes.ts index 6314047..948898c 100755 --- a/src/routes.ts +++ b/src/routes.ts @@ -196,6 +196,8 @@ const routes = { // MarketingLandingV1 emailMarketingV1Landing: () => [emailMarketingV1Prefix, "marketing-landing"].join("/"), emailMarketingV1SpecialOffer: () => [emailMarketingV1Prefix, "special-offer"].join("/"), + emailMarketingV1SaveOff: () => [emailMarketingV1Prefix, "save-off"].join("/"), + emailMarketingV1SecretDiscount: () => [emailMarketingV1Prefix, "secret-discount"].join("/"), // ABDesignV1 genderV1: () => [host, "v1", "gender"].join("/"), questionnaireV1: () => [host, "v1", "questionnaire"].join("/"), diff --git a/src/store/paywalls.ts b/src/store/paywalls.ts index 2692ab7..1933c67 100644 --- a/src/store/paywalls.ts +++ b/src/store/paywalls.ts @@ -27,6 +27,7 @@ const initialState: TPaywalls = { "aura.placement.chat": null, "aura.placement.email.palmistry": null, "aura.placement.email.palmistry.discount": null, + "aura.placement.email.compatibility.discount": null, isMustUpdate: { "aura.placement.v1.mike": true, "aura.placement.main": true, @@ -38,6 +39,7 @@ const initialState: TPaywalls = { "aura.placement.chat": true, "aura.placement.email.palmistry": true, "aura.placement.email.palmistry.discount": true, + "aura.placement.email.compatibility.discount": true, }, }