From 3321fdaddbffddaf6cb21f651caa7b1a57d08ceb Mon Sep 17 00:00:00 2001 From: Stanislav Holts Date: Fri, 23 Feb 2024 17:35:29 +0200 Subject: [PATCH] refactor(subscriptions): change subscriptions UX --- apps/subscription/src/components/Input.tsx | 2 +- apps/subscription/src/locales/translations.ts | 5 + .../src/renderer/+onRenderHtml.tsx | 15 -- .../src/sections/HelpIsImportant.tsx | 9 + apps/subscription/src/sections/LogoPanel.tsx | 10 +- .../src/sections/Subscriptions.tsx | 181 +++++++++++++----- 6 files changed, 160 insertions(+), 62 deletions(-) diff --git a/apps/subscription/src/components/Input.tsx b/apps/subscription/src/components/Input.tsx index 3ddd881e..fa25ca1c 100644 --- a/apps/subscription/src/components/Input.tsx +++ b/apps/subscription/src/components/Input.tsx @@ -54,7 +54,7 @@ const StyledError = styled.div` padding: 0.5rem 0; `; -const StyledContainer = styled.div` +export const StyledContainer = styled.div` margin-bottom: 4rem; padding-top: 1rem; position: relative; diff --git a/apps/subscription/src/locales/translations.ts b/apps/subscription/src/locales/translations.ts index 28980c80..4e13a343 100644 --- a/apps/subscription/src/locales/translations.ts +++ b/apps/subscription/src/locales/translations.ts @@ -109,4 +109,9 @@ export const translations: Record> = { 'uk-UA': '* ви можете відмовитись від підписки в будь який момент, натиснувши', }, 'click here': { 'uk-UA': 'СЮДИ' }, + '1 time donation': { 'uk-UA': 'Разовий донат' }, + Custom: { 'uk-UA': 'Інша сума' }, + 'per month': { 'uk-UA': '/ місяць' }, + 'Enter donation amount': { 'uk-UA': 'Введіть бажану суму' }, + 'Enter subscription amount': { 'uk-UA': 'Введіть бажану суму' }, }; diff --git a/apps/subscription/src/renderer/+onRenderHtml.tsx b/apps/subscription/src/renderer/+onRenderHtml.tsx index 5044a43d..ae4eb042 100644 --- a/apps/subscription/src/renderer/+onRenderHtml.tsx +++ b/apps/subscription/src/renderer/+onRenderHtml.tsx @@ -64,27 +64,12 @@ async function render(pageContext: PageContextServer) { ${dangerouslySkipEscape(``)} ${dangerouslySkipEscape(``)} - ${title} ${dangerouslySkipEscape(metaTags)}
${dangerouslySkipEscape(pageHtml)}
- - `; diff --git a/apps/subscription/src/sections/HelpIsImportant.tsx b/apps/subscription/src/sections/HelpIsImportant.tsx index 45377469..60cdd4f8 100644 --- a/apps/subscription/src/sections/HelpIsImportant.tsx +++ b/apps/subscription/src/sections/HelpIsImportant.tsx @@ -4,6 +4,7 @@ import ENVideo from '../../public/assets/subscription/videos/EN.mp4'; import VideoThumbnail from '../../public/assets/subscription/videos/thumb.png'; import UAVideo from '../../public/assets/subscription/videos/UA.mp4'; import { Container, H2, Item, Paragraph, Section, Video } from '../components'; +import { breakpoints } from '../helpers'; import { defaultLocale } from '../locales'; import { LocaleText } from '../renderer/LocaleText'; import { usePageContext } from '../renderer/usePageContext'; @@ -16,6 +17,14 @@ const StyledItem = styled(Item)` const StyledContainer = styled(Container)` gap: 7.6rem; + + ${Item} { + width: 100%; + + ${breakpoints.desktop} { + width: auto; + } + } `; const StyledParagraph = styled(Paragraph)` diff --git a/apps/subscription/src/sections/LogoPanel.tsx b/apps/subscription/src/sections/LogoPanel.tsx index c801267f..d7491954 100644 --- a/apps/subscription/src/sections/LogoPanel.tsx +++ b/apps/subscription/src/sections/LogoPanel.tsx @@ -61,7 +61,15 @@ const Wrapper = styled.div<{ isFixed: boolean }>` z-index: 10; flex-direction: column; width: 100%; - position: ${({ isFixed }) => (isFixed ? 'fixed' : 'relative')}; + position: relative; + + ${({ isFixed }) => + isFixed && + css` + ${breakpoints.desktop} { + position: fixed; + } + `} `; const LangNav = styled.div` diff --git a/apps/subscription/src/sections/Subscriptions.tsx b/apps/subscription/src/sections/Subscriptions.tsx index 4bd6fa10..98de4f88 100644 --- a/apps/subscription/src/sections/Subscriptions.tsx +++ b/apps/subscription/src/sections/Subscriptions.tsx @@ -1,45 +1,26 @@ import { ButtonLink, H3, Paragraph } from 'landing/src/components'; import { breakpoints } from 'landing/src/helpers'; -import { useState } from 'react'; +import { ChangeEvent, MouseEventHandler, useState } from 'react'; import styled, { css } from 'styled-components'; -import { Container, H2, Item, Section } from '../components'; -import { locales } from '../locales'; +import { Container, H2, Input, Item, Section, StyledContainer } from '../components'; +import { locales, translate } from '../locales'; import { LocaleText } from '../renderer/LocaleText'; import { usePageContext } from '../renderer/usePageContext'; +type Currency = 'usd' | 'eur' | 'uah'; + interface SubscriptionItem { - title: string; - url: string; - description?: string; + type: 'common' | 'oneTime' | 'custom'; + amount: SubscriptionItem['type'] extends 'common' ? number : null | number; + currency: Currency; } -const usdItems: SubscriptionItem[] = [ - { title: '25 USD', description: 'per month', url: '#' }, - { title: '50 USD', description: 'per month', url: '#' }, - { title: '75 USD', description: 'per month', url: '#' }, - { title: '100 USD', description: 'per month', url: '#' }, - { title: 'Custom', description: 'per month', url: '#' }, - { title: '1 time donation', url: '#' }, -]; - -const eurItems: SubscriptionItem[] = [ - { title: '25 EUR', description: 'per month', url: '#' }, - { title: '50 EUR', description: 'per month', url: '#' }, - { title: '75 EUR', description: 'per month', url: '#' }, - { title: '100 EUR', description: 'per month', url: '#' }, - { title: 'Custom', description: 'per month', url: '#' }, - { title: '1 time donation', url: '#' }, -]; - -const uahItems: SubscriptionItem[] = [ - { title: '2000 грн', description: '/ місяць', url: '#' }, - { title: '3000 грн', description: '/ місяць', url: '#' }, - { title: '4000 грн', description: '/ місяць', url: '#' }, - { title: '5000 грн', description: '/ місяць', url: '#' }, - { title: 'Інша сума', description: '/ місяць', url: '#' }, - { title: 'Разовий донат', url: '#' }, -]; +const amountItems: Record = { + usd: [25, 50, 75, 100], + eur: [25, 50, 75, 100], + uah: [2000, 3000, 4000, 5000], +}; const StyledParagraph = styled(Paragraph)` margin-bottom: 3rem; @@ -104,10 +85,6 @@ const StyledItem = styled.div<{ hasDescription: boolean }>` padding: 3rem 1.5rem; text-align: center; - ${H3} { - margin-bottom: ${({ hasDescription }) => (hasDescription ? '0' : '5rem')}; - } - ${Paragraph} { margin-bottom: 3rem; } @@ -121,6 +98,21 @@ const StyledItem = styled.div<{ hasDescription: boolean }>` ${breakpoints.desktop} { padding: 5rem 4rem; } + + label { + color: #fff; + } + + ${StyledContainer} { + margin-bottom: 2rem; + margin-top: -1rem; + } + + input { + color: #fff; + background-color: transparent; + border-bottom-color: #fff; + } `; const Note = styled(Paragraph)` @@ -132,11 +124,110 @@ const Note = styled(Paragraph)` } `; +const StyledButtonLink = styled(ButtonLink)<{ isDisabled: boolean }>` + ${({ isDisabled }) => + isDisabled && + css` + pointer-events: none; + opacity: 0.5; + `} +`; + +const SubscriptionItem = ({ type, amount, currency }: SubscriptionItem) => { + const { locale } = usePageContext(); + const [customAmount, setCustomAmount] = useState(undefined); + const [isExpanded, setIsExpanded] = useState(false); + + const description = type === 'oneTime' ? null : 'per month'; + + const isDisabled = isExpanded && type !== 'common' && !customAmount; + + const label = type === 'oneTime' ? 'Enter donation amount' : 'Enter subscription amount'; + + const getHref = () => { + const language = currency === 'uah' ? 'ua' : 'en'; + + if (type === 'common') { + return `/pay?language=${language}¤cy=${currency.toUpperCase()}&amount=${amount}&action=subscribe`; + } + + if (type === 'oneTime' && !!customAmount) { + return `/pay?language=${language}¤cy=${currency.toUpperCase()}&amount=${customAmount}&action=paydonation`; + } + + if (type === 'custom' && !!customAmount) { + return `/pay?language=${language}¤cy=${currency.toUpperCase()}&amount=${customAmount}&action=subscribe`; + } + + return '#'; + }; + + const getTitle = () => { + if (type === 'common') { + const postFix = currency === 'uah' ? 'грн' : currency; + + return `${amount} ${postFix}`.toUpperCase(); + } + + if (type === 'oneTime') { + return '1 time donation'; + } + + return 'Custom'; + }; + + const handleClick: MouseEventHandler = (e) => { + if (!isExpanded) { + e.preventDefault(); + + setIsExpanded(true); + } + }; + + return ( + +

+ {getTitle()} +

+ {!!description && ( + + {description} + + )} + {isExpanded && type !== 'common' && ( + ) => setCustomAmount(e.target.value)} + type="number" + value={customAmount} + /> + )} + + Support + +
+ ); +}; + export const Subscriptions = () => { const { locale } = usePageContext(); const [activeTab, setActiveTab] = useState<'usd' | 'eur'>('usd'); - const items = locale === locales.en ? (activeTab === 'usd' ? usdItems : eurItems) : uahItems; + const items = + locale === locales.en + ? activeTab === 'usd' + ? amountItems.usd + : amountItems.eur + : amountItems.uah; + + const currency = locale === locales.en ? activeTab : 'uah'; return (
@@ -162,17 +253,17 @@ export const Subscriptions = () => { )} - {items.map(({ title, description, url }, i) => ( + {items.map((amount, i) => ( - -

{title}

- {!!description && {description}} - - Support - -
+
))} + + + + + +