diff --git a/client/src/components/landing/landing.css b/client/src/components/landing/landing.css index ac5e4b0e41..6a4e9c32b7 100644 --- a/client/src/components/landing/landing.css +++ b/client/src/components/landing/landing.css @@ -9,6 +9,10 @@ white-space: pre-line; } +.cert-btn { + margin-top: 40px; +} + .landing-page ul { list-style: none; padding-left: 0px; diff --git a/client/src/templates/Introduction/SuperBlockIntro.js b/client/src/templates/Introduction/SuperBlockIntro.js index 32225f6fdd..178ba7433d 100644 --- a/client/src/templates/Introduction/SuperBlockIntro.js +++ b/client/src/templates/Introduction/SuperBlockIntro.js @@ -17,6 +17,7 @@ import { Spacer } from '../../components/helpers'; import { currentChallengeIdSelector, userFetchStateSelector, + signInLoadingSelector, isSignedInSelector, tryToShowDonationModal, userSelector @@ -50,6 +51,7 @@ const propTypes = { }) }), resetExpansion: PropTypes.func, + signInLoading: PropTypes.bool, t: PropTypes.func, toggleBlock: PropTypes.func, tryToShowDonationModal: PropTypes.func.isRequired, @@ -62,11 +64,13 @@ const mapStateToProps = state => { return createSelector( currentChallengeIdSelector, isSignedInSelector, + signInLoadingSelector, userFetchStateSelector, userSelector, - (currentChallengeId, isSignedIn, fetchState, user) => ({ + (currentChallengeId, isSignedIn, signInLoading, fetchState, user) => ({ currentChallengeId, isSignedIn, + signInLoading, fetchState, user }) @@ -150,6 +154,7 @@ const SuperBlockIntroductionPage = props => { allChallengeNode: { edges } }, isSignedIn, + signInLoading, t, user } = props; @@ -202,7 +207,7 @@ const SuperBlockIntroductionPage = props => { )} - {!isSignedIn && ( + {!isSignedIn && !signInLoading && (
{t('buttons.logged-out-cta-btn')} diff --git a/client/src/templates/Introduction/components/CertChallenge.js b/client/src/templates/Introduction/components/CertChallenge.js index e1c5df7c4e..8e9ffb06f3 100644 --- a/client/src/templates/Introduction/components/CertChallenge.js +++ b/client/src/templates/Introduction/components/CertChallenge.js @@ -5,13 +5,16 @@ import React, { useState, useEffect } from 'react'; import { withTranslation } from 'react-i18next'; import { connect } from 'react-redux'; import { createSelector } from 'reselect'; - import { certSlugTypeMap, superBlockCertTypeMap } from '../../../../../config/certification-settings'; import { createFlashMessage } from '../../../components/Flash/redux'; -import { stepsToClaimSelector } from '../../../redux'; +import { + userFetchStateSelector, + stepsToClaimSelector, + isSignedInSelector +} from '../../../redux'; import { StepsType, User } from '../../../redux/prop-types'; import { verifyCert } from '../../../redux/settings'; @@ -22,6 +25,12 @@ import CertificationCard from './CertificationCard'; const propTypes = { createFlashMessage: PropTypes.func.isRequired, + fetchState: PropTypes.shape({ + pending: PropTypes.bool, + complete: PropTypes.bool, + errored: PropTypes.bool + }), + isSignedIn: PropTypes.bool, steps: StepsType, superBlock: PropTypes.string, t: PropTypes.func, @@ -36,9 +45,16 @@ const honestyInfoMessage = { }; const mapStateToProps = state => { - return createSelector(stepsToClaimSelector, steps => ({ - steps - }))(state); + return createSelector( + stepsToClaimSelector, + userFetchStateSelector, + isSignedInSelector, + (steps, fetchState, isSignedIn) => ({ + steps, + fetchState, + isSignedIn + }) + )(state); }; const mapDispatchToProps = { @@ -53,15 +69,21 @@ const CertChallenge = ({ t, verifyCert, title, + fetchState, + isSignedIn, user: { isHonest, username } }) => { - const [canClaim, setCanClaim] = useState({ status: false, result: '' }); + const [canClaimCert, setCanClaimCert] = useState(false); + const [certVerificationMessage, setCertVerificationMessage] = useState(''); const [isCertified, setIsCertified] = useState(false); + const [userLoaded, setUserLoaded] = useState(false); + const [verificationComplete, setVerificationComplete] = useState(false); const [stepState, setStepState] = useState({ numberOfSteps: 0, completedCount: 0 }); - const [canViewCert, setCanViewCert] = useState(false); + const [hasCompletedRequiredSteps, setHasCompletedRequiredSteps] = + useState(false); const [isProjectsCompleted, setIsProjectsCompleted] = useState(false); useEffect(() => { @@ -70,7 +92,9 @@ const CertChallenge = ({ try { const data = await getVerifyCanClaimCert(username, superBlock); const { status, result } = data?.response?.message; - setCanClaim({ status, result }); + setCanClaimCert(status); + setCertVerificationMessage(result); + setVerificationComplete(true); } catch (e) { // TODO: How do we handle errors...? } @@ -81,6 +105,14 @@ const CertChallenge = ({ const { certSlug } = certMap.find(x => x.title === title); + useEffect(() => { + const { pending, complete } = fetchState; + + if (complete && !pending) { + setUserLoaded(true); + } + }, [fetchState]); + useEffect(() => { setIsCertified( steps?.currentCerts?.find( @@ -90,18 +122,17 @@ const CertChallenge = ({ ); const projectsCompleted = - canClaim.status || canClaim.result === 'projects-completed'; + canClaimCert || certVerificationMessage === 'projects-completed'; const completedCount = Object.values(steps).filter( stepVal => typeof stepVal === 'boolean' && stepVal ).length + projectsCompleted; const numberOfSteps = Object.keys(steps).length; - - setCanViewCert(completedCount === numberOfSteps); + setHasCompletedRequiredSteps(completedCount === numberOfSteps); setStepState({ numberOfSteps, completedCount }); setIsProjectsCompleted(projectsCompleted); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [steps, canClaim]); + }, [steps, canClaimCert, certVerificationMessage]); const certLocation = `/certification/${username}/${certSlug}`; const i18nSuperBlock = t(`intro:${superBlock}.title`); @@ -109,6 +140,11 @@ const CertChallenge = ({ cert: i18nSuperBlock }); + const showCertificationCard = + userLoaded && + isSignedIn && + (!isCertified || (!hasCompletedRequiredSteps && verificationComplete)); + const createClickHandler = certSlug => e => { e.preventDefault(); if (isCertified) { @@ -118,10 +154,9 @@ const CertChallenge = ({ ? verifyCert(certSlug) : createFlashMessage(honestyInfoMessage); }; - return (
- {(!isCertified || !canViewCert) && ( + {showCertificationCard && ( )} - + <> + {isSignedIn && ( + + )} +
); }; diff --git a/client/src/templates/Introduction/components/ClaimCertSteps.js b/client/src/templates/Introduction/components/ClaimCertSteps.js index f02a09f9f8..1f49384674 100644 --- a/client/src/templates/Introduction/components/ClaimCertSteps.js +++ b/client/src/templates/Introduction/components/ClaimCertSteps.js @@ -2,7 +2,6 @@ import { Link } from 'gatsby'; import PropTypes from 'prop-types'; import React from 'react'; import { withTranslation, useTranslation } from 'react-i18next'; - import GreenNotCompleted from '../../../assets/icons/green-not-completed'; import GreenPass from '../../../assets/icons/green-pass'; import { StepsType } from '../../../redux/prop-types'; @@ -39,6 +38,7 @@ const ClaimCertSteps = ({ isShowCerts = false, isShowProfile = false } = steps; + return (