feat: add breath page
This commit is contained in:
parent
32a326c8b9
commit
cdd769ff26
46
src/components/BreathCircle/index.tsx
Normal file
46
src/components/BreathCircle/index.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import routes from '@/routes'
|
||||
import styles from './styles.module.css'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
|
||||
|
||||
function BreathCircle(): JSX.Element {
|
||||
const { t } = useTranslation()
|
||||
const navigate = useNavigate()
|
||||
const [text, setText] = useState(t(''))
|
||||
const [render, setRender] = useState(false)
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const handleNext = () => navigate(routes.client.compatibility())
|
||||
Promise.resolve()
|
||||
.then(() => {
|
||||
setText(t('breathIn'))
|
||||
return sleep(4000)
|
||||
})
|
||||
.then(() => {
|
||||
setText(t('hold'))
|
||||
return sleep(2000)
|
||||
})
|
||||
.then(() => {
|
||||
setText(t('breathOut'))
|
||||
return sleep(4000)
|
||||
})
|
||||
.then(() => {
|
||||
handleNext()
|
||||
setRender((prevState) => !prevState)
|
||||
})
|
||||
}, [t, render, navigate])
|
||||
|
||||
return (
|
||||
<div className={styles['outer-circle']}>
|
||||
<div className={styles['inner-circle']}>
|
||||
{text}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default BreathCircle
|
||||
58
src/components/BreathCircle/styles.module.css
Normal file
58
src/components/BreathCircle/styles.module.css
Normal file
@ -0,0 +1,58 @@
|
||||
.outer-circle {
|
||||
background-color: #38597f;
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
border-radius: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.inner-circle {
|
||||
position: relative;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background-color: #69a8e7;
|
||||
border-radius: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
font-weight: 500;
|
||||
font-size: 20px;
|
||||
animation-name: pulse;
|
||||
animation-duration: 10s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-timing-function: linear;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
@keyframes text {
|
||||
0% {
|
||||
content: "Breathe in";
|
||||
}
|
||||
60% {
|
||||
content: "Hold";
|
||||
}
|
||||
80% {
|
||||
content: "Breathe out";
|
||||
}
|
||||
100% {
|
||||
content: "Breathe out";
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
transform: scale(0.6);
|
||||
}
|
||||
40% {
|
||||
transform: scale(1);
|
||||
}
|
||||
60% {
|
||||
transform: scale(1);
|
||||
}
|
||||
100% {
|
||||
transform: scale(0.6);
|
||||
}
|
||||
}
|
||||
13
src/components/BreathPage/index.tsx
Normal file
13
src/components/BreathPage/index.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import styles from './styles.module.css'
|
||||
import BreathCircle from '../BreathCircle'
|
||||
|
||||
function BreathPage(): JSX.Element {
|
||||
|
||||
return (
|
||||
<section className={`${styles.page} page`}>
|
||||
<BreathCircle />
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
export default BreathPage
|
||||
11
src/components/BreathPage/styles.module.css
Normal file
11
src/components/BreathPage/styles.module.css
Normal file
@ -0,0 +1,11 @@
|
||||
.page {
|
||||
position: relative;
|
||||
height: calc(100vh - 50px);
|
||||
max-height: -webkit-fill-available;
|
||||
flex: auto;
|
||||
justify-content: center;
|
||||
display: grid;
|
||||
grid-template-rows: 1fr 96px;
|
||||
justify-items: center;
|
||||
background-color: #01010b;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user