Skip to content
Snippets Groups Projects
ChallengeView.tsx 6.43 KiB
Newer Older
  • Learn to ignore specific revisions
  • import LeftArrowIcon from 'assets/icons/ico/left-arrow.svg'
    import RightArrowIcon from 'assets/icons/ico/right-arrow.svg'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    import StyledIconButton from 'components/CommonKit/IconButton/StyledIconButton'
    
    import Content from 'components/Content/Content'
    
    import CozyBar from 'components/Header/CozyBar'
    
    import Header from 'components/Header/Header'
    
    Hugo's avatar
    Hugo committed
    import { useI18n } from 'cozy-ui/transpiled/react/I18n'
    
    import { UserChallengeState } from 'enum/userChallenge.enum'
    import { UserChallenge } from 'models'
    
    import React, { useCallback, useEffect, useState } from 'react'
    import { useSelector } from 'react-redux'
    import { AppStore } from 'store'
    import ChallengeCard from './ChallengeCard'
    import './challengeView.scss'
    
    const ChallengeView: React.FC = () => {
    
    Hugo's avatar
    Hugo committed
      const { t } = useI18n()
    
      const { userChallengeList } = useSelector(
    
        (state: AppStore) => state.ecolyo.challenge
    
      const marginPx = 16
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
      const cardWidth =
    
        window.outerWidth < 500 ? window.outerWidth - marginPx * 6 : 285
    
      const cardHeight = window.outerHeight * 0.6
    
      const [headerHeight, setHeaderHeight] = useState<number>(0)
      const [touchStart, setTouchStart] = useState<number>()
      const [touchEnd, setTouchEnd] = useState<number>()
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
      const [index, setIndex] = useState<number>(0)
      const [lastChallengeIndex, setLastChallengeIndex] = useState<number>(0)
    
      const [isLastDuelDone, setIsLastDuelDone] = useState<boolean>(false)
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
      const [containerTranslation, setContainerTranslation] =
    
        useState<number>(marginPx)
    
      const defineHeaderHeight = (height: number) => {
        setHeaderHeight(height)
      }
    
    
      const resetValues = () => {
    
        // Method used to cancel a swipe on a simple click
    
        setTouchEnd(0)
        setTouchStart(0)
      }
    
      const moveSliderRight = useCallback(() => {
    
        if (
          index < userChallengeList.length - 1 ||
          (isLastDuelDone && index < userChallengeList.length)
        ) {
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
            setContainerTranslation(
              (prev: number) => prev - cardWidth - marginPx * 1.2
    
            )
          else if (index >= 1)
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
            setContainerTranslation((prev: number) => prev - cardWidth - marginPx)
          else setContainerTranslation((prev: number) => prev - cardWidth)
          setIndex(prev => prev + 1)
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
      }, [cardWidth, index, userChallengeList.length])
    
    
      const moveSliderLeft = useCallback(() => {
    
        if (index > 0) {
          if (index >= 1)
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
            setContainerTranslation((prev: number) => prev + cardWidth + marginPx)
          else setContainerTranslation((prev: number) => prev + cardWidth)
          setIndex(prev => prev - 1)
    
        }
        if (index <= 1) {
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
          setContainerTranslation(marginPx)
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
      }, [cardWidth, index])
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
      const moveToSlide = useCallback(
        (slideIndex: number) => {
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
          setContainerTranslation(-slideIndex * (cardWidth + marginPx) + marginPx)
          setIndex(slideIndex)
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
        [cardWidth]
    
      const handleClickOrTouchEnd = () => {
    
        // if the swipe is too small and can be taken for a touch
    
        if (touchStart && touchEnd) {
          if (touchStart - touchEnd < 5 && -5 < touchStart - touchEnd) return
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
          // Change the following value in order to change the swipe sensibility
    
          if (touchStart - touchEnd > 75) {
    
            // If swipe left move slider right and add positive translation
    
            moveSliderRight()
          }
          if (touchStart - touchEnd < -75) {
    
            // If swipe right move slider left and add negative translation
    
        resetValues()
    
      useEffect(() => {
    
        userChallengeList.forEach((challenge: UserChallenge, i: number) => {
    
            challenge.state === UserChallengeState.UNLOCKED ||
    
            challenge.state === UserChallengeState.ONGOING ||
            challenge.state === UserChallengeState.DUEL
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
            setLastChallengeIndex(i)
    
            if (lastChallengeIndex === 0) return
            else if (lastChallengeIndex === 1) {
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
              setContainerTranslation(0 - cardWidth * lastChallengeIndex)
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
              setContainerTranslation(
                0 - cardWidth * lastChallengeIndex - marginPx * 1.2
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
              setLastChallengeIndex(i + 1)
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
            setIndex(i)
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
      }, [userChallengeList, lastChallengeIndex, cardWidth, isLastDuelDone])
    
    
      useEffect(() => {
        if (
          userChallengeList[userChallengeList.length - 1].state ==
          UserChallengeState.DONE
        ) {
          setIsLastDuelDone(true)
        }
      }, [userChallengeList])
    
          <CozyBar titleKey={'common.title_challenge'} />
    
          <Header
            setHeaderHeight={defineHeaderHeight}
    
    Yoan VALLET's avatar
    Yoan VALLET committed
            desktopTitleKey={'common.title_challenge'}
    
          <Content height={headerHeight}>
            <div
    
              className="challengeSlider"
    
              onClick={resetValues}
    
              onTouchStart={event => setTouchStart(event.targetTouches[0].clientX)}
              onTouchMove={event => setTouchEnd(event.targetTouches[0].clientX)}
    
              onTouchEnd={handleClickOrTouchEnd}
    
              onMouseDown={event => setTouchStart(event.clientX)}
              onMouseMove={event => setTouchEnd(event.clientX)}
    
              onMouseUp={handleClickOrTouchEnd}
    
                className="challenge-container"
    
                style={{
                  transform: `translateX(${containerTranslation}px)`,
                }}
    
                {userChallengeList.map((userChallenge, i) => (
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
                    key={userChallenge.id}
    
                    userChallenge={userChallenge}
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
                    indexSlider={index}
                    index={i}
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
                    cardWidth={cardWidth}
    
                    cardHeight={cardHeight}
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
                    moveToSlide={moveToSlide}
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
                  />
    
    
                {isLastDuelDone && (
                  <ChallengeCard
                    indexSlider={index}
                    index={5}
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
                    cardWidth={cardWidth}
    
                    cardHeight={cardHeight}
                    isChallengeCardLast={true}
                    moveToSlide={moveToSlide}
                  />
                )}
    
            <div className="sliderButtons">
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
              <StyledIconButton
    
                onClick={moveSliderLeft}
                icon={LeftArrowIcon}
    
    Hugo's avatar
    Hugo committed
                aria-label={t('challenge.accessibility.button_slider_previous')}
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
              <StyledIconButton
    
                onClick={moveSliderRight}
                icon={RightArrowIcon}
    
    Hugo's avatar
    Hugo committed
                aria-label={t('challenge.accessibility.button_slider_next')}
    
    export default ChallengeView