Skip to content

Commit

Permalink
Merge pull request #1050 from internxt/feat/add-spring-banner
Browse files Browse the repository at this point in the history
[MKT-264]: feat/adding spring banner
  • Loading branch information
xabg2 authored Mar 5, 2024
2 parents 858ef89 + 7cdba85 commit 7ab019d
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 126 deletions.
8 changes: 4 additions & 4 deletions src/app/banners/BannerWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';

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

const SHOW_BANNER_COOKIE_NAME = 'show_lifetime_soft_banner';
const OFFER_OFF_DAY = new Date('2024-03-04');
const SHOW_BANNER_COOKIE_NAME = 'show_spring_banner';
const OFFER_OFF_DAY = new Date('2024-03-18');

const BannerWrapper = (): JSX.Element => {
const [showBanner, setShowBanner] = useState(false);
Expand Down Expand Up @@ -41,7 +41,7 @@ const BannerWrapper = (): JSX.Element => {
}
}

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

export default BannerWrapper;
86 changes: 41 additions & 45 deletions src/app/banners/FeaturesBanner.tsx
Original file line number Diff line number Diff line change
@@ -1,74 +1,70 @@
import { CheckCircle, CircleWavyCheck, X } from '@phosphor-icons/react';
import { CheckCircle, Flower, X } from '@phosphor-icons/react';
import { useTranslationContext } from 'app/i18n/provider/TranslationProvider';

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

const features = [
{
title: translate('featuresBanner.features.discount'),
},
{
title: translate('featuresBanner.features.safeCloud'),
},
{
title: translate('featuresBanner.features.openSource'),
},
{
title: translate('featuresBanner.features.endToEnd'),
},
{
title: translate('featuresBanner.features.unauthorized'),
},
{
title: translate('featuresBanner.features.offerEnds'),
},
];
const features = translateList('featuresBanner.features');

const handleOnClick = () => {
window.open('https://internxt.com/pricing', '_blank', 'noopener noreferrer');
};

return (
//Background
<div
className={`${showBanner ? 'flex' : 'hidden'}
absolute bottom-0 left-0 right-0 top-0 z-10 bg-opacity-40`}
fixed bottom-0 left-0 right-0 top-0 z-50 h-screen bg-black bg-opacity-50 px-10 lg:px-0`}
>
{/* Banner */}
<div
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`}
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/10 bg-white px-10'
}
>
<button className="absolute right-0 m-5 flex w-auto text-white" onClick={onClose}>
<button className="absolute right-0 m-7 flex text-black" onClick={onClose}>
<X size={32} />
</button>
<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 className="flex w-full max-w-[800px] flex-col space-x-10 py-14 lg:flex-row">
<div className="flex w-full flex-col items-center justify-center space-y-3 text-center lg:items-start lg:justify-between lg:text-start">
<div className="flex rounded-lg bg-white px-3 py-1.5 ring-4 ring-primary/7">
<p className="text-2xl font-bold text-primary">{translate('featuresBanner.label')}</p>
</div>
<div className="flex flex-col space-y-4">
<p className="w-full max-w-[380px] text-4xl font-bold leading-tight text-black">
{translate('featuresBanner.title')}
</p>

<div className="flex flex-col items-center space-y-3 lg:items-start">
<button
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"
onClick={handleOnClick}
className="flex w-max items-center rounded-lg bg-primary px-5 py-3 text-lg font-medium text-white hover:bg-primary-dark"
>
{translate('featuresBanner.cta')}
</button>
<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 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>

<p className="text-sm font-medium text-gray-50">{translate('featuresBanner.lastCta')}</p>
</div>
</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 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}>
<Flower size={30} weight="fill" className="mr-4 text-primary" />
<p className="whitespace-nowrap text-lg font-semibold text-gray-80 dark:text-gray-20">{card}</p>
</div>
))}
</div>
))}
</div>
</div>
</div>
</div>
</div>
);
};

export default FeaturesBanner;
25 changes: 13 additions & 12 deletions src/app/i18n/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@
"logOut": "Log-out"
},
"featuresBanner": {
"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 29. Februar"
}
"label": "Spare 75%",
"title": "Starten Sie Ihre digitale Frühjahrsputz",
"cta": "Wähle einen Plan",
"guarantee": "30 Tage Geld-zurück-Garantie",
"lastCta": "*Angebot gilt für kostenlose Konten oder neue Kunden",
"features": [
"Sparen Sie bei allen unseren Plänen",
"Sicherer Cloud-Speicher",
"Backup privater Dateien und Fotos",
"End-to-end verschlüsselte Übertragungen",
"Kein unbefugter Zugriff",
"Angebot endet am 18. März"
]
},
"valentinesBanner": {
"title": "Liebe ohne grenzen!",
Expand Down
20 changes: 10 additions & 10 deletions src/app/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@
"logOut": "Log Out"
},
"featuresBanner": {
"header": "Save 70%!",
"title": "Get ready for Data Privacy Week",
"label": "Save 75%",
"title": "Start your digital spring cleaning",
"cta": "Choose plan",
"guarantee": "30-day money-back guarantee",
"lastCta": "*Offer is for free accounts or new customers",
"features": {
"discount": "Save on monthly & annual plans",
"safeCloud": "Safe and secure cloud storage",
"openSource": "Open source and transparent",
"endToEnd": "End-to-end encrypted transfers",
"unauthorized": "No unauthorized access",
"offerEnds": "Offer ends February 29th"
}
"features": [
"Save on all of our plans",
"Safe and secure cloud storage",
"Open source and transparent",
"End-to-end encrypted transfers",
"No unauthorized access",
"Offer ends March 18th"
]
},
"valentinesBanner": {
"title": "Love without limits!",
Expand Down
20 changes: 10 additions & 10 deletions src/app/i18n/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@
"logOut": "Cerrar sesión"
},
"featuresBanner": {
"header": "¡Ahorra un 70%!",
"title": "Prepárate para la Semana de la Privacidad de Datos",
"label": "Ahorra un 75%",
"title": "Comienza a ahorrar esta primavera",
"cta": "Elige un plan",
"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 29 de febrero"
}
"features": [
"Ahorra en todos nuestros planes",
"Almacenamiento seguro en la nube",
"Código abierto y auditado",
"Transferencias cifradas de extremo a extremo",
"Sin accesos no autorizados",
"La oferta finaliza el 18 de marzo"
]
},
"valentinesBanner": {
"title": "¡Amor sin limites!",
Expand Down
20 changes: 10 additions & 10 deletions src/app/i18n/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@
"logOut": "Déconnexion"
},
"featuresBanner": {
"header": "Économisez 70% !",
"title": "Préparez-vous pour la Semaine de la Protection des Données",
"label": "Économisez 75%",
"title": "Profitez de votre offre de printemps",
"cta": "Choisissez un plan",
"guarantee": "Garantie de remboursement de 30 jours",
"lastCta": "*L'offre est valable pour les comptes gratuits ou les nouveaux clients",
"features": {
"discount": "Économisez sur les plans mensuels et annuels",
"safeCloud": "Stockage cloud sûr et sécurisé",
"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 29 février"
}
"features": [
"Économisez sur tous nos plans",
"Stockage cloud sûr et sécurisé",
"Open source et transparent",
"Transferts chiffrés de bout en bout",
"Aucun accès non autorisé",
"L'offre se termine le 18 mars"
]
},
"valentinesBanner": {
"title": "L'amour sans limites !",
Expand Down
20 changes: 10 additions & 10 deletions src/app/i18n/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@
"cta": "Get the deal"
},
"featuresBanner": {
"header": "Risparmia il 70%!",
"title": "Preparati per la Settimana della Privacy dei Dati",
"label": "Risparmia il 75%",
"title": "Inizia la tua pulizia digitale di primavera",
"cta": "Scegli un piano",
"guarantee": "Garanzia di rimborso entro 30 giorni",
"lastCta": "*L'offerta è valida solo per account gratuiti o nuovi clienti",
"features": {
"discount": "Risparmia su piani mensili e annuali",
"safeCloud": "Archiviazione cloud sicura e protetta",
"openSource": "Open source e trasparente",
"endToEnd": "Trasferimenti crittografati end-to-end",
"unauthorized": "Nessun accesso non autorizzato",
"offerEnds": "L'offerta termina il 29 febbraio"
}
"features": [
"Risparmia su tutti i nostri piani",
"Archiviazione cloud sicura e protetta",
"Open source e trasparente",
"Trasferimenti crittografati end-to-end",
"Nessun accesso non autorizzato",
"L'offerta termina il 18 marzo"
]
},
"lifetimeBanner": {
"label": "Cercate uno spazio sicuro per i vostri dati per tutta la vita?",
Expand Down
22 changes: 11 additions & 11 deletions src/app/i18n/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@
"cta": "Получить скидку"
},
"featuresBanner": {
"label": "Сэкономьте 70%!",
"title": "Приготовьтесь к Неделе конфиденциальности данных",
"label": "Скидка 75%",
"title": "Получите своё весеннее предложение",
"cta": "Выбрать план",
"guarantee": "30-дневная гарантия возврата денег",
"guarantee": "Гарантия возврата денег в течение 30 дней",
"lastCta": "*Предложение действует только для бесплатных аккаунтов или новых клиентов",
"features": {
"discount": "Скидка на годовые и месячные планы",
"safeCloud": "Надежное и безопасное облачное хранилище",
"openSource": "Открытый исходный код и прозрачность",
"endToEnd": "Передача данных в зашифрованном виде",
"unauthorized": "Отсутствие несанкционированного доступа",
"offerEnds": "Предложение действует до 29 февраля"
}
"features": [
"Экономьте на всех наших планах",
"Надежное и безопасное облачное хранилище",
"Открытый исходный код и прозрачность",
"Передача данных в зашифрованном виде",
"Отсутствие несанкционированного доступа",
"Предложение заканчивается 18 марта"
]
},
"lifetimeBanner": {
"label": "Ищите надежное хранилище данных на всю жизнь?",
Expand Down
24 changes: 12 additions & 12 deletions src/app/i18n/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@
"logOut": "登出"
},
"featuresBanner": {
"header": "省 70%!",
"title": "为数据隐私周做好准备",
"label": "省75%",
"title": "开始您的数字春季大扫除",
"cta": "选择计划",
"guarantee": "30 天内退款保证",
"lastCta": "*此优惠仅适用于免费账户或新客户",
"features": {
"discount": "在月度和年度计划上节省",
"safeCloud": "安全可靠的云存储",
"openSource": "开源和透明",
"endToEnd": "端到端加密传输",
"unauthorized": "无未经授权访问",
"offerEnds": "优惠截止日期为2月29日"
}
"guarantee": "30天退款保证",
"lastCta": "*优惠仅适用于免费帐户或新客户",
"features": [
"在我们所有的计划上节省",
"安全可靠的云存储",
"开源和透明",
"端到端加密传输",
"没有未经授权的访问",
"优惠截至日期为3月18日"
]
},
"valentinesBanner": {
"title": "爱无极限!",
Expand Down
8 changes: 6 additions & 2 deletions src/app/i18n/provider/TranslationProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,20 @@ import { useTranslation } from 'react-i18next';

interface TranslationContextProps {
translate: (key: string, props?: Record<string, unknown>) => string;
translateList: (key: string) => string[];
}

const TranslationContext = createContext<TranslationContextProps>({ translate: () => '' });
const TranslationContext = createContext<TranslationContextProps>({ translate: () => '', translateList: () => [] });
interface TranslationProviderProps {
children: React.ReactNode;
}

export const TranslationProvider: React.FC<TranslationProviderProps> = ({ children }) => {
const { t } = useTranslation();
const value = useMemo(() => ({ translate: t }), [t]);

const translateList = (key: string) => t(key, { returnObjects: true }) as string[];

const value = useMemo(() => ({ translate: t, translateList }), [t]);
return <TranslationContext.Provider value={value}>{children}</TranslationContext.Provider>;
};

Expand Down

0 comments on commit 7ab019d

Please sign in to comment.