64 lines
1.7 KiB
JavaScript
64 lines
1.7 KiB
JavaScript
import React from 'react'
|
|
import PropTypes from 'prop-types'
|
|
import { motion, useReducedMotion } from 'framer-motion'
|
|
import { moveInTop, getAnimationProps } from '../atoms/Transitions'
|
|
import {
|
|
location as styleLocation,
|
|
emoji as styleEmoji,
|
|
next as styleNext
|
|
} from './Location.module.css'
|
|
import { useLocation } from '../../hooks/useLocation'
|
|
import RelativeTime from '@yaireo/relative-time'
|
|
|
|
function Flag({ countryCode }) {
|
|
if (!countryCode) return null
|
|
// offset between uppercase ascii and regional indicator symbols
|
|
const OFFSET = 127397
|
|
|
|
const emoji = countryCode.replace(/./g, (char) =>
|
|
String.fromCodePoint(char.charCodeAt(0) + OFFSET)
|
|
)
|
|
|
|
return (
|
|
<span role="img" className={styleEmoji}>
|
|
{emoji}
|
|
</span>
|
|
)
|
|
}
|
|
|
|
Flag.propTypes = {
|
|
countryCode: PropTypes.string
|
|
}
|
|
|
|
export default function Location({ hide }) {
|
|
const { now, next } = useLocation()
|
|
const shouldReduceMotion = useReducedMotion()
|
|
const isSSr = typeof window === 'undefined'
|
|
const isDifferentCountry = now?.country !== next?.country
|
|
const relativeTime = new RelativeTime({ locale: 'en' })
|
|
|
|
return !hide && now?.city ? (
|
|
<motion.aside
|
|
variants={moveInTop}
|
|
className={styleLocation}
|
|
{...getAnimationProps(shouldReduceMotion, isSSr)}
|
|
>
|
|
<Flag countryCode={now?.country_code} />
|
|
{now?.city} <span>Now</span>
|
|
<div className={styleNext}>
|
|
{next?.city && (
|
|
<>
|
|
{isDifferentCountry && <Flag countryCode={next.country_code} />}
|
|
{next.city}{' '}
|
|
<span>{relativeTime.from(new Date(next.date_start))}</span>
|
|
</>
|
|
)}
|
|
</div>
|
|
</motion.aside>
|
|
) : null
|
|
}
|
|
|
|
Location.propTypes = {
|
|
hide: PropTypes.bool
|
|
}
|