Answersheet to 'Componentizing the countdown block'
// store-block/react/Countdown.tsx
import React, { useState } from 'react'
import { TimeSplit } from './typings/global'
import { tick, getTwoDaysFromNow } from './utils/time'
import { useCssHandles } from 'vtex.css-handles'
interface CountdownProps {
targetDate: string
}
const DEFAULT_TARGET_DATE = getTwoDaysFromNow()
const CSS_HANDLES = ['countdown']
const Countdown: StorefrontFunctionComponent<CountdownProps> = ({
targetDate = DEFAULT_TARGET_DATE,
}) => {
const [timeRemaining, setTime] = useState<TimeSplit>({
hours: '00',
minutes: '00',
seconds: '00',
})
const handles = useCssHandles(CSS_HANDLES)
tick(targetDate, setTime)
return (
<div className={`${handles.countdown} c-muted-1 db tc`}>
<h1>{`${timeRemaining.hours}:${timeRemaining.minutes}:${timeRemaining.seconds}`}</h1>
</div>
)
}
Countdown.schema = {
title: 'editor.countdown.title',
description: 'editor.countdown.description',
type: 'object',
properties: {
title: {
title: 'I am a title',
type: 'string',
default: null,
},
targetDate: {
title: 'Final date',
description: 'Final date used in the countdown',
type: 'string',
default: null,
},
},
}
export default Countdown
// store-block/react/Title.tsx
import React from 'react'
import { FormattedMessage } from 'react-intl'
import { useCssHandles } from 'vtex.css-handles'
const CSS_HANDLES = ['title']
const Title: StorefrontFunctionComponent<TitleProps> = ({ title }) => {
const handles = useCssHandles(CSS_HANDLES)
const titleText = title || <FormattedMessage id="countdown.title" />
return (
<div className={`${handles.title} t-heading-2 fw3 w-100 c-muted-1 db tc`}>
{titleText}
</div>
)
}
interface TitleProps {
title: string
}
Title.schema = {
title: 'editor.countdown-title.title',
description: 'editor.countdown-title.description',
type: 'object',
properties: {
title: {
title: 'I am a title',
type: 'string',
default: null,
},
},
}
export default Title
// store-theme/store/blocks/home/home.jsonc
{
"store.home": {
"blocks": [
"countdown.title",
"countdown",
"list-context.image-list#demo",
"__fold__.mobile",
"flex-layout.row#deals",
"__fold__.desktop",
"rich-text#shelf-title",
"flex-layout.row#shelf",
"info-card#home",
"rich-text#question",
"rich-text#link",
"newsletter"
]
},
"shelf#home": {
"blocks": ["product-summary.shelf"]
},
"list-context.image-list#demo": {
"children": ["slider-layout#demo-images"],
"props": {
"height": 720,
"images": [
{
"image": "https://storecomponents.vteximg.com.br/arquivos/banner-principal.png",
"mobileImage": "https://storecomponents.vteximg.com.br/arquivos/banner-principal-mobile.jpg"
},
{
"image": "https://storecomponents.vteximg.com.br/arquivos/banner.jpg",
"mobileImage": "https://storecomponents.vteximg.com.br/arquivos/banner-principal-mobile.jpg"
}
]
}
},
"slider-layout#demo-images": {
"props": {
"itemsPerPage": {
"desktop": 1,
"tablet": 1,
"phone": 1
},
"infinite": true,
"showNavigationArrows": "desktopOnly",
"blockClass": "carousel"
}
},
"rich-text#shelf-title": {
"props": {
"text": "## Summer",
"blockClass": "shelfTitle"
}
},
"flex-layout.row#shelf": {
"children": ["list-context.product-list#demo1"]
},
"list-context.product-list#demo1": {
"blocks": ["product-summary.shelf"],
"children": ["slider-layout#demo-products"],
"props": {
"orderBy": "OrderByTopSaleDESC"
}
},
"slider-layout#demo-products": {
"props": {
"itemsPerPage": {
"desktop": 5,
"tablet": 3,
"phone": 1
},
"infinite": true,
"fullWidth": true,
"blockClass": "shelf"
}
},
"info-card#home": {
"props": {
"id": "info-card-home",
"isFullModeStyle": false,
"textPosition": "left",
"imageUrl": "https://storecomponents.vteximg.com.br/arquivos/banner-infocard2.png",
"headline": "Clearance Sale",
"callToActionText": "DISCOVER",
"callToActionUrl": "/sale/d",
"blockClass": "info-card-home",
"textAlignment": "center"
}
},
"rich-text#question": {
"props": {
"text": "**This is an example store built using the VTEX platform.\nWant to know more?**",
"blockClass": "question"
}
},
"rich-text#link": {
"props": {
"text": "\n**Reach us at**\nwww.vtex.com.br",
"blockClass": "link"
}
}
}
// store-block/store/interfaces.json
{
"countdown": {
"component": "Countdown"
},
"countdown.title": {
"component": "Title"
}
}
Help us make this content better!
VTEX IO courses are open source. If you see something wrong, you can open a pull request!
Make a contributionUpdated almost 4 years ago