diff --git a/client/i18n/locales/english/translations.json b/client/i18n/locales/english/translations.json
index 4b5d867f0b3..9825d391fa4 100644
--- a/client/i18n/locales/english/translations.json
+++ b/client/i18n/locales/english/translations.json
@@ -166,6 +166,7 @@
"professional-certs-heading": "Earn free professional certifications:",
"interview-prep-heading": "Prepare for the developer interview job search:",
"legacy-curriculum-heading": "Explore our Legacy Curriculum:",
+ "next-heading": "Try our beta curriculum:",
"upcoming-heading": "Upcoming curriculum:",
"faq": "Frequently asked questions:",
"faqs": [
diff --git a/client/src/components/Map/index.tsx b/client/src/components/Map/index.tsx
index 664559af93c..5addcad77bd 100644
--- a/client/src/components/Map/index.tsx
+++ b/client/src/components/Map/index.tsx
@@ -3,6 +3,8 @@ import { useTranslation } from 'react-i18next';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { Spacer } from '@freecodecamp/ui';
+import { useFeature } from '@growthbook/growthbook-react';
+
import {
type SuperBlocks,
SuperBlockStage,
@@ -60,6 +62,7 @@ const superBlockHeadings: { [key in SuperBlockStage]: string } = {
[SuperBlockStage.Extra]: 'landing.interview-prep-heading',
[SuperBlockStage.Legacy]: 'landing.legacy-curriculum-heading',
[SuperBlockStage.New]: '', // TODO: add translation
+ [SuperBlockStage.Next]: 'landing.next-heading',
[SuperBlockStage.Upcoming]: 'landing.upcoming-heading'
};
@@ -135,6 +138,7 @@ function Map({
allChallenges
}: MapProps): React.ReactElement {
const { t } = useTranslation();
+ const showNextCurriculum = useFeature('fcc-10').on;
const allSuperblockChallengesCompleted = (superblock: SuperBlocks) => {
// array of all challenge ID's in the superblock
@@ -161,7 +165,11 @@ function Map({
return (
- {getStageOrder({ showNewCurriculum, showUpcomingChanges }).map(stage => (
+ {getStageOrder({
+ showNewCurriculum,
+ showUpcomingChanges,
+ showNextCurriculum
+ }).map(stage => (
{t(superBlockHeadings[stage])}
diff --git a/curriculum/utils.js b/curriculum/utils.js
index cd80b423e23..1b6d95347f5 100644
--- a/curriculum/utils.js
+++ b/curriculum/utils.js
@@ -44,7 +44,8 @@ function createSuperOrder(superBlocks) {
const flatSuperBlockMap = generateSuperBlockList({
showNewCurriculum: process.env.SHOW_NEW_CURRICULUM === 'true',
- showUpcomingChanges: process.env.SHOW_UPCOMING_CHANGES === 'true'
+ showUpcomingChanges: process.env.SHOW_UPCOMING_CHANGES === 'true',
+ showNextCurriculum: true
});
const superOrder = createSuperOrder(flatSuperBlockMap);
diff --git a/shared/config/curriculum.test.ts b/shared/config/curriculum.test.ts
index d79940d63d8..eb3cab9efd1 100644
--- a/shared/config/curriculum.test.ts
+++ b/shared/config/curriculum.test.ts
@@ -20,10 +20,11 @@ describe('superBlockOrder', () => {
});
describe('generateSuperBlockList', () => {
- it('should return an array of SuperBlocks object with New and Upcoming when { showNewCurriculum: true, showUpcomingChanges: true }', () => {
+ it('should return an array of SuperBlocks object with all elements when if all configs are true', () => {
const result = generateSuperBlockList({
showNewCurriculum: true,
- showUpcomingChanges: true
+ showUpcomingChanges: true,
+ showNextCurriculum: true
});
expect(result).toHaveLength(Object.values(superBlockStages).flat().length);
});
@@ -31,13 +32,27 @@ describe('generateSuperBlockList', () => {
it('should return an array of SuperBlocks without New and Upcoming when { showNewCurriculum: false, showUpcomingChanges: false }', () => {
const result = generateSuperBlockList({
showNewCurriculum: false,
- showUpcomingChanges: false
+ showUpcomingChanges: false,
+ showNextCurriculum: true
});
const tempSuperBlockMap = { ...superBlockStages };
tempSuperBlockMap[SuperBlockStage.New] = [];
tempSuperBlockMap[SuperBlockStage.Upcoming] = [];
expect(result).toHaveLength(Object.values(tempSuperBlockMap).flat().length);
});
+
+ it('should exclude the Next SuperBlocks when { showNextCurriculum: false }', () => {
+ const result = generateSuperBlockList({
+ showNewCurriculum: false,
+ showUpcomingChanges: false,
+ showNextCurriculum: false
+ });
+ const tempSuperBlockMap = { ...superBlockStages };
+ tempSuperBlockMap[SuperBlockStage.New] = [];
+ tempSuperBlockMap[SuperBlockStage.Upcoming] = [];
+ tempSuperBlockMap[SuperBlockStage.Next] = [];
+ expect(result).toHaveLength(Object.values(tempSuperBlockMap).flat().length);
+ });
});
describe('Immutability of superBlockOrder, notAuditedSuperBlocks, and flatSuperBlockMap', () => {
diff --git a/shared/config/curriculum.ts b/shared/config/curriculum.ts
index 681f4ca5309..48d21adabf5 100644
--- a/shared/config/curriculum.ts
+++ b/shared/config/curriculum.ts
@@ -35,6 +35,10 @@ export enum SuperBlocks {
*
* SuperBlockStages.Upcoming = SHOW_UPCOMING_CHANGES === 'true'
* 'Upcoming' is for development -> not shown on stag or prod anywhere
+ *
+ * SuperBlockStages.Next = deployed, but only shown if the Growthbook feature
+ * is enabled.
+ *
*/
export enum SuperBlockStage {
Core,
@@ -43,11 +47,13 @@ export enum SuperBlockStage {
Extra,
Legacy,
New,
- Upcoming
+ Upcoming,
+ Next
}
const defaultStageOrder = [
SuperBlockStage.Core,
+ SuperBlockStage.Next,
SuperBlockStage.English,
SuperBlockStage.Professional,
SuperBlockStage.Extra,
@@ -56,9 +62,12 @@ const defaultStageOrder = [
export function getStageOrder({
showNewCurriculum,
- showUpcomingChanges
+ showUpcomingChanges,
+ showNextCurriculum
}: Config): SuperBlockStage[] {
- const stageOrder = [...defaultStageOrder];
+ const stageOrder = showNextCurriculum
+ ? [...defaultStageOrder]
+ : [...defaultStageOrder.filter(stage => stage !== SuperBlockStage.Next)];
if (showNewCurriculum) stageOrder.push(SuperBlockStage.New);
if (showUpcomingChanges) stageOrder.push(SuperBlockStage.Upcoming);
@@ -85,6 +94,7 @@ export const superBlockStages: StageMap = {
SuperBlocks.MachineLearningPy,
SuperBlocks.CollegeAlgebraPy
],
+ [SuperBlockStage.Next]: [SuperBlocks.FullStackDeveloper],
[SuperBlockStage.English]: [SuperBlocks.A2English],
[SuperBlockStage.Professional]: [SuperBlocks.FoundationalCSharp],
[SuperBlockStage.Extra]: [
@@ -99,10 +109,7 @@ export const superBlockStages: StageMap = {
SuperBlocks.PythonForEverybody
],
[SuperBlockStage.New]: [],
- [SuperBlockStage.Upcoming]: [
- SuperBlocks.B1English,
- SuperBlocks.FullStackDeveloper
- ]
+ [SuperBlockStage.Upcoming]: [SuperBlocks.B1English]
};
Object.freeze(superBlockStages);
@@ -246,6 +253,7 @@ Object.freeze(notAuditedSuperBlocks);
type Config = {
showNewCurriculum: boolean;
showUpcomingChanges: boolean;
+ showNextCurriculum: boolean;
};
export function generateSuperBlockList(config: Config): SuperBlocks[] {
@@ -266,7 +274,8 @@ export function getAuditedSuperBlocks({
// To find the audited superblocks, we need to start with all superblocks.
const flatSuperBlockMap = generateSuperBlockList({
showNewCurriculum: true,
- showUpcomingChanges: true
+ showUpcomingChanges: true,
+ showNextCurriculum: true
});
const auditedSuperBlocks = flatSuperBlockMap.filter(
superBlock =>