Skip to content

Commit

Permalink
Merge pull request #1041 from internxt/feat/add-lifetime-banner
Browse files Browse the repository at this point in the history
[_]: feat/add lifetime soft banner
  • Loading branch information
xabg2 authored Feb 27, 2024
2 parents 86464bf + 6944afc commit 4949f8c
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 74 deletions.
13 changes: 8 additions & 5 deletions src/app/banners/BannerWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,26 @@ import { PlanState } from '../store/slices/plan';
import { userSelectors } from '../store/slices/user';
import { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import FeaturesBanner from './FeaturesBanner';

import { UserSettings } from '@internxt/sdk/dist/shared/types/userSettings';
import Banner from './Banner';

const SHOW_BANNER_COOKIE_NAME = 'show_valentines_banner_sale';
const OFFER_OFF_DAY = new Date('2024-02-25');
const SHOW_BANNER_COOKIE_NAME = 'show_lifetime_soft_banner';
const OFFER_OFF_DAY = new Date('2024-02-29');

const BannerWrapper = (): JSX.Element => {
const [showBanner, setShowBanner] = useState(false);
const user = useSelector((state: RootState) => state.user.user) as UserSettings;
const plan = useSelector<RootState, PlanState>((state) => state.plan);
const isTutorialCompleted = localStorageService.hasCompletedTutorial(user.userId);
const userPlan = plan.subscription?.type;

const isNewUser = userPlan === 'free';
const isNewAccount = useAppSelector(userSelectors.hasSignedToday);
const isLocalStorage = localStorageService.get(SHOW_BANNER_COOKIE_NAME);
const isOfferOffDay = new Date() > OFFER_OFF_DAY;

const shouldShowBanner = userPlan === 'free' && !isLocalStorage && !isOfferOffDay;
const shouldShowBanner = isNewUser && !isLocalStorage && !isOfferOffDay;

useEffect(() => {
handleBannerDisplay();
Expand All @@ -38,7 +41,7 @@ const BannerWrapper = (): JSX.Element => {
}
}

return <FeaturesBanner showBanner={showBanner} onClose={onCloseBanner} />;
return <Banner showBanner={showBanner} onClose={onCloseBanner} />;
};

export default BannerWrapper;
68 changes: 24 additions & 44 deletions src/app/banners/FeaturesBanner.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { CheckCircle, Heart, X } from '@phosphor-icons/react';
import { CheckCircle, CircleWavyCheck, X } from '@phosphor-icons/react';
import { useTranslationContext } from 'app/i18n/provider/TranslationProvider';

const WEBSITE_URL = process.env.REACT_APP_WEBSITE_URL;

const FeaturesBanner = ({ showBanner, onClose }: { showBanner: boolean; onClose: () => void }): JSX.Element => {
const { translate } = useTranslationContext();

Expand All @@ -27,68 +25,50 @@ const FeaturesBanner = ({ showBanner, onClose }: { showBanner: boolean; onClose:
},
];

const handleOnClick = () => {
window.open(`${WEBSITE_URL}/pricing`, '_blank', 'noopener noreferrer');
};

return (
<div
className={`${showBanner ? 'flex' : 'hidden'}
fixed bottom-0 left-0 right-0 top-0 z-50 h-screen bg-black bg-opacity-50 px-10 lg:px-0`}
absolute bottom-0 left-0 right-0 top-0 z-10 bg-opacity-40`}
>
{/* Banner */}
<div
className={
'fixed left-1/2 top-1/2 flex h-auto -translate-x-[50%] -translate-y-[50%] flex-col overflow-hidden rounded-2xl border-4 border-primary/7 bg-white'
}
className={`absolute left-1/2 top-1/2 flex h-auto w-full max-w-4xl -translate-x-1/2 -translate-y-1/2 transform
flex-col overflow-hidden rounded-2xl bg-primary text-gray-100`}
>
<button className="absolute right-0 m-7 flex text-black" onClick={onClose}>
<button className="absolute right-0 m-5 flex w-auto text-white" onClick={onClose}>
<X size={32} />
</button>
<div className="flex w-auto flex-col p-14 lg:flex-row lg:p-20">
<div className="flex flex-col items-center justify-center space-y-4 text-center lg:items-start lg:justify-between lg:pr-20 lg:text-start">
<div className="flex w-max rounded-2xl bg-red-dark px-4 py-2 ring-4 ring-red">
<p className="text-2xl font-bold text-white">{translate('featuresBanner.label')}</p>
<div className="flex w-full flex-row justify-between px-20 py-16">
<div className="flex w-full flex-col items-start justify-between space-y-10">
<div className="flex w-full max-w-[297px] flex-col space-y-4">
<p className="text-3xl font-semibold text-white">{translate('featuresBanner.header')}</p>
<p className="text-5xl font-bold text-white">{translate('featuresBanner.title')}</p>
</div>
<p className="pt-5 text-5xl font-bold text-gray-100 dark:text-gray-10">
{translate('featuresBanner.title')}
</p>

<div className="flex flex-col items-center space-y-3 lg:items-start">
<div className="flex flex-col space-y-4">
<button
onClick={handleOnClick}
className="flex w-max items-center rounded-lg bg-gray-5 px-5 py-3 text-lg font-medium text-gray-80 hover:bg-gray-10"
onClick={() => {
window.open(`${process.env.REACT_APP_WEBSITE_URL}/lifetime`, '_blank', 'noopener noreferrer');
}}
className="w-max rounded-lg bg-white px-5 py-3 text-lg font-medium text-black"
>
{translate('featuresBanner.cta')}
</button>
<div className="flex flex-row items-center space-x-3 pt-2 text-gray-80 dark:text-gray-20">
<CheckCircle size={24} className="" />
<p className="whitespace-nowrap font-medium lg:text-lg">{translate('featuresBanner.guarantee')}</p>
<div className="flex flex-row items-center space-x-2">
<CheckCircle size={24} className="text-white" />
<p className="text-lg font-medium text-white">{translate('lifetimeBanner.guarantee')}</p>
</div>

<p className="text-sm font-medium text-gray-80 dark:text-gray-20">
{translate('featuresBanner.lastCta')}
</p>
</div>
</div>
<div className="hidden items-center lg:flex">
<div className="flex flex-col">
<div className="flex flex-col space-y-8">
{features.map((card) => (
<div className="flex flex-row" key={card.title}>
<Heart size={32} weight="fill" className="mr-4 text-red-dark" />
<p className="whitespace-nowrap text-xl font-semibold text-gray-80 dark:text-gray-20">
{card.title}
</p>
</div>
))}
<div className="flex h-full w-full flex-col space-y-6 text-white">
{features.map((item) => (
<div className="flex w-full flex-row items-center space-x-4" key={item.title}>
<CircleWavyCheck weight={'fill'} className="text-white" size={32} />
<p className="whitespace-nowrap text-xl font-semibold">{item.title}</p>
</div>
</div>
))}
</div>
</div>
</div>
</div>
);
};

export default FeaturesBanner;
11 changes: 5 additions & 6 deletions src/app/i18n/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@
"logOut": "Log-out"
},
"featuresBanner": {
"label": "Spare 69%",
"title": "Süße Valentinstagsgeschenke!",
"cta": "Wähle einen Plan",
"guarantee": "30 Tage Geld-zurück-Garantie",
"lastCta": "*Angebot gilt für kostenlose Konten oder neue Kunden",
"header": "Spare 70%!",
"title": "Bereiten Sie sich auf die Datenschutzwoche vor",
"cta": "Plan auswählen",
"guarantee": "30-tägige Geld-zurück-Garantie",
"features": {
"discount": "Sparen Sie bei monatlichen und jährlichen Plänen",
"safeCloud": "Sicherer und geschützter Cloud-Speicher",
"openSource": "Open Source und transparent",
"endToEnd": "Ende-zu-Ende-verschlüsselte Übertragungen",
"unauthorized": "Kein unberechtigter Zugriff",
"offerEnds": "Angebot endet am 25. Februar"
"offerEnds": "Angebot endet am 29. Februar"
}
},
"valentinesBanner": {
Expand Down
6 changes: 3 additions & 3 deletions src/app/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"logOut": "Log Out"
},
"featuresBanner": {
"label": "Save 69%",
"title": "Sweet Valentine's treats!",
"header": "Save 70%!",
"title": "Get ready for Data Privacy Week",
"cta": "Choose plan",
"guarantee": "30-day money-back guarantee",
"lastCta": "*Offer is for free accounts or new customers",
Expand All @@ -15,7 +15,7 @@
"openSource": "Open source and transparent",
"endToEnd": "End-to-end encrypted transfers",
"unauthorized": "No unauthorized access",
"offerEnds": "Offer ends February 25th"
"offerEnds": "Offer ends February 29th"
}
},
"valentinesBanner": {
Expand Down
8 changes: 4 additions & 4 deletions src/app/i18n/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@
"logOut": "Cerrar sesión"
},
"featuresBanner": {
"label": "Ahorra un 69%",
"title": "¡Dulces regalos de San Valentín!",
"header": "¡Ahorra un 70%!",
"title": "Prepárate para la Semana de la Privacidad de Datos",
"cta": "Elige un plan",
"guarantee": "Garantía de devolución de dinero de 30 días",
"guarantee": "Garantía de devolución de 30 días",
"lastCta": "*La oferta es para cuentas gratuitas o nuevos clientes",
"features": {
"discount": "Ahorra en suscripciones mensuales y anuales",
"safeCloud": "Almacenamiento seguro en la nube",
"openSource": "Código abierto y transparente",
"endToEnd": "Transferencias cifradas de extremo a extremo",
"unauthorized": "Sin acceso no autorizado",
"offerEnds": "La oferta finaliza el 25 de febrero"
"offerEnds": "La oferta finaliza el 29 de febrero"
}
},
"valentinesBanner": {
Expand Down
6 changes: 3 additions & 3 deletions src/app/i18n/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"logOut": "Déconnexion"
},
"featuresBanner": {
"label": "Économisez 69%",
"title": "Délices sucrés de la Saint-Valentin!",
"header": "Économisez 70% !",
"title": "Préparez-vous pour la Semaine de la Protection des Données",
"cta": "Choisissez un plan",
"guarantee": "Garantie de remboursement de 30 jours",
"lastCta": "*L'offre est valable pour les comptes gratuits ou les nouveaux clients",
Expand All @@ -15,7 +15,7 @@
"openSource": "Open source et transparent",
"endToEnd": "Transferts chiffrés de bout en bout",
"unauthorized": "Aucun accès non autorisé",
"offerEnds": "L'offre se termine le 25 février"
"offerEnds": "L'offre se termine le 29 février"
}
},
"valentinesBanner": {
Expand Down
6 changes: 3 additions & 3 deletions src/app/i18n/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"cta": "Get the deal"
},
"featuresBanner": {
"label": "Risparmia il 69%",
"title": "Dolci regali di San Valentino!",
"header": "Risparmia il 70%!",
"title": "Preparati per la Settimana della Privacy dei Dati",
"cta": "Scegli un piano",
"guarantee": "Garanzia di rimborso entro 30 giorni",
"lastCta": "*L'offerta è valida solo per account gratuiti o nuovi clienti",
Expand All @@ -20,7 +20,7 @@
"openSource": "Open source e trasparente",
"endToEnd": "Trasferimenti crittografati end-to-end",
"unauthorized": "Nessun accesso non autorizzato",
"offerEnds": "L'offerta termina il 25 febbraio"
"offerEnds": "L'offerta termina il 29 febbraio"
}
},
"lifetimeBanner": {
Expand Down
6 changes: 3 additions & 3 deletions src/app/i18n/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"cta": "Получить скидку"
},
"featuresBanner": {
"label": "Скидка 69%!",
"title": "Сладкие подарки к Дню св. Валентина!",
"label": "Сэкономьте 70%!",
"title": "Приготовьтесь к Неделе конфиденциальности данных",
"cta": "Выбрать план",
"guarantee": "30-дневная гарантия возврата денег",
"lastCta": "*Предложение действует только для бесплатных аккаунтов или новых клиентов",
Expand All @@ -20,7 +20,7 @@
"openSource": "Открытый исходный код и прозрачность",
"endToEnd": "Передача данных в зашифрованном виде",
"unauthorized": "Отсутствие несанкционированного доступа",
"offerEnds": "Предложение действует до 25 февраля"
"offerEnds": "Предложение действует до 29 февраля"
}
},
"lifetimeBanner": {
Expand Down
6 changes: 3 additions & 3 deletions src/app/i18n/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"logOut": "登出"
},
"featuresBanner": {
"label": "省69%",
"title": "甜蜜的情人节礼物!",
"header": "省 70%!",
"title": "为数据隐私周做好准备",
"cta": "选择计划",
"guarantee": "30 天内退款保证",
"lastCta": "*此优惠仅适用于免费账户或新客户",
Expand All @@ -15,7 +15,7 @@
"openSource": "开源和透明",
"endToEnd": "端到端加密传输",
"unauthorized": "无未经授权访问",
"offerEnds": "优惠截止日期为2月25日"
"offerEnds": "优惠截止日期为2月29日"
}
},
"valentinesBanner": {
Expand Down

0 comments on commit 4949f8c

Please sign in to comment.