Skip to content
Snippets Groups Projects
ChallengeCardOnGoing.tsx 9.86 KiB
Newer Older
  • Learn to ignore specific revisions
  • import { Button } from '@material-ui/core'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    import defaultChallengeIcon from 'assets/icons/visu/challenge/CHALLENGE0001.svg'
    import circleChecked from 'assets/icons/visu/challenge/circleChecked.svg'
    import circleUnchecked from 'assets/icons/visu/challenge/circleUnchecked.svg'
    import circleStar from 'assets/icons/visu/duel/circleStar.svg'
    import defaultIcon from 'assets/icons/visu/duel/default.svg'
    
    import lockedDuel from 'assets/icons/visu/duel/locked.svg'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    import classNames from 'classnames'
    import StyledIcon from 'components/CommonKit/Icon/StyledIcon'
    
    import StarsContainer from 'components/CommonKit/StarsContainer/StarsContainer'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    import Loader from 'components/Loader/Loader'
    
    import { useClient } from 'cozy-client'
    
    import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
    
    import {
      UserActionState,
      UserChallengeUpdateFlag,
      UserDuelState,
      UserExplorationState,
      UserQuizState,
    } from 'enums'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    import { UserChallenge } from 'models'
    
    import React, { useEffect, useMemo, useState } from 'react'
    
    import { useNavigate } from 'react-router-dom'
    
    import ChallengeService from 'services/challenge.service'
    
    import { updateUserChallengeList } from 'store/challenge/challenge.slice'
    
    import { useAppDispatch, useAppSelector } from 'store/hooks'
    
    import { getChallengeTitleWithLineReturn, importIconById } from 'utils/utils'
    
    import ChallengeNoFluidModal from '../ChallengeNoFluidModal/ChallengeNoFluidModal'
    
    import './challengeCardOnGoing.scss'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    const ChallengeCardOnGoing = ({
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    }: {
      userChallenge: UserChallenge
    }) => {
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
      const { t } = useI18n()
    
      const client = useClient()
    
      const navigate = useNavigate()
    
      const dispatch = useAppDispatch()
      const {
        challenge: { currentDataload },
        global: { fluidTypes, fluidStatus },
      } = useAppSelector(state => state.ecolyo)
    
      const [noFluidConnected, setNoFluidConnected] = useState<boolean>(false)
    
      const [challengeIcon, setChallengeIcon] = useState<string>(defaultIcon)
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
      const [isDone, setIsDone] = useState<boolean>(false)
    
      const [isLoading, setIsLoading] = useState<boolean>(false)
    
      const {
        progress: { actionProgress, explorationProgress, quizProgress },
        target,
        duel,
      } = userChallenge
    
      const quizFinished = userChallenge.progress.quizProgress === 5
      const explorationFinished = userChallenge.progress.explorationProgress === 5
      const actionFinished = userChallenge.progress.actionProgress === 5
    
    
      const challengeService = useMemo(() => new ChallengeService(client), [client])
    
    
      const goDuel = async () => {
    
        setIsLoading(true)
    
        // Check if at least one fluid is up
    
        if (fluidTypes.length !== 0) {
          if (userChallenge.duel.state !== UserDuelState.ONGOING) {
            const updatedChallenge = await challengeService.updateUserChallenge(
              userChallenge,
    
              UserChallengeUpdateFlag.DUEL_UPDATE_THRESHOLD,
              undefined,
              fluidStatus
    
            )
            dispatch(updateUserChallengeList(updatedChallenge))
          }
    
          setIsLoading(false)
    
          navigate(`/challenges/duel?id=${userChallenge.id}`)
    
          setIsLoading(false)
    
          setNoFluidConnected(true)
    
    Rémi PAPIN's avatar
    Rémi PAPIN committed
      const goQuiz = async () => {
    
        if (userChallenge.quiz.state !== UserQuizState.ONGOING) {
    
    Rémi PAPIN's avatar
    Rémi PAPIN committed
          const updatedChallenge = await challengeService.updateUserChallenge(
            userChallenge,
    
            UserChallengeUpdateFlag.QUIZ_RESET
    
    Rémi PAPIN's avatar
    Rémi PAPIN committed
          )
          dispatch(updateUserChallengeList(updatedChallenge))
        }
    
        if (userChallenge.progress.quizProgress !== 5) navigate('/challenges/quiz')
    
    Rémi PAPIN's avatar
    Rémi PAPIN committed
      }
    
    Rémi PAPIN's avatar
    Rémi PAPIN committed
      const goExploration = () => {
    
    Rémi PAPIN's avatar
    Rémi PAPIN committed
        if (userChallenge.progress.explorationProgress !== 5)
    
          navigate('/challenges/exploration')
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
      const goAction = () => {
        if (userChallenge.progress.actionProgress !== 5)
    
          navigate('/challenges/action')
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
      }
    
      useEffect(() => {
    
        let subscribed = true
    
        function importIcon() {
    
          importIconById(userChallenge.id, 'challenge').then(icon => {
    
            icon ? setChallengeIcon(icon) : setChallengeIcon(defaultChallengeIcon)
    
        subscribed && importIcon()
    
        return () => {
          subscribed = false
        }
    
      }, [userChallenge])
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
      useEffect(() => {
        let subscribed = true
    
        function setChallengeResult() {
    
          const isChallengeDone = challengeService.isChallengeDone(
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
            userChallenge,
            currentDataload
          )
    
          setIsDone(isChallengeDone.isDone)
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
        }
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
        const unlockDuel = async () => {
          if (
            userChallenge.duel.state === UserDuelState.LOCKED &&
            userChallenge.progress.actionProgress === 5 &&
            userChallenge.progress.quizProgress === 5 &&
            userChallenge.progress.explorationProgress === 5
          ) {
            const updatedChallenge = await challengeService.updateUserChallenge(
              {
                ...userChallenge,
                progress: {
                  ...userChallenge.progress,
                  explorationProgress: 5,
                  actionProgress: 5,
                },
              },
              UserChallengeUpdateFlag.DUEL_UNLOCK
            )
            dispatch(updateUserChallengeList(updatedChallenge))
          }
        }
        unlockDuel()
    
        subscribed && setChallengeResult()
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
        return () => {
          subscribed = false
        }
    
      }, [currentDataload, userChallenge, dispatch, challengeService])
    
      const quizButton = () => (
    
          title={t('challenge.card.ongoing.quiz')}
    
          tabIndex={quizFinished ? -1 : 0}
    
          className={classNames('smallCard', {
    
            ['finished']: quizFinished,
    
          })}
          onClick={goQuiz}
        >
          <StyledIcon
            className="cardIcon"
    
            icon={quizFinished ? circleChecked : circleUnchecked}
    
            size={25}
          />
          <div className="content">
            <span>{t('challenge.card.ongoing.quiz')}</span>
            <StarsContainer result={userChallenge.progress.quizProgress} />
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
          </div>
    
      )
    
      const explorationButton = () => (
    
          title={t('challenge.card.ongoing.exploration')}
    
          tabIndex={explorationFinished ? -1 : 0}
    
          className={classNames('smallCard explorationCard', {
    
            ['finished']: explorationFinished,
    
          })}
          onClick={goExploration}
        >
          <StyledIcon
            className="cardIcon"
    
            icon={explorationFinished ? circleChecked : circleUnchecked}
    
            size={25}
          />
          {userChallenge.exploration.state ===
            UserExplorationState.NOTIFICATION && (
            <div className="notifChallenge">1</div>
          )}
          <div className="content">
            <span>{t('challenge.card.ongoing.exploration')}</span>
            <StarsContainer result={userChallenge.progress.explorationProgress} />
          </div>
    
      )
    
      const actionButton = () => (
    
          title={t('challenge.card.ongoing.action')}
    
          tabIndex={actionFinished ? -1 : 0}
    
          className={classNames('smallCard actionCard', {
    
            ['finished']: actionFinished,
    
          })}
          onClick={goAction}
        >
          <StyledIcon
            className="cardIcon"
    
            icon={actionFinished ? circleChecked : circleUnchecked}
    
            size={25}
          />
          {userChallenge.action.state === UserActionState.NOTIFICATION && (
            <div className="notifChallenge">1</div>
          )}
          <div className="content">
            <span>{t('challenge.card.ongoing.action')}</span>
            <StarsContainer result={userChallenge.progress.actionProgress} />
          </div>
    
      )
    
      const duelButton = (
    
        <Button className="smallCard goDuel" onClick={goDuel}>
    
          {isLoading ? (
            <div className="spinner-container">
              <Loader color="black" />
    
          ) : (
            <>
              {t('challenge.card.ongoing.duel')}
              <StyledIcon
                className="challengeminIcon"
                icon={challengeIcon}
                size={60}
              />
            </>
          )}
    
      )
    
      const duelCard = (content: JSX.Element, extraClassName = '') => (
    
        <Button className={`smallCard duelCard ${extraClassName}`} onClick={goDuel}>
    
          {content}
          <StyledIcon className="circleStar" icon={challengeIcon} size={60} />
    
      )
    
      const duelContainer = () => {
        if (
          duel.state === UserDuelState.NO_REF_PERIOD_VALID ||
          (actionProgress + explorationProgress + quizProgress >= target &&
            duel.state === UserDuelState.UNLOCKED)
        ) {
          return duelButton
        } else if (duel.state === UserDuelState.ONGOING && !isDone) {
          return duelCard(
            <div className="finalDuel">
              <span>{t('challenge.card.ongoing.duel')}</span>
              <p className="starCount">
                <span className="blueNumber">{`${duel.userConsumption} €  `}</span>
                <span>{` / ${duel.threshold} €`}</span>
              </p>
            </div>,
            'active'
          )
        } else if (duel.state === UserDuelState.ONGOING && isDone) {
          return duelCard(
            <>
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
              <div className="finalDuel result">
                <span>{t('challenge.card.ongoing.result')}</span>
    
                <span className="lowercase">
                  {t('challenge.card.ongoing.duelDone')}
                </span>
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
              </div>
    
    Yoan VALLET's avatar
    Yoan VALLET committed
              <div className="notifChallenge">1</div>
    
            </>,
            'active'
          )
        } else {
    
            <Button className="smallCard duelCard duelLocked" disabled>
    
              <div className="starCount">
                <StyledIcon icon={circleStar} size={30} />
                <span className="blueNumber">
                  {quizProgress + explorationProgress + actionProgress}
                </span>
                <span>{` / ${target}`}</span>
              </div>
              <StyledIcon className="circleStar" icon={lockedDuel} size={60} />
            </Button>
    
          )
        }
      }
    
      return (
        <div className="cardContent onGoing">
          <div className="titleBlock">
            <span className="challengeTitle">
              {getChallengeTitleWithLineReturn(userChallenge.id)}
            </span>
          </div>
          {quizButton()}
          {explorationButton()}
          {actionButton()}
          {duelContainer()}
    
          <ChallengeNoFluidModal
    
            open={noFluidConnected}
            handleCloseClick={() => setNoFluidConnected(false)}
    
    export default ChallengeCardOnGoing