From 8b554d4043752dec636f8c47dc94a5d2ab1278e8 Mon Sep 17 00:00:00 2001 From: Guilherme Popolin Date: Fri, 7 Jul 2023 10:54:09 +0200 Subject: [PATCH] feat: added TrustpilotBlock --- apps/store/src/blocks/TrustpilotBlock.tsx | 77 +++++++++++++++++++ .../TrustpilotLogo/TrustpilotLogo.tsx | 27 +++++++ .../store/src/services/storyblok/storyblok.ts | 2 + apps/store/src/utils/formatter.ts | 4 + 4 files changed, 110 insertions(+) create mode 100644 apps/store/src/blocks/TrustpilotBlock.tsx create mode 100644 apps/store/src/components/TrustpilotLogo/TrustpilotLogo.tsx diff --git a/apps/store/src/blocks/TrustpilotBlock.tsx b/apps/store/src/blocks/TrustpilotBlock.tsx new file mode 100644 index 0000000000..7a15eefe28 --- /dev/null +++ b/apps/store/src/blocks/TrustpilotBlock.tsx @@ -0,0 +1,77 @@ +import styled from '@emotion/styled' +import { storyblokEditable } from '@storyblok/react' +import { useTranslation } from 'react-i18next' +import { Text, theme, mq } from 'ui' +import { TrustpilotLogo } from '@/components/TrustpilotLogo/TrustpilotLogo' +import { SbBaseBlockProps } from '@/services/storyblok/storyblok' +import { LinkField } from '@/services/storyblok/storyblok' +import { useTrustpilotData } from '@/services/trustpilot/trustpilot' +import { useFormatter } from '@/utils/useFormatter' + +type Props = SbBaseBlockProps<{ + link: LinkField +}> + +export const TrustpilotBlock = ({ blok }: Props) => { + const { t } = useTranslation('common') + const { numberGrouping } = useFormatter() + const data = useTrustpilotData() + + if (!data) { + console.warn('[TrustpilotBlock]: No Trustpilot data found. Skip rendering.') + return null + } + + return ( + + + + {t('TRUSTPILOT_SCORE', { score: data.score })} + + + {t('TRUSTPILOT_REVIEWS_COUNT', { + numberOfReviews: numberGrouping(data.totalReviews), + })} + + + + + ) +} + +const Wrapper = styled.div({ + display: 'grid', + placeItems: 'center', + backgroundColor: theme.colors.signalGreenFill, + paddingBlock: theme.space[10], + paddingInline: theme.space.md, +}) + +const Link = styled.a({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + gap: theme.space.md, +}) + +const ScoreText = styled(Text)({ + lineHeight: '1.32', + fontSize: theme.fontSizes[11], + [mq.md]: { + // Font size this high is an edge case. That's why I'm not using Text's 'size' prop + fontSize: '12.5rem', + }, +}) + +const ReviewText = styled(Text)({ + display: 'inline-flex', + alignItems: 'center', + gap: theme.space.xxs, + + [mq.lg]: { + gap: theme.space.xs, + }, +}) + +TrustpilotBlock.blockName = 'trustpilot' diff --git a/apps/store/src/components/TrustpilotLogo/TrustpilotLogo.tsx b/apps/store/src/components/TrustpilotLogo/TrustpilotLogo.tsx new file mode 100644 index 0000000000..9b81b51092 --- /dev/null +++ b/apps/store/src/components/TrustpilotLogo/TrustpilotLogo.tsx @@ -0,0 +1,27 @@ +export type Props = { + width?: number | string + height?: number | string +} + +export const TrustpilotLogo = (props: Props) => { + return ( + + + + + + + + + + + + + ) +} diff --git a/apps/store/src/services/storyblok/storyblok.ts b/apps/store/src/services/storyblok/storyblok.ts index 0fc3e05d07..542acba777 100644 --- a/apps/store/src/services/storyblok/storyblok.ts +++ b/apps/store/src/services/storyblok/storyblok.ts @@ -63,6 +63,7 @@ import { TextContentBlock } from '@/blocks/TextContentBlock' import { TimelineBlock } from '@/blocks/TimelineBlock' import { TimelineItemBlock } from '@/blocks/TimelineItemBlock' import { TopPickCardBlock } from '@/blocks/TopPickCardBlock' +import { TrustpilotBlock } from '@/blocks/TrustpilotBlock' import { USPBlock, USPBlockItem } from '@/blocks/USPBlock' import { VideoBlock } from '@/blocks/VideoBlock' import { VideoListBlock } from '@/blocks/VideoListBlock' @@ -278,6 +279,7 @@ export const initStoryblok = () => { TextBlock, TextContentBlock, TopPickCardBlock, + TrustpilotBlock, VideoBlock, VideoListBlock, ProductNavContainerBlock, diff --git a/apps/store/src/utils/formatter.ts b/apps/store/src/utils/formatter.ts index b5d0a7d88c..a5c3a8dd77 100644 --- a/apps/store/src/utils/formatter.ts +++ b/apps/store/src/utils/formatter.ts @@ -79,6 +79,9 @@ const formatZipCode = (value: string): string => { return value.replace(/(\d{3})(\d{2})/, '$1 $2') } +const formatNumberGrouping = (value: number, locale: string) => + new Intl.NumberFormat(locale, { useGrouping: true }).format(value) + type FormatterOptions = MoneyFormatOptions & { t: TFunction } export class Formatter { @@ -100,4 +103,5 @@ export class Formatter { public ssn = formatSsn public carRegistrationNumber = formatCarRegistrationNumber public zipCode = formatZipCode + public numberGrouping = (value: number) => formatNumberGrouping(value, this.options.locale) }