mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-01-01 18:03:58 -05:00
fix(UI): make the task challenges be in the grid view (#53687)
Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
@@ -718,6 +718,8 @@
|
||||
"step": "Step",
|
||||
"steps": "Steps",
|
||||
"steps-for": "Steps for {{blockTitle}}",
|
||||
"task": "Task",
|
||||
"dialogues-and-tasks-for": "Dialogues and tasks for {{blockTitle}}",
|
||||
"code-example": "{{codeName}} code example",
|
||||
"opens-new-window": "Opens in new window"
|
||||
},
|
||||
|
||||
@@ -9,6 +9,14 @@ import GreenNotCompleted from '../../../assets/icons/green-not-completed';
|
||||
import GreenPass from '../../../assets/icons/green-pass';
|
||||
import { executeGA } from '../../../redux/actions';
|
||||
import { ChallengeWithCompletedNode } from '../../../redux/prop-types';
|
||||
import { SuperBlocks } from '../../../../../shared/config/superblocks';
|
||||
import { challengeTypes } from '../../../../../shared/config/challenge-types';
|
||||
|
||||
const getStepNumber = (dashedName: string) => {
|
||||
// dashedName should be in the format 'step-1' or 'task-1'
|
||||
const match = dashedName.match(/-(\d+)/);
|
||||
return match ? match[1] : '';
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch: Dispatch) =>
|
||||
bindActionCreators({ executeGA }, dispatch);
|
||||
@@ -23,6 +31,28 @@ interface Challenges {
|
||||
const CheckMark = ({ isCompleted }: { isCompleted: boolean }) =>
|
||||
isCompleted ? <GreenPass /> : <GreenNotCompleted />;
|
||||
|
||||
const Challenge = ({
|
||||
challenge
|
||||
}: {
|
||||
challenge: ChallengeWithCompletedNode;
|
||||
}) => (
|
||||
<Link to={challenge.fields.slug}>
|
||||
<span className='badge map-badge'>
|
||||
<CheckMark isCompleted={challenge.isCompleted} />
|
||||
</span>
|
||||
{challenge.title}
|
||||
</Link>
|
||||
);
|
||||
|
||||
const Project = ({ challenge }: { challenge: ChallengeWithCompletedNode }) => (
|
||||
<Link to={challenge.fields.slug}>
|
||||
{challenge.title}
|
||||
<span className=' badge map-badge map-project-checkmark'>
|
||||
<CheckMark isCompleted={challenge.isCompleted} />
|
||||
</span>
|
||||
</Link>
|
||||
);
|
||||
|
||||
function Challenges({
|
||||
challengesWithCompleted,
|
||||
isProjectBlock,
|
||||
@@ -56,40 +86,51 @@ function Challenges({
|
||||
)}
|
||||
<nav
|
||||
aria-label={
|
||||
blockTitle ? t('aria.steps-for', { blockTitle }) : t('aria.steps')
|
||||
blockTitle
|
||||
? challengesWithCompleted[0].superBlock === SuperBlocks.A2English
|
||||
? t('aria.dialogues-and-tasks-for', { blockTitle })
|
||||
: t('aria.steps-for', { blockTitle })
|
||||
: t('aria.steps')
|
||||
}
|
||||
>
|
||||
<ul className={`map-challenges-ul map-challenges-grid `}>
|
||||
{challengesWithCompleted.map((challenge, i) => (
|
||||
{challengesWithCompleted.map(challenge => (
|
||||
<li
|
||||
className={`map-challenge-title map-challenge-title-grid ${
|
||||
isProjectBlock ? 'map-project-wrap' : 'map-challenge-wrap'
|
||||
isProjectBlock
|
||||
? 'map-project-wrap'
|
||||
: challenge.challengeType === challengeTypes.dialogue
|
||||
? 'map-dialogue-wrap'
|
||||
: 'map-challenge-wrap'
|
||||
}`}
|
||||
id={challenge.dashedName}
|
||||
key={`map-challenge ${challenge.fields.slug}`}
|
||||
>
|
||||
{!isProjectBlock ? (
|
||||
{!isProjectBlock &&
|
||||
challenge.challengeType !== challengeTypes.dialogue ? (
|
||||
// Step or Task challenge
|
||||
<Link
|
||||
to={challenge.fields.slug}
|
||||
className={`map-grid-item ${
|
||||
+challenge.isCompleted ? 'challenge-completed' : ''
|
||||
}`}
|
||||
>
|
||||
<span className='sr-only'>{t('aria.step')}</span>
|
||||
<span>{i + 1}</span>
|
||||
<span className='sr-only'>
|
||||
{challenge.superBlock === SuperBlocks.A2English
|
||||
? t('aria.task')
|
||||
: t('aria.step')}
|
||||
</span>
|
||||
<span>{getStepNumber(challenge.dashedName)}</span>
|
||||
<span className='sr-only'>
|
||||
{challenge.isCompleted
|
||||
? t('icons.passed')
|
||||
: t('icons.not-passed')}
|
||||
</span>
|
||||
</Link>
|
||||
) : challenge.challengeType === challengeTypes.dialogue ? (
|
||||
<Challenge challenge={challenge} />
|
||||
) : (
|
||||
<Link to={challenge.fields.slug}>
|
||||
{challenge.title}
|
||||
<span className=' badge map-badge map-project-checkmark'>
|
||||
<CheckMark isCompleted={challenge.isCompleted} />
|
||||
</span>
|
||||
</Link>
|
||||
<Project challenge={challenge} />
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
@@ -107,19 +148,9 @@ function Challenges({
|
||||
key={'map-challenge' + challenge.fields.slug}
|
||||
>
|
||||
{!isProjectBlock ? (
|
||||
<Link to={challenge.fields.slug}>
|
||||
<span className='badge map-badge'>
|
||||
<CheckMark isCompleted={challenge.isCompleted} />
|
||||
</span>
|
||||
{challenge.title}
|
||||
</Link>
|
||||
<Challenge challenge={challenge} />
|
||||
) : (
|
||||
<Link to={challenge.fields.slug}>
|
||||
{challenge.title}
|
||||
<span className='badge map-badge map-project-checkmark'>
|
||||
<CheckMark isCompleted={challenge.isCompleted} />
|
||||
</span>
|
||||
</Link>
|
||||
<Project challenge={challenge} />
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
|
||||
@@ -125,6 +125,7 @@ button.map-title {
|
||||
}
|
||||
|
||||
.map-challenge-wrap > a,
|
||||
.map-dialogue-wrap > a,
|
||||
.map-project-wrap > a {
|
||||
display: flex;
|
||||
gap: 7px;
|
||||
@@ -229,28 +230,15 @@ button.map-title {
|
||||
.map-challenge-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
font-size: 1.13rem;
|
||||
}
|
||||
|
||||
.map-challenge-title a {
|
||||
width: 100%;
|
||||
padding: 10px 15px;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.map-challenges-grid .map-challenge-title a {
|
||||
width: 3.4rem;
|
||||
height: 3.4rem;
|
||||
min-width: 24px;
|
||||
min-height: 24px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.map-challenges-grid .map-challenge-title a:focus {
|
||||
outline-offset: 1px;
|
||||
}
|
||||
|
||||
.map-challenges-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, 3.4rem);
|
||||
@@ -258,19 +246,40 @@ button.map-title {
|
||||
justify-content: space-between;
|
||||
margin: 0 auto 18px;
|
||||
width: calc(100% - 50px);
|
||||
list-style: none;
|
||||
}
|
||||
.map-challenge-title-grid {
|
||||
flex: 0 1 60px;
|
||||
|
||||
.map-challenges-grid .map-challenge-title a:focus {
|
||||
outline-offset: 1px;
|
||||
}
|
||||
.map-challenges-grid .map-project-wrap {
|
||||
flex: 1 1 100px;
|
||||
}
|
||||
.map-challenge-title-grid a.map-grid-item {
|
||||
|
||||
.map-challenges-grid .map-challenge-wrap {
|
||||
margin: 6px 0;
|
||||
max-width: 3.4rem;
|
||||
}
|
||||
|
||||
.map-challenge-wrap a.map-grid-item {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 3.4rem;
|
||||
height: 3.4rem;
|
||||
min-width: 24px;
|
||||
min-height: 24px;
|
||||
border: 1px dashed var(--background-quaternary);
|
||||
}
|
||||
|
||||
.map-dialogue-wrap {
|
||||
grid-column: 1 / -1;
|
||||
margin: 0 auto 6px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.map-dialogue-wrap a {
|
||||
align-items: center;
|
||||
min-height: 50px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.block-description {
|
||||
padding: 18px 0;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@ import { SuperBlocks } from '../../../shared/config/superblocks';
|
||||
const gridBasedSuperBlocks = [
|
||||
SuperBlocks.RespWebDesignNew,
|
||||
SuperBlocks.JsAlgoDataStructNew,
|
||||
SuperBlocks.SciCompPy
|
||||
SuperBlocks.SciCompPy,
|
||||
SuperBlocks.A2English
|
||||
];
|
||||
|
||||
export const isGridBased = (
|
||||
|
||||
Reference in New Issue
Block a user