diff --git a/src/components/landing/BenefitsSection/BenefitsSection.tsx b/src/components/landing/BenefitsSection/BenefitsSection.tsx index dc74dbf..3270aef 100644 --- a/src/components/landing/BenefitsSection/BenefitsSection.tsx +++ b/src/components/landing/BenefitsSection/BenefitsSection.tsx @@ -1,52 +1,29 @@ import React, { FC } from 'react'; import { useTranslation } from 'react-i18next'; -import { - MdEco, - MdMiscellaneousServices, - MdPlace, - MdHandshake, -} from 'react-icons/md'; import { Heading, HStack, List, Text, VStack } from '@chakra-ui/react'; import { CtaButton, PageSection } from '../'; import { ListItem } from './ListItem'; +import { BenefitsSectionProps } from './types'; +import { iconsMap } from './helper'; -export const BenefitsSection: FC = () => { - const { t } = useTranslation('~', { - keyPrefix: 'dry-wash.landing.benefits-section', - }); - - const listData = [ - { - Icon: MdEco, - children: t('list.0'), - }, - { - Icon: MdMiscellaneousServices, - children: t('list.1'), - }, - { - Icon: MdPlace, - children: t('list.2'), - }, - { - Icon: MdHandshake, - children: t('list.3'), - }, - ]; +export const BenefitsSection: FC = ({ + data: { heading, description, list }, +}) => { + const { t } = useTranslation('~', { keyPrefix: 'dry-wash.landing' }); return ( - {t('heading')} - - {t('description')} - + {t(heading)} + {t(description)} - {listData.map((props, i) => ( - + {list.map((itemKey, i) => ( + + {t(itemKey)} + ))} diff --git a/src/components/landing/BenefitsSection/helper.ts b/src/components/landing/BenefitsSection/helper.ts new file mode 100644 index 0000000..66bed05 --- /dev/null +++ b/src/components/landing/BenefitsSection/helper.ts @@ -0,0 +1,11 @@ +import { IconType } from "react-icons"; +import { MdEco, MdMiscellaneousServices, MdPlace, MdHandshake } from "react-icons/md"; +import { ArrElement } from "../../../lib"; +import { BenefitsList } from "./types"; + +export const iconsMap: Record, IconType> = { + "benefits-section.list.0": MdEco, + "benefits-section.list.1": MdMiscellaneousServices, + "benefits-section.list.2": MdPlace, + "benefits-section.list.3": MdHandshake, +}; \ No newline at end of file diff --git a/src/components/landing/BenefitsSection/index.ts b/src/components/landing/BenefitsSection/index.ts index d10431b..f5cfc6d 100644 --- a/src/components/landing/BenefitsSection/index.ts +++ b/src/components/landing/BenefitsSection/index.ts @@ -1 +1,2 @@ +export type { BenefitsSectionProps } from './types'; export { BenefitsSection } from './BenefitsSection'; \ No newline at end of file diff --git a/src/components/landing/BenefitsSection/types.ts b/src/components/landing/BenefitsSection/types.ts new file mode 100644 index 0000000..4099a0d --- /dev/null +++ b/src/components/landing/BenefitsSection/types.ts @@ -0,0 +1,14 @@ +export type BenefitsList = [ + 'benefits-section.list.0', + 'benefits-section.list.1', + 'benefits-section.list.2', + 'benefits-section.list.3', +]; + +export type BenefitsSectionProps = { + data: { + heading: 'benefits-section.heading'; + description: 'benefits-section.description'; + list: BenefitsList; + }; +}; \ No newline at end of file diff --git a/src/components/landing/CtaButton/CtaButton.tsx b/src/components/landing/CtaButton/CtaButton.tsx index cf5df8d..d4769e7 100644 --- a/src/components/landing/CtaButton/CtaButton.tsx +++ b/src/components/landing/CtaButton/CtaButton.tsx @@ -6,7 +6,7 @@ import { ButtonProps, Button } from '@chakra-ui/react'; import { URLs } from '../../../__data__/urls'; export const CtaButton: FC = (props) => { - const { t } = useTranslation(); + const { t } = useTranslation('~', { keyPrefix: 'dry-wash.landing' }); return ( ); }; diff --git a/src/components/landing/HeroSection/HeroSection.tsx b/src/components/landing/HeroSection/HeroSection.tsx index 9ae61c9..cf19ebb 100644 --- a/src/components/landing/HeroSection/HeroSection.tsx +++ b/src/components/landing/HeroSection/HeroSection.tsx @@ -1,22 +1,21 @@ import React, { FC } from 'react'; import { useTranslation } from 'react-i18next'; -import { Box, Heading, Text, Center, VStack, BoxProps } from '@chakra-ui/react'; - +import { Box, Heading, Text, Center, VStack } from '@chakra-ui/react'; import { DemoVideoPosterImg } from '../../../assets/images'; import { CtaButton, SiteLogo, PageSection } from '../'; +import { HeroSectionProps } from './types'; -type HeroSectionProps = Pick; - -export const HeroSection: FC = ({ flexShrink }) => { - const { t } = useTranslation('~', { - keyPrefix: 'dry-wash.landing.hero-section', - }); +export const HeroSection: FC = ({ + data: { headline, description, video }, + flexShrink, +}) => { + const { t } = useTranslation('~', { keyPrefix: 'dry-wash.landing' }); return ( = ({ flexShrink }) => { color='white' __css={{ textWrap: 'balance' }} > - {t('headline')} + {t(headline)} - {t('description')} + {t(description)} diff --git a/src/components/landing/HeroSection/types.ts b/src/components/landing/HeroSection/types.ts new file mode 100644 index 0000000..ce2eb6a --- /dev/null +++ b/src/components/landing/HeroSection/types.ts @@ -0,0 +1,9 @@ +import { BoxProps } from "@chakra-ui/react"; + +export type HeroSectionProps = { + data: { + headline: 'hero-section.headline'; + description: 'hero-section.description'; + video: string; + }; +} & Pick; \ No newline at end of file diff --git a/src/components/landing/SocialProofSection/SocialProofSection.tsx b/src/components/landing/SocialProofSection/SocialProofSection.tsx index fd49911..c424f35 100644 --- a/src/components/landing/SocialProofSection/SocialProofSection.tsx +++ b/src/components/landing/SocialProofSection/SocialProofSection.tsx @@ -5,15 +5,16 @@ import { Heading, HStack } from '@chakra-ui/react'; import { CtaButton, PageSection } from '../'; import { ReviewsSlider } from './ReviewsSlider'; +import { SocialProofSectionProps } from './types'; -export const SocialProofSection: FC = () => { - const { t } = useTranslation('~', { - keyPrefix: 'dry-wash.landing.social-proof-section', - }); +export const SocialProofSection: FC = ({ + data: { heading }, +}) => { + const { t } = useTranslation('~', { keyPrefix: 'dry-wash.landing' }); return ( - {t('heading')} + {t(heading)} diff --git a/src/components/landing/SocialProofSection/index.ts b/src/components/landing/SocialProofSection/index.ts index e20037f..2bdd48c 100644 --- a/src/components/landing/SocialProofSection/index.ts +++ b/src/components/landing/SocialProofSection/index.ts @@ -1 +1,2 @@ +export type { SocialProofSectionProps } from './types'; export { SocialProofSection } from './SocialProofSection'; \ No newline at end of file diff --git a/src/components/landing/SocialProofSection/types.ts b/src/components/landing/SocialProofSection/types.ts new file mode 100644 index 0000000..539208d --- /dev/null +++ b/src/components/landing/SocialProofSection/types.ts @@ -0,0 +1,5 @@ +export type SocialProofSectionProps = { + data: { + heading: 'social-proof-section.heading'; + }; +}; \ No newline at end of file diff --git a/src/lib/types.ts b/src/lib/types.ts index b244840..a2dbcc5 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -1,3 +1,11 @@ +/** + * @example type Output = ArrElement<['a', 'b', 'c']>; + * // "a" | "b" | "c" + */ +export type ArrElement = ArrType extends readonly (infer ElementType)[] + ? ElementType + : never; + /** * @example type Output = Split<'a.b1' | 'a.b2', '.'>; * // ["a", "b1"] | ["a", "b2"] diff --git a/src/pages/landing/index.tsx b/src/pages/landing/index.tsx index 62155e7..bab11ee 100644 --- a/src/pages/landing/index.tsx +++ b/src/pages/landing/index.tsx @@ -1,13 +1,9 @@ import React, { FC } from 'react'; import { Container, VStack } from '@chakra-ui/react'; - -import { - BenefitsSection, - Footer, - HeroSection, - SocialProofSection, -} from '../../components/landing'; +import LandingSuccess from '../../../stubs/json/landing/landing-success.json'; +import { BenefitsSection, Footer, HeroSection, SocialProofSection } from '../../components/landing'; import { LandingThemeProvider } from '../../containers'; +import { isBenefitsSectionData, isSocialProofSectionData } from './types'; const Page: FC = () => { return ( @@ -21,10 +17,19 @@ const Page: FC = () => { centerContent > - + - - + {LandingSuccess.body.sections.map(({ type, ...data }, i) => { + if (isBenefitsSectionData(type, data)) { + return ; + } + if (isSocialProofSectionData(type, data)) { + return ; + } + })}