diff --git a/components/Header/index.js b/components/Header/index.js index 03b31df..f9aaca0 100644 --- a/components/Header/index.js +++ b/components/Header/index.js @@ -1,16 +1,24 @@ // @flow import * as React from 'react'; import Link from 'next/link'; -import { Container, ButtonRowContainer, Label } from './style'; +import { + Container, + ButtonRowContainer, + Label, + Progression, + ProgressBar } from './style'; import { PrimaryButton, GhostButton } from '../Button'; import Logo from './Logo'; type Props = { showHeaderShadow: boolean, + displayProgress: boolean, + totalItemsCount: number, + currentCount: number, }; export default function Header(props: Props) { - const { showHeaderShadow } = props; + const { showHeaderShadow, totalItemsCount, currentCount, displayProgress } = props; return ( @@ -21,6 +29,11 @@ export default function Header(props: Props) { + + {currentCount} of {totalItemsCount} completed + + + diff --git a/components/Header/style.js b/components/Header/style.js index 4ad6b1e..33e7366 100644 --- a/components/Header/style.js +++ b/components/Header/style.js @@ -4,8 +4,8 @@ import { theme } from '../theme'; export const Container = styled.div` display: grid; - grid-template-columns: 1fr 1fr; - grid-template-areas: 'logo actions'; + grid-template-columns: 1fr 1fr 1fr; + grid-template-areas: 'logo progression actions'; padding: 16px; position: fixed; top: 0; @@ -25,7 +25,7 @@ export const Container = styled.div` @media (max-width: 968px) { padding: 8px 16px; grid-template-columns: 1fr 1fr; - grid-template-areas: 'logo actions'; + grid-template-areas: "logo actions" "progression progression"; } `; @@ -36,6 +36,34 @@ export const Logo = styled.h1` color: ${theme.text.default}; `; +export const Progression = styled.div` + grid-area: progression; + text-align: center; + + display: ${props => + props.isHidden ? 'none' : 'block'}; +`; + +export const ProgressBar = styled.div` + height: 8px; + margin: 6px 0; + position: relative; + overflow: hidden; + border-radius: 4px; + background-image: linear-gradient(to left, #a913de, #6ac9ff); + + &:after { + content: ''; + position: absolute; + height: 100%; + right: 0; + width: 100%; + background: ${theme.border.default}; + max-width: var(--progress); + transition: max-width ${theme.animations.default}; + } +`; + export const ButtonRowContainer = styled.div` display: flex; justify-content: flex-end; diff --git a/components/Page/index.js b/components/Page/index.js index c3075cc..6671845 100644 --- a/components/Page/index.js +++ b/components/Page/index.js @@ -17,18 +17,25 @@ import { ScrollToTop, } from './style'; import * as gtag from '../../lib/gtag'; +import { getLocalStorageLength } from '../../lib/localStorage'; +import data from '../../config/data'; export { SectionHeading, Heading, Subheading }; type Props = { children: Node, + displayProgress: boolean, }; +const totalItemsCount = Object.keys(data).length; + export default function Page(props: Props) { - const { children } = props; + const { children, displayProgress } = props; const [lastTrackedPageview, setLastTrackedPageview] = useState(null); const [showHeaderShadow, setHeaderShadow] = useState(false); const [scrollToTopVisible, setScrollToTopVisible] = useState(false); + const [progress, setProgress] = useState(0); + const [currentCount, setCurrentCount] = useState(0); function handleScroll() { const headerShadowState = window && window.pageYOffset > 0; @@ -39,6 +46,14 @@ export default function Page(props: Props) { const throttledScroll = throttle(300, handleScroll); + function updateProgress() { + console.log("called") + const checkedItemsCount = getLocalStorageLength(); + const progressPercentage = checkedItemsCount * 100 / totalItemsCount; + setProgress(progressPercentage); + setCurrentCount(checkedItemsCount); + }; + const scrollToTop = () => { if (window) { window.scrollTo(0, 0); @@ -46,6 +61,8 @@ export default function Page(props: Props) { }; useEffect(() => { + updateProgress(); + if (window) { window.addEventListener('scroll', throttledScroll); } @@ -56,7 +73,18 @@ export default function Page(props: Props) { setLastTrackedPageview(null); } }; - }, []); + }, [progress]); + + useEffect(() => { + if (window && displayProgress) { + window.addEventListener('storage:updated', updateProgress ); + } + return () => { + if (window && displayProgress) { + window.removeEventListener('storage:updated', updateProgress ); + } + }; + }); useEffect(() => { if (document) { @@ -71,7 +99,18 @@ export default function Page(props: Props) { return ( -
+ + +
{children}