feat: add translations to landing (#18)
This commit is contained in:
parent
425a47b33c
commit
3cdb9a997e
@ -1,4 +1,5 @@
|
|||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
import {
|
||||||
MdEco,
|
MdEco,
|
||||||
MdMiscellaneousServices,
|
MdMiscellaneousServices,
|
||||||
@ -10,33 +11,39 @@ import { CtaButton, PageSection } from '../';
|
|||||||
import { ListItem } from './ListItem';
|
import { ListItem } from './ListItem';
|
||||||
|
|
||||||
export const BenefitsSection: FC = () => {
|
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'),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageSection>
|
<PageSection>
|
||||||
<VStack w='full' spacing={2}>
|
<VStack w='full' spacing={2}>
|
||||||
<Heading as='h2'>Преимущества экологичной автомойки</Heading>
|
<Heading as='h2'>{t('heading')}</Heading>
|
||||||
<Text>
|
<Text>
|
||||||
Откройте для себя преимущества наших услуг по химчистке автомобилей
|
{t('description')}
|
||||||
</Text>
|
</Text>
|
||||||
</VStack>
|
</VStack>
|
||||||
<List display='flex' flexDirection='column' spacing={3}>
|
<List display='flex' flexDirection='column' spacing={3}>
|
||||||
{[
|
{listData.map((props, i) => (
|
||||||
{
|
|
||||||
Icon: MdEco,
|
|
||||||
children: 'Экологически безопасные продукты',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Icon: MdMiscellaneousServices,
|
|
||||||
children: 'Быстрое и эффективное обслуживание',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Icon: MdPlace,
|
|
||||||
children: 'Удобный мобильный доступ',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Icon: MdHandshake,
|
|
||||||
children: 'Надежный и заслуживающий доверия',
|
|
||||||
},
|
|
||||||
].map((props, i) => (
|
|
||||||
<ListItem key={i} {...props} />
|
<ListItem key={i} {...props} />
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
|
@ -2,7 +2,7 @@ import React, { FC, PropsWithChildren } from 'react';
|
|||||||
import { ListIcon, ListItem as ChakraListItem } from '@chakra-ui/react';
|
import { ListIcon, ListItem as ChakraListItem } from '@chakra-ui/react';
|
||||||
import { IconType } from 'react-icons';
|
import { IconType } from 'react-icons';
|
||||||
|
|
||||||
type ListItemProps = PropsWithChildren & {
|
export type ListItemProps = PropsWithChildren & {
|
||||||
Icon: IconType;
|
Icon: IconType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
export { ListItem } from './ListItem';
|
export { type ListItemProps, ListItem } from './ListItem';
|
@ -1,12 +1,20 @@
|
|||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Link as RouterLink } from 'react-router-dom';
|
import { Link as RouterLink } from 'react-router-dom';
|
||||||
import { ButtonProps, Button } from '@chakra-ui/react';
|
import { ButtonProps, Button } from '@chakra-ui/react';
|
||||||
import { URLs } from '../../../__data__/urls';
|
import { URLs } from '../../../__data__/urls';
|
||||||
|
|
||||||
export const CtaButton: FC<ButtonProps> = (props) => {
|
export const CtaButton: FC<ButtonProps> = (props) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button as={RouterLink} to={URLs.orderForm.getUrl()} colorScheme='primary' {...props}>
|
<Button
|
||||||
Сделать заказ
|
as={RouterLink}
|
||||||
|
to={URLs.orderForm.getUrl()}
|
||||||
|
colorScheme='primary'
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{t('dry-wash.landing.make-order-button')}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Text } from '@chakra-ui/react';
|
import { Text } from '@chakra-ui/react';
|
||||||
|
|
||||||
const currentYear = new Date().getFullYear();
|
const currentYear = new Date().getFullYear();
|
||||||
|
|
||||||
export const Copyright: FC = () => {
|
export const Copyright: FC = () => {
|
||||||
return <Text color='whiteAlpha.500'>© {currentYear} DryMaster. Все права защищены</Text>;
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return <Text color='whiteAlpha.500'>{t('dry-wash.landing.footer.copyright', { currentYear })}</Text>;
|
||||||
};
|
};
|
||||||
|
@ -1,20 +1,27 @@
|
|||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Link, List, ListItem } from '@chakra-ui/react';
|
import { Link, List, ListItem } from '@chakra-ui/react';
|
||||||
import { Link as RouterLink } from 'react-router-dom';
|
import { Link as RouterLink } from 'react-router-dom';
|
||||||
import { SiteLogo, PageSection } from '../';
|
import { SiteLogo, PageSection } from '../';
|
||||||
import { Copyright } from './Copyright';
|
import { Copyright } from './Copyright';
|
||||||
|
|
||||||
export const Footer: FC = () => {
|
export const Footer: FC = () => {
|
||||||
|
const { t } = useTranslation('~', {
|
||||||
|
keyPrefix: 'dry-wash.landing.footer.links',
|
||||||
|
});
|
||||||
|
|
||||||
|
const listData = [
|
||||||
|
{ to: '#', label: t('privacy-policy') },
|
||||||
|
{ to: '#', label: t('service-terms') },
|
||||||
|
{ to: '#', label: t('faq') },
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageSection as='footer' py={5} bg='gray.700' color='white'>
|
<PageSection as='footer' py={5} bg='gray.700' color='white'>
|
||||||
<SiteLogo />
|
<SiteLogo />
|
||||||
<Copyright />
|
<Copyright />
|
||||||
<List spacing={2}>
|
<List spacing={2}>
|
||||||
{[
|
{listData.map(({ to, label }, i) => (
|
||||||
{ to: '#', label: 'Политика конфиденциальности' },
|
|
||||||
{ to: '#', label: 'Условия обслуживания' },
|
|
||||||
{ to: '#', label: 'FAQ' },
|
|
||||||
].map(({ to, label }, i) => (
|
|
||||||
<ListItem key={i}>
|
<ListItem key={i}>
|
||||||
<Link as={RouterLink} to={to}>
|
<Link as={RouterLink} to={to}>
|
||||||
{label}
|
{label}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import React, { FC } from 'react';
|
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, BoxProps } from '@chakra-ui/react';
|
||||||
import { DemoVideoPosterImg } from '../../../assets/images';
|
import { DemoVideoPosterImg } from '../../../assets/images';
|
||||||
import { CtaButton, SiteLogo, PageSection } from '../';
|
import { CtaButton, SiteLogo, PageSection } from '../';
|
||||||
@ -6,6 +7,10 @@ import { CtaButton, SiteLogo, PageSection } from '../';
|
|||||||
type HeroSectionProps = Pick<BoxProps, 'flexShrink'>;
|
type HeroSectionProps = Pick<BoxProps, 'flexShrink'>;
|
||||||
|
|
||||||
export const HeroSection: FC<HeroSectionProps> = ({ flexShrink }) => {
|
export const HeroSection: FC<HeroSectionProps> = ({ flexShrink }) => {
|
||||||
|
const { t } = useTranslation('~', {
|
||||||
|
keyPrefix: 'dry-wash.landing.hero-section',
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box flexShrink={flexShrink} as='header' pos='relative' zIndex={0}>
|
<Box flexShrink={flexShrink} as='header' pos='relative' zIndex={0}>
|
||||||
<Box
|
<Box
|
||||||
@ -41,19 +46,18 @@ export const HeroSection: FC<HeroSectionProps> = ({ flexShrink }) => {
|
|||||||
color='white'
|
color='white'
|
||||||
__css={{ textWrap: 'balance' }}
|
__css={{ textWrap: 'balance' }}
|
||||||
>
|
>
|
||||||
Оживите свою поездку с помощью экологически чистого ухода!
|
{t('headline')}
|
||||||
</Heading>
|
</Heading>
|
||||||
<Text
|
<Text
|
||||||
textAlign='center'
|
textAlign='center'
|
||||||
__css={{ textWrap: 'balance' }}
|
__css={{ textWrap: 'balance' }}
|
||||||
color='white'
|
color='white'
|
||||||
>
|
>
|
||||||
Ощутите максимальное удобство сухой мойки автомобилей, созданной для
|
{t('description')}
|
||||||
того, чтобы планета стала чище
|
|
||||||
</Text>
|
</Text>
|
||||||
</VStack>
|
</VStack>
|
||||||
<CtaButton size='lg' />
|
<CtaButton size='lg' />
|
||||||
</PageSection>
|
</PageSection>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Image } from '@chakra-ui/react';
|
import { Image } from '@chakra-ui/react';
|
||||||
import { LogoSvg } from '../../../assets/icons';
|
import { LogoSvg } from '../../../assets/icons';
|
||||||
|
|
||||||
export const SiteLogo: FC = () => {
|
export const SiteLogo: FC = () => {
|
||||||
return <Image src={LogoSvg} alt='Логотип компании "Сухой мастер"' w={40} />;
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return <Image src={LogoSvg} alt={t('dry-wash.landing.site-logo')} w={40} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
// todo: add i18n for alt
|
// todo: replace Image by SVG React component
|
||||||
// todo: replace Image by SVG React component
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import React, { FC, useEffect, useState } from 'react';
|
import React, { FC, useEffect, useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
import {
|
||||||
Tab,
|
Tab,
|
||||||
TabList,
|
TabList,
|
||||||
@ -7,13 +8,17 @@ import {
|
|||||||
Tabs,
|
Tabs,
|
||||||
Text,
|
Text,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { mockReviews } from '../../../../mocks/landing';
|
import { mockReview } from '../../../../mocks/landing';
|
||||||
|
import { Review } from '../../../../models';
|
||||||
import { ReviewCard } from './ReviewCard';
|
import { ReviewCard } from './ReviewCard';
|
||||||
|
|
||||||
const reviewsCount = mockReviews.length;
|
|
||||||
const SLIDE_CHANGE_INTERVAL = 5000;
|
const SLIDE_CHANGE_INTERVAL = 5000;
|
||||||
|
|
||||||
export const ReviewsSlider: FC = () => {
|
export const ReviewsSlider: FC = () => {
|
||||||
|
const { i18n } = useTranslation();
|
||||||
|
const mockReviews: Review.View[] = mockReview.getReviewsByLocale(i18n.language);
|
||||||
|
const reviewsCount = mockReviews.length;
|
||||||
|
|
||||||
const [activeTab, setActiveTab] = useState(0);
|
const [activeTab, setActiveTab] = useState(0);
|
||||||
const [isSlideShowStopped, setIsSlideShowStopped] = useState(false);
|
const [isSlideShowStopped, setIsSlideShowStopped] = useState(false);
|
||||||
|
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import {
|
import { useTranslation } from 'react-i18next';
|
||||||
Heading,
|
import { Heading, HStack } from '@chakra-ui/react';
|
||||||
HStack,
|
|
||||||
} from '@chakra-ui/react';
|
|
||||||
import { CtaButton, PageSection } from '../';
|
import { CtaButton, PageSection } from '../';
|
||||||
import { ReviewsSlider } from './ReviewsSlider';
|
import { ReviewsSlider } from './ReviewsSlider';
|
||||||
|
|
||||||
export const SocialProofSection: FC = () => {
|
export const SocialProofSection: FC = () => {
|
||||||
|
const { t } = useTranslation('~', {
|
||||||
|
keyPrefix: 'dry-wash.landing.social-proof-section',
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageSection>
|
<PageSection>
|
||||||
<Heading as='h2'>Нас выбирают</Heading>
|
<Heading as='h2'>{t('heading')}</Heading>
|
||||||
<ReviewsSlider />
|
<ReviewsSlider />
|
||||||
<HStack w='full' justify='flex-end'>
|
<HStack w='full' justify='flex-end'>
|
||||||
<CtaButton />
|
<CtaButton />
|
||||||
|
@ -2,13 +2,13 @@ import React from 'react';
|
|||||||
import { Link as RouterLink } from 'react-router-dom';
|
import { Link as RouterLink } from 'react-router-dom';
|
||||||
import { Button } from '@chakra-ui/react';
|
import { Button } from '@chakra-ui/react';
|
||||||
import { URLs } from '../../__data__/urls';
|
import { URLs } from '../../__data__/urls';
|
||||||
import { mockOrders } from '../../mocks/landing';
|
import { mockOrder } from '../../mocks/landing';
|
||||||
|
|
||||||
const Page = () => {
|
const Page = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h1>Order form</h1>
|
<h1>Order form</h1>
|
||||||
{mockOrders.map(({ id }) => (
|
{mockOrder.orders.map(({ id }) => (
|
||||||
<Button key={id} as={RouterLink} to={URLs.orderView.getUrl(id)}>
|
<Button key={id} as={RouterLink} to={URLs.orderView.getUrl(id)}>
|
||||||
Посмотреть заказ {id}
|
Посмотреть заказ {id}
|
||||||
</Button>
|
</Button>
|
||||||
|
Loading…
Reference in New Issue
Block a user