feat(client): ts-migration for Introduction templates (#43752)
* chore: rename the file CertificationCard.js to tsx * refactor: refactor the file CertificationCard to tsx refactor: refactor the file CertificationCard to tsx refactor: refactor the file CertificationCard to tsx * chore: rename the file ClaimCertSteps.js to tsx * refactor: refactor the file ClaimCertSteps to TS * chore: rename the file SuperBlockIntro.js to tsx * refactor: refactor the file SuperBlockIntro to TS * chore: rename the file Block.js to tsx * refactor: refactor the file Block to TS refactor: refactor the file Block to TS refactor: refactor the file Block to TS * chore: rename the file CertChallenge.js to tsx * refactor: refactor the file CertChallenge to TS * fix typing * ignore missing redux store connection Co-authored-by: ismail <i.tlemcani@quinten-maroc.com> Co-authored-by: Ismail Tlemcani <ismail.tlemcani@gmail.com> Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { HandlerProps } from 'react-reflex';
|
||||
import { SuperBlocks } from '../../../config/certification-settings';
|
||||
import { certMap } from '../resources/cert-and-project-map';
|
||||
|
||||
export const UserPropType = PropTypes.shape({
|
||||
about: PropTypes.string,
|
||||
@ -63,12 +64,13 @@ export const CurrentCertsPropType = PropTypes.arrayOf(
|
||||
})
|
||||
);
|
||||
|
||||
export const StepsPropType = PropTypes.shape({
|
||||
currentCerts: CurrentCertsPropType,
|
||||
isShowCerts: PropTypes.bool,
|
||||
isShowName: PropTypes.bool,
|
||||
isShowProfile: PropTypes.bool
|
||||
});
|
||||
export type Steps = {
|
||||
isHonest?: boolean;
|
||||
currentCerts?: Array<CurrentCert>;
|
||||
isShowCerts?: boolean;
|
||||
isShowName?: boolean;
|
||||
isShowProfile?: boolean;
|
||||
};
|
||||
|
||||
export type CurrentCert = {
|
||||
show: boolean;
|
||||
@ -83,7 +85,7 @@ export type MarkdownRemark = {
|
||||
block: string;
|
||||
isBeta: boolean;
|
||||
superBlock: SuperBlocks;
|
||||
title: string;
|
||||
title: typeof certMap[number]['title'];
|
||||
};
|
||||
headings: [
|
||||
{
|
||||
|
@ -1,9 +1,8 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { withTranslation, TFunction } from 'react-i18next';
|
||||
import { connect } from 'react-redux';
|
||||
import ScrollableAnchor from 'react-scrollable-anchor';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { bindActionCreators, Dispatch } from 'redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import store from 'store';
|
||||
|
||||
@ -12,60 +11,69 @@ import { isAuditedCert } from '../../../../../utils/is-audited';
|
||||
import Caret from '../../../assets/icons/caret';
|
||||
import GreenNotCompleted from '../../../assets/icons/green-not-completed';
|
||||
import GreenPass from '../../../assets/icons/green-pass';
|
||||
import { Link } from '../../../components/helpers/';
|
||||
import { Link } from '../../../components/helpers';
|
||||
import { completedChallengesSelector, executeGA } from '../../../redux';
|
||||
import { ChallengeNode, CompletedChallenge } from '../../../redux/prop-types';
|
||||
import { makeExpandedBlockSelector, toggleBlock } from '../redux';
|
||||
import Challenges from './Challenges';
|
||||
|
||||
const { curriculumLocale } = envData;
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
const mapStateToProps = (
|
||||
state: unknown,
|
||||
ownProps: { blockDashedName: string } & unknown
|
||||
) => {
|
||||
const expandedSelector = makeExpandedBlockSelector(ownProps.blockDashedName);
|
||||
|
||||
return createSelector(
|
||||
expandedSelector,
|
||||
completedChallengesSelector,
|
||||
(isExpanded, completedChallenges) => ({
|
||||
(isExpanded: boolean, completedChallenges: CompletedChallenge[]) => ({
|
||||
isExpanded,
|
||||
completedChallenges: completedChallenges.map(({ id }) => id)
|
||||
completedChallengeIds: completedChallenges.map(({ id }) => id)
|
||||
})
|
||||
)(state);
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch =>
|
||||
const mapDispatchToProps = (dispatch: Dispatch) =>
|
||||
bindActionCreators({ toggleBlock, executeGA }, dispatch);
|
||||
|
||||
const propTypes = {
|
||||
blockDashedName: PropTypes.string,
|
||||
challenges: PropTypes.array,
|
||||
completedChallenges: PropTypes.arrayOf(PropTypes.string),
|
||||
executeGA: PropTypes.func,
|
||||
isExpanded: PropTypes.bool,
|
||||
superBlock: PropTypes.string,
|
||||
t: PropTypes.func,
|
||||
toggleBlock: PropTypes.func.isRequired
|
||||
};
|
||||
interface BlockProps {
|
||||
blockDashedName: string;
|
||||
challenges: ChallengeNode[];
|
||||
completedChallengeIds: string[];
|
||||
executeGA: typeof executeGA;
|
||||
isExpanded: boolean;
|
||||
superBlock: string;
|
||||
t: TFunction;
|
||||
toggleBlock: typeof toggleBlock;
|
||||
}
|
||||
|
||||
const mapIconStyle = { height: '15px', marginRight: '10px', width: '15px' };
|
||||
|
||||
export class Block extends Component {
|
||||
constructor(...props) {
|
||||
super(...props);
|
||||
export class Block extends Component<BlockProps> {
|
||||
static displayName: string;
|
||||
constructor(props: BlockProps) {
|
||||
super(props);
|
||||
|
||||
this.handleBlockClick = this.handleBlockClick.bind(this);
|
||||
}
|
||||
|
||||
handleBlockClick() {
|
||||
handleBlockClick(): void {
|
||||
const { blockDashedName, toggleBlock, executeGA } = this.props;
|
||||
const playSound = store.get('fcc-sound');
|
||||
const playSound = store.get('fcc-sound') as boolean;
|
||||
if (playSound) {
|
||||
void import('tone').then(tone => {
|
||||
void (async () => {
|
||||
const tone = await import('tone');
|
||||
|
||||
const player = new tone.Player(
|
||||
'https://tonejs.github.io/audio/berklee/guitar_chord1.mp3'
|
||||
).toDestination();
|
||||
if (tone.context.state !== 'running') tone.context.resume();
|
||||
if (tone.context.state !== 'running') {
|
||||
void tone.context.resume();
|
||||
}
|
||||
player.autostart = playSound;
|
||||
});
|
||||
})();
|
||||
}
|
||||
executeGA({
|
||||
type: 'event',
|
||||
@ -74,10 +82,10 @@ export class Block extends Component {
|
||||
action: blockDashedName
|
||||
}
|
||||
});
|
||||
return toggleBlock(blockDashedName);
|
||||
toggleBlock(blockDashedName);
|
||||
}
|
||||
|
||||
renderCheckMark(isCompleted) {
|
||||
renderCheckMark(isCompleted: boolean): JSX.Element {
|
||||
return isCompleted ? (
|
||||
<GreenPass style={mapIconStyle} />
|
||||
) : (
|
||||
@ -85,7 +93,7 @@ export class Block extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
renderBlockIntros(arr) {
|
||||
renderBlockIntros(arr: string[]): JSX.Element {
|
||||
return (
|
||||
<div className='block-description'>
|
||||
{arr.map((str, i) => (
|
||||
@ -95,10 +103,10 @@ export class Block extends Component {
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
render(): JSX.Element {
|
||||
const {
|
||||
blockDashedName,
|
||||
completedChallenges,
|
||||
completedChallengeIds,
|
||||
challenges,
|
||||
isExpanded,
|
||||
superBlock,
|
||||
@ -108,8 +116,8 @@ export class Block extends Component {
|
||||
let completedCount = 0;
|
||||
const challengesWithCompleted = challenges.map(challenge => {
|
||||
const { id } = challenge;
|
||||
const isCompleted = completedChallenges.some(
|
||||
completedId => id === completedId
|
||||
const isCompleted = completedChallengeIds.some(
|
||||
(completedChallengeId: string) => completedChallengeId === id
|
||||
);
|
||||
if (isCompleted) {
|
||||
completedCount++;
|
||||
@ -134,13 +142,19 @@ export class Block extends Component {
|
||||
);
|
||||
});
|
||||
|
||||
const blockIntroObj = t(`intro:${superBlock}.blocks.${blockDashedName}`);
|
||||
const blockIntroObj: { title?: string; intro: string[] } = t(
|
||||
`intro:${superBlock}.blocks.${blockDashedName}`
|
||||
);
|
||||
const blockTitle = blockIntroObj ? blockIntroObj.title : null;
|
||||
const blockIntroArr = blockIntroObj ? blockIntroObj.intro : [];
|
||||
const {
|
||||
expand: expandText,
|
||||
collapse: collapseText,
|
||||
courses: coursesText
|
||||
}: {
|
||||
expand: string;
|
||||
collapse: string;
|
||||
courses: string;
|
||||
} = t('intro:misc-text');
|
||||
|
||||
return isProjectBlock ? (
|
||||
@ -196,7 +210,9 @@ export class Block extends Component {
|
||||
<button
|
||||
aria-expanded={isExpanded}
|
||||
className='map-title'
|
||||
onClick={this.handleBlockClick}
|
||||
onClick={() => {
|
||||
this.handleBlockClick();
|
||||
}}
|
||||
>
|
||||
<Caret />
|
||||
<h4 className='course-title'>
|
||||
@ -224,7 +240,6 @@ export class Block extends Component {
|
||||
}
|
||||
|
||||
Block.displayName = 'Block';
|
||||
Block.propTypes = propTypes;
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
@ -1,13 +1,13 @@
|
||||
import { Button } from '@freecodecamp/react-bootstrap';
|
||||
import { navigate } from 'gatsby-link';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { TFunction, withTranslation } from 'react-i18next';
|
||||
import { connect } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import {
|
||||
certSlugTypeMap,
|
||||
superBlockCertTypeMap
|
||||
superBlockCertTypeMap,
|
||||
SuperBlocks
|
||||
} from '../../../../../config/certification-settings';
|
||||
import { createFlashMessage } from '../../../components/Flash/redux';
|
||||
import {
|
||||
@ -15,41 +15,40 @@ import {
|
||||
stepsToClaimSelector,
|
||||
isSignedInSelector
|
||||
} from '../../../redux';
|
||||
|
||||
import { StepsPropType, UserPropType } from '../../../redux/prop-types';
|
||||
import { User, Steps } from '../../../redux/prop-types';
|
||||
import { verifyCert } from '../../../redux/settings';
|
||||
|
||||
import { certMap } from '../../../resources/cert-and-project-map';
|
||||
import { getVerifyCanClaimCert } from '../../../utils/ajax';
|
||||
import CertificationCard from './CertificationCard';
|
||||
import CertificationCard from './certification-card';
|
||||
|
||||
const propTypes = {
|
||||
createFlashMessage: PropTypes.func.isRequired,
|
||||
fetchState: PropTypes.shape({
|
||||
pending: PropTypes.bool,
|
||||
complete: PropTypes.bool,
|
||||
errored: PropTypes.bool
|
||||
}),
|
||||
isSignedIn: PropTypes.bool,
|
||||
steps: StepsPropType,
|
||||
superBlock: PropTypes.string,
|
||||
t: PropTypes.func,
|
||||
title: PropTypes.string,
|
||||
user: UserPropType,
|
||||
verifyCert: PropTypes.func.isRequired
|
||||
interface CertChallengeProps {
|
||||
createFlashMessage: typeof createFlashMessage;
|
||||
fetchState: {
|
||||
pending: boolean;
|
||||
complete: boolean;
|
||||
errored: boolean;
|
||||
error: null | string;
|
||||
};
|
||||
isSignedIn: boolean;
|
||||
steps: Steps;
|
||||
superBlock: SuperBlocks;
|
||||
t: TFunction;
|
||||
title: typeof certMap[number]['title'];
|
||||
user: User;
|
||||
verifyCert: typeof verifyCert;
|
||||
}
|
||||
|
||||
const honestyInfoMessage = {
|
||||
type: 'info',
|
||||
message: 'flash.honest-first'
|
||||
};
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const mapStateToProps = (state: unknown) => {
|
||||
return createSelector(
|
||||
stepsToClaimSelector,
|
||||
userFetchStateSelector,
|
||||
isSignedInSelector,
|
||||
(steps, fetchState, isSignedIn) => ({
|
||||
(steps, fetchState: CertChallengeProps['fetchState'], isSignedIn) => ({
|
||||
steps,
|
||||
fetchState,
|
||||
isSignedIn
|
||||
@ -72,7 +71,7 @@ const CertChallenge = ({
|
||||
fetchState,
|
||||
isSignedIn,
|
||||
user: { isHonest, username }
|
||||
}) => {
|
||||
}: CertChallengeProps): JSX.Element => {
|
||||
const [canClaimCert, setCanClaimCert] = useState(false);
|
||||
const [certVerificationMessage, setCertVerificationMessage] = useState('');
|
||||
const [isCertified, setIsCertified] = useState(false);
|
||||
@ -88,7 +87,7 @@ const CertChallenge = ({
|
||||
|
||||
useEffect(() => {
|
||||
if (username) {
|
||||
(async () => {
|
||||
void (async () => {
|
||||
try {
|
||||
const data = await getVerifyCanClaimCert(username, superBlock);
|
||||
const { status, result } = data?.response?.message;
|
||||
@ -103,7 +102,8 @@ const CertChallenge = ({
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [username]);
|
||||
|
||||
const { certSlug } = certMap.find(x => x.title === title);
|
||||
// @ts-expect-error Typescript is confused
|
||||
const certSlug = certMap.find(x => x.title === title).certSlug;
|
||||
|
||||
useEffect(() => {
|
||||
const { pending, complete } = fetchState;
|
||||
@ -113,20 +113,26 @@ const CertChallenge = ({
|
||||
}
|
||||
}, [fetchState]);
|
||||
|
||||
const certSlugTypeMapTyped: { [key: string]: string } = certSlugTypeMap;
|
||||
const superBlockCertTypeMapTyped: { [key: string]: string } =
|
||||
superBlockCertTypeMap;
|
||||
|
||||
useEffect(() => {
|
||||
setIsCertified(
|
||||
steps?.currentCerts?.find(
|
||||
cert =>
|
||||
certSlugTypeMap[cert.certSlug] === superBlockCertTypeMap[superBlock]
|
||||
(cert: { certSlug: string }) =>
|
||||
certSlugTypeMapTyped[cert.certSlug] ===
|
||||
superBlockCertTypeMapTyped[superBlock]
|
||||
)?.show ?? false
|
||||
);
|
||||
|
||||
const projectsCompleted =
|
||||
canClaimCert || certVerificationMessage === 'projects-completed';
|
||||
const projectsCompletedNumber = projectsCompleted ? 1 : 0;
|
||||
const completedCount =
|
||||
Object.values(steps).filter(
|
||||
stepVal => typeof stepVal === 'boolean' && stepVal
|
||||
).length + projectsCompleted;
|
||||
).length + projectsCompletedNumber;
|
||||
const numberOfSteps = Object.keys(steps).length;
|
||||
setHasCompletedRequiredSteps(completedCount === numberOfSteps);
|
||||
setStepState({ numberOfSteps, completedCount });
|
||||
@ -145,7 +151,8 @@ const CertChallenge = ({
|
||||
isSignedIn &&
|
||||
(!isCertified || (!hasCompletedRequiredSteps && verificationComplete));
|
||||
|
||||
const createClickHandler = certSlug => e => {
|
||||
const createClickHandler =
|
||||
(certSlug: string | undefined) => (e: { preventDefault: () => void }) => {
|
||||
e.preventDefault();
|
||||
if (isCertified) {
|
||||
return navigate(certLocation);
|
||||
@ -188,7 +195,6 @@ const CertChallenge = ({
|
||||
};
|
||||
|
||||
CertChallenge.displayName = 'CertChallenge';
|
||||
CertChallenge.propTypes = propTypes;
|
||||
|
||||
export { CertChallenge };
|
||||
|
@ -1,26 +1,24 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ScrollableAnchor from 'react-scrollable-anchor';
|
||||
import { SuperBlocks } from '../../../../../config/certification-settings';
|
||||
import Caret from '../../../assets/icons/caret';
|
||||
import GreenNotCompleted from '../../../assets/icons/green-not-completed';
|
||||
// import { navigate } from 'gatsby';
|
||||
import GreenPass from '../../../assets/icons/green-pass';
|
||||
import { StepsPropType } from '../../../redux/prop-types';
|
||||
import ClaimCertSteps from './ClaimCertSteps';
|
||||
import { Steps } from '../../../redux/prop-types';
|
||||
import ClaimCertSteps from './claim-cert-steps';
|
||||
|
||||
const propTypes = {
|
||||
i18nCertText: PropTypes.string,
|
||||
isProjectsCompleted: PropTypes.bool,
|
||||
stepState: PropTypes.shape({
|
||||
numberOfSteps: PropTypes.number,
|
||||
completedCount: PropTypes.number
|
||||
}),
|
||||
steps: StepsPropType,
|
||||
superBlock: PropTypes.string
|
||||
interface CertificationCardProps {
|
||||
i18nCertText: string;
|
||||
isProjectsCompleted: boolean;
|
||||
stepState: {
|
||||
numberOfSteps: number;
|
||||
completedCount: number;
|
||||
};
|
||||
|
||||
steps: Steps;
|
||||
superBlock: SuperBlocks;
|
||||
}
|
||||
const mapIconStyle = { height: '15px', marginRight: '10px', width: '15px' };
|
||||
|
||||
const CertificationCard = ({
|
||||
@ -29,7 +27,7 @@ const CertificationCard = ({
|
||||
i18nCertText,
|
||||
stepState: { completedCount, numberOfSteps },
|
||||
steps
|
||||
}) => {
|
||||
}: CertificationCardProps): JSX.Element => {
|
||||
const { t } = useTranslation();
|
||||
const [isExpanded, setIsExpanded] = useState(true);
|
||||
|
||||
@ -41,6 +39,10 @@ const CertificationCard = ({
|
||||
expand: expandText,
|
||||
collapse: collapseText,
|
||||
courses: coursesText
|
||||
}: {
|
||||
expand: string;
|
||||
collapse: string;
|
||||
courses: string;
|
||||
} = t('intro:misc-text');
|
||||
return (
|
||||
<ScrollableAnchor id='claim-cert-block'>
|
||||
@ -90,6 +92,5 @@ const CertificationCard = ({
|
||||
};
|
||||
|
||||
CertificationCard.displayName = 'CertStatus';
|
||||
CertificationCard.propTypes = propTypes;
|
||||
|
||||
export default CertificationCard;
|
@ -1,28 +1,28 @@
|
||||
import { Link } from 'gatsby';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { withTranslation, useTranslation } from 'react-i18next';
|
||||
import { SuperBlocks } from '../../../../../config/certification-settings';
|
||||
import GreenNotCompleted from '../../../assets/icons/green-not-completed';
|
||||
import GreenPass from '../../../assets/icons/green-pass';
|
||||
import { StepsPropType } from '../../../redux/prop-types';
|
||||
import { Steps } from '../../../redux/prop-types';
|
||||
|
||||
const mapIconStyle = { height: '15px', marginRight: '10px', width: '15px' };
|
||||
|
||||
const propTypes = {
|
||||
i18nCertText: PropTypes.string,
|
||||
isProjectsCompleted: PropTypes.bool,
|
||||
steps: StepsPropType,
|
||||
superBlock: PropTypes.string
|
||||
};
|
||||
interface ClaimCertStepsProps {
|
||||
i18nCertText: string;
|
||||
isProjectsCompleted: boolean;
|
||||
steps: Steps;
|
||||
superBlock: SuperBlocks;
|
||||
}
|
||||
|
||||
const ClaimCertSteps = ({
|
||||
isProjectsCompleted,
|
||||
i18nCertText,
|
||||
steps,
|
||||
superBlock
|
||||
}) => {
|
||||
}: ClaimCertStepsProps): JSX.Element => {
|
||||
const { t } = useTranslation();
|
||||
const renderCheckMark = isCompleted => {
|
||||
const renderCheckMark = (isCompleted: boolean) => {
|
||||
return isCompleted ? (
|
||||
<GreenPass style={mapIconStyle} />
|
||||
) : (
|
||||
@ -84,6 +84,5 @@ const ClaimCertSteps = ({
|
||||
};
|
||||
|
||||
ClaimCertSteps.displayName = 'ClaimCertSteps';
|
||||
ClaimCertSteps.propTypes = propTypes;
|
||||
|
||||
export default withTranslation()(ClaimCertSteps);
|
@ -1,19 +1,22 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { SuperBlocks } from '../../../../../config/certification-settings';
|
||||
import { generateIconComponent } from '../../../assets/icons';
|
||||
import { Spacer } from '../../../components/helpers';
|
||||
|
||||
const propTypes = {
|
||||
superBlock: PropTypes.string
|
||||
};
|
||||
interface SuperBlockIntroProps {
|
||||
superBlock: SuperBlocks;
|
||||
}
|
||||
|
||||
function SuperBlockIntro(props) {
|
||||
function SuperBlockIntro(props: SuperBlockIntroProps): JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
const { superBlock } = props;
|
||||
|
||||
const superBlockIntroObj = t(`intro:${superBlock}`);
|
||||
const superBlockIntroObj: {
|
||||
title: string;
|
||||
intro: string[];
|
||||
note: string[];
|
||||
} = t(`intro:${superBlock}`);
|
||||
const {
|
||||
title: i18nSuperBlock,
|
||||
intro: superBlockIntroText,
|
||||
@ -39,6 +42,5 @@ function SuperBlockIntro(props) {
|
||||
}
|
||||
|
||||
SuperBlockIntro.displayName = 'SuperBlockIntro';
|
||||
SuperBlockIntro.propTypes = propTypes;
|
||||
|
||||
export default SuperBlockIntro;
|
@ -25,9 +25,9 @@ import {
|
||||
userSelector
|
||||
} from '../../redux';
|
||||
import { MarkdownRemark, AllChallengeNode, User } from '../../redux/prop-types';
|
||||
import Block from './components/Block';
|
||||
import CertChallenge from './components/CertChallenge';
|
||||
import SuperBlockIntro from './components/SuperBlockIntro';
|
||||
import Block from './components/block';
|
||||
import CertChallenge from './components/cert-challenge';
|
||||
import SuperBlockIntro from './components/super-block-intro';
|
||||
import { resetExpansion, toggleBlock } from './redux';
|
||||
|
||||
import './intro.css';
|
||||
|
@ -3,6 +3,7 @@ import envData from '../../../config/env.json';
|
||||
|
||||
import type {
|
||||
ChallengeFile,
|
||||
ClaimedCertifications,
|
||||
CompletedChallenge,
|
||||
User
|
||||
} from '../redux/prop-types';
|
||||
@ -158,11 +159,25 @@ export function getUsernameExists(username: string): Promise<boolean> {
|
||||
return get(`/api/users/exists?username=${username}`);
|
||||
}
|
||||
|
||||
// TODO: Does a GET return a bolean?
|
||||
export interface GetVerifyCanClaimCert {
|
||||
response: {
|
||||
type: string;
|
||||
message: {
|
||||
status: boolean;
|
||||
result: string;
|
||||
};
|
||||
variables: {
|
||||
name: string;
|
||||
};
|
||||
};
|
||||
isCertMap: ClaimedCertifications;
|
||||
completedChallenges: CompletedChallenge[];
|
||||
}
|
||||
|
||||
export function getVerifyCanClaimCert(
|
||||
username: string,
|
||||
superBlock: string
|
||||
): Promise<boolean> {
|
||||
): Promise<GetVerifyCanClaimCert> {
|
||||
return get(
|
||||
`/certificate/verify-can-claim-cert?username=${username}&superBlock=${superBlock}`
|
||||
);
|
||||
|
Reference in New Issue
Block a user