Skip to content

Instantly share code, notes, and snippets.

@vicasas
Created May 17, 2022 00:57
Show Gist options
  • Save vicasas/46843d099969478bf9c7fe435fb76dfc to your computer and use it in GitHub Desktop.
Save vicasas/46843d099969478bf9c7fe435fb76dfc to your computer and use it in GitHub Desktop.
How to do a countdown
import { useEffect, useState } from 'react'
import Head from 'next/head'
import { Box, Typography } from '@mui/material'
const getReturnValues = (countDown: number) => {
const days = Math.floor(countDown / (1000 * 60 * 60 * 24))
const hours = Math.floor((countDown % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
const minutes = Math.floor((countDown % (1000 * 60 * 60)) / (1000 * 60))
const seconds = Math.floor((countDown % (1000 * 60)) / 1000)
return [
{ value: days, label: 'days' },
{ value: hours, label: 'hours' },
{ value: minutes, label: 'minutes' },
{ value: seconds, label: 'seconds' },
]
}
const useCountdown = (dateEnd, serverDate) => {
const [timer, setTimer] = useState(0)
useEffect(() => {
const difference = dateEnd - serverDate
setTimer(difference > 0 ? difference : 0)
}, [])
useEffect(() => {
const interval = setInterval(() => {
setTimer(timer - 1000)
}, 1000)
return () => clearInterval(interval)
}, [timer])
return getReturnValues(timer)
}
interface CounterProps {
children: React.ReactNode
}
function Counter({ children }: CounterProps) {
return <Box sx={{ display: 'flex', gap: 1 }}>{children}</Box>
}
interface CounterItemProps {
label: string
value: string
}
function CounterItem({ value, label }: CounterItemProps) {
return (
<Box
sx={{
display: 'flex',
flexDirection: 'column',
textAlign: 'center',
minWidth: 50,
}}
>
<Typography
component='span'
variant='h5'
fontWeight='bold'
sx={{ bgcolor: '#cc0077', color: '#fff', borderRadius: 1, px: 1, width: '100%' }}
>
{value}
</Typography>
<Typography
component='span'
sx={{
fontSize: (theme) => theme.typography.pxToRem(7),
textTransform: 'uppercase',
mt: 0.25,
}}
>
{label}
</Typography>
</Box>
)
}
interface CountdownProps {
dateEnd: number
serverDate: number
}
function Countdown({ dateEnd, serverDate }: CountdownProps) {
const times = useCountdown(dateEnd, serverDate)
return (
<Counter>
{times.map(({ value, label }) => (
<CounterItem key={label} value={String(value).padStart(2, '0')} label={label} />
))}
</Counter>
)
}
export default function Docs() {
const NOW_IN_MS = new Date().getTime()
return (
<div>
<Head>
<title>Create Next App</title>
<meta name='description' content='Generated by create next app' />
<link rel='icon' href='/favicon.ico' />
</Head>
<Box sx={{ display: 'flex', justifyContent: 'center', py: 2 }}>
<Countdown dateEnd={1652623260000} serverDate={NOW_IN_MS} />
</Box>
</div>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment