Skip to content
Snippets Groups Projects
ChallengeCardOnGoing.tsx 10.2 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/I18n'
    
    import {
      UserActionState,
      UserChallengeUpdateFlag,
      UserDuelState,
      UserExplorationState,
      UserQuizState,
    } from 'enums'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    import { UserChallenge } from 'models'
    
    import React, { useCallback, useEffect, 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 [isOneFluidUp, setIsOneFluidUp] = useState<boolean>(true)
      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 toggleNoFluidModal = useCallback(() => {
        setIsOneFluidUp(prev => !prev)
      }, [])
    
      const goDuel = async () => {
    
        setIsLoading(true)
    
        // Check if at least one fluid is up
    
        if (fluidTypes.length !== 0) {
          if (userChallenge.duel.state !== UserDuelState.ONGOING) {
            const challengeService = new ChallengeService(client)
            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)
    
    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 challengeService = new ChallengeService(client)
          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
        async function importIcon() {
    
          importIconById(userChallenge.id, 'challenge').then(icon => {
    
            if (subscribed) {
              icon ? setChallengeIcon(icon) : setChallengeIcon(defaultChallengeIcon)
            }
          })
        }
        importIcon()
        return () => {
          subscribed = false
        }
    
      }, [userChallenge])
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
      useEffect(() => {
        const challengeService = new ChallengeService(client)
        let subscribed = true
        async function setChallengeResult() {
    
    unknown's avatar
    unknown committed
          const isChallengeDone = await challengeService.isChallengeDone(
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
            userChallenge,
            currentDataload
          )
          if (subscribed) {
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
            setIsDone(isChallengeDone.isDone)
    
    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()
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
        setChallengeResult()
        return () => {
          subscribed = false
        }
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
      }, [client, currentDataload, userChallenge, dispatch])
    
      const quizButton = () => (
    
          title={t('challenge.card.ongoing.quiz')}
          tabIndex={userChallenge.progress.quizProgress === 5 ? -1 : 0}
          className={classNames('smallCard', {
            ['finished']: userChallenge.progress.quizProgress === 5,
          })}
          onClick={goQuiz}
        >
          <StyledIcon
            className="cardIcon"
            icon={
              userChallenge.progress.quizProgress === 5
                ? 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={userChallenge.progress.explorationProgress === 5 ? -1 : 0}
          className={classNames('smallCard explorationCard', {
            ['finished']: userChallenge.progress.explorationProgress === 5,
          })}
          onClick={goExploration}
        >
          <StyledIcon
            className="cardIcon"
            icon={
              userChallenge.progress.explorationProgress === 5
                ? 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={userChallenge.progress.actionProgress === 5 ? -1 : 0}
          className={classNames('smallCard actionCard', {
            ['finished']: userChallenge.progress.actionProgress === 5,
          })}
          onClick={goAction}
        >
          <StyledIcon
            className="cardIcon"
            icon={
              userChallenge.progress.actionProgress === 5
                ? 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>{t('challenge.card.ongoing.duelDone')}</span>
              </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={!isOneFluidUp}
            handleCloseClick={toggleNoFluidModal}
          />
    
    export default ChallengeCardOnGoing