From b11ba378321a8b8e1d389e21528603daeeea043b Mon Sep 17 00:00:00 2001
From: Ahmad Abdolsaheb
Date: Tue, 15 Oct 2024 23:11:28 +0300
Subject: [PATCH] feat(client): update landing page ab tests (#56602)
---
.../config/growthbook-features-default.json | 32 ++++++
client/i18n/locales/english/translations.json | 25 ++++-
client/src/assets/icons/cap.tsx | 28 +++++
client/src/assets/icons/community.tsx | 44 ++++++++
client/src/assets/icons/curriculum.tsx | 26 +++++
client/src/assets/icons/free.tsx | 26 +++++
.../landing/components/benefits.tsx | 67 ++++++++++++
.../landing/components/campers-image.tsx | 25 +----
.../landing/components/landing-top-b.tsx | 27 ++---
.../landing/components/landing-top.tsx | 4 +-
client/src/components/landing/landing.css | 60 ++++++++--
client/src/components/layouts/global.css | 2 +-
client/src/pages/index.tsx | 41 ++++---
e2e/landing.spec.ts | 103 +++++++-----------
14 files changed, 374 insertions(+), 136 deletions(-)
create mode 100644 client/src/assets/icons/cap.tsx
create mode 100644 client/src/assets/icons/community.tsx
create mode 100644 client/src/assets/icons/curriculum.tsx
create mode 100644 client/src/assets/icons/free.tsx
create mode 100644 client/src/components/landing/components/benefits.tsx
diff --git a/client/config/growthbook-features-default.json b/client/config/growthbook-features-default.json
index f73e3d55181..7a16d1bd9ef 100644
--- a/client/config/growthbook-features-default.json
+++ b/client/config/growthbook-features-default.json
@@ -62,5 +62,37 @@
"name": "stg show modal randomly"
}
]
+ },
+ "show-benefits": {
+ "defaultValue": false,
+ "rules": [
+ {
+ "coverage": 1,
+ "hashAttribute": "id",
+ "seed": "show-benefits",
+ "hashVersion": 2,
+ "variations": [
+ false,
+ true
+ ],
+ "weights": [
+ 0.5,
+ 0.5
+ ],
+ "key": "show-benefits",
+ "meta": [
+ {
+ "key": "0",
+ "name": "Control"
+ },
+ {
+ "key": "1",
+ "name": "Variation 1"
+ }
+ ],
+ "phase": "0",
+ "name": "prod-show-benefits"
+ }
+ ]
}
}
\ No newline at end of file
diff --git a/client/i18n/locales/english/translations.json b/client/i18n/locales/english/translations.json
index 36d9999ecb7..6aa08815765 100644
--- a/client/i18n/locales/english/translations.json
+++ b/client/i18n/locales/english/translations.json
@@ -112,7 +112,7 @@
"big-heading-3": "Earn certifications.",
"big-heading-4": "All for free.",
"h2-heading": "Since 2014, more than 40,000 freeCodeCamp.org graduates have gotten jobs at tech companies including:",
- "h2-heading-b": "More than 100,000 freeCodeCamp.org graduates have gotten jobs at tech companies including:",
+ "h2-heading-b": "More than 100,000 freeCodeCamp.org graduates have gotten jobs at tech companies including:",
"hero-img-description": "freeCodeCamp students at a local study group in South Korea.",
"hero-img-alt": "A group of people, including a White man, a Black woman, and an Asian woman, gathered around a laptop.",
"hero-img-uis": "A group of screenshots showing the freeCodeCamp editor interface on both a mobile and desktop device and a certification.",
@@ -135,6 +135,29 @@
"testimony": "\"I've always struggled with learning JavaScript. I've taken many courses but freeCodeCamp's course was the one which stuck. Studying JavaScript as well as data structures and algorithms on freeCodeCamp gave me the skills and confidence I needed to land my dream job as a software engineer at Spotify.\""
}
},
+ "benefits": {
+ "heading": "Why learn with freeCodeCamp:",
+ "list": [
+ {
+ "title": "Large Community",
+ "description": "Join our vibrant learning community of students, alumni, and educators."
+ },
+ {
+ "title": "Free Education",
+ "description": "Learn from our charity and save money on your education. No paywalls. No hidden costs."
+ },
+ {
+ "title": "Extensive Certifications",
+ "description": "Earn industry-recognized, verifiable certifications in high-demand technologies."
+ },
+ {
+ "title": "Comprehensive Curriculum",
+ "description": "Enhance your technical skills with our linear, world-class, project-based curriculum."
+ }
+ ],
+ "cta": "Start Learning Now (it's free)"
+ },
+
"certification-heading": "Earn free verified certifications in:",
"core-certs-heading": "Earn free verified certifications with freeCodeCamp's core curriculum:",
"learn-english-heading": "Learn English for Developers:",
diff --git a/client/src/assets/icons/cap.tsx b/client/src/assets/icons/cap.tsx
new file mode 100644
index 00000000000..27d884de3d3
--- /dev/null
+++ b/client/src/assets/icons/cap.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+function FreeIcon(
+ props: JSX.IntrinsicAttributes & React.SVGProps
+): JSX.Element {
+ return (
+
+ );
+}
+
+FreeIcon.displayName = 'FreeIcon';
+
+export default FreeIcon;
diff --git a/client/src/assets/icons/community.tsx b/client/src/assets/icons/community.tsx
new file mode 100644
index 00000000000..8df72f013c3
--- /dev/null
+++ b/client/src/assets/icons/community.tsx
@@ -0,0 +1,44 @@
+import React from 'react';
+function CommunityIcon(
+ props: JSX.IntrinsicAttributes & React.SVGProps
+): JSX.Element {
+ return (
+
+ );
+}
+
+CommunityIcon.displayName = 'CommunityIcon';
+
+export default CommunityIcon;
diff --git a/client/src/assets/icons/curriculum.tsx b/client/src/assets/icons/curriculum.tsx
new file mode 100644
index 00000000000..1a97d5188c2
--- /dev/null
+++ b/client/src/assets/icons/curriculum.tsx
@@ -0,0 +1,26 @@
+import React from 'react';
+function CurriculumIcon(
+ props: JSX.IntrinsicAttributes & React.SVGProps
+): JSX.Element {
+ return (
+
+ );
+}
+
+CurriculumIcon.displayName = 'CurriculumIcon';
+
+export default CurriculumIcon;
diff --git a/client/src/assets/icons/free.tsx b/client/src/assets/icons/free.tsx
new file mode 100644
index 00000000000..5b6e5280d14
--- /dev/null
+++ b/client/src/assets/icons/free.tsx
@@ -0,0 +1,26 @@
+import React from 'react';
+function FreeIcon(
+ props: JSX.IntrinsicAttributes & React.SVGProps
+): JSX.Element {
+ return (
+
+ );
+}
+
+FreeIcon.displayName = 'FreeIcon';
+
+export default FreeIcon;
diff --git a/client/src/components/landing/components/benefits.tsx b/client/src/components/landing/components/benefits.tsx
new file mode 100644
index 00000000000..c6e0f697165
--- /dev/null
+++ b/client/src/components/landing/components/benefits.tsx
@@ -0,0 +1,67 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { Col, Row, Container } from '@freecodecamp/ui';
+
+import { Spacer } from '../../helpers';
+import FreeIcon from '../../../assets/icons/free';
+import CapIcon from '../../../assets/icons/cap';
+import CommunityIcon from '../../../assets/icons/community';
+import CurriculumIcon from '../../../assets/icons/curriculum';
+import BigCallToAction from './big-call-to-action';
+
+interface BenefitsItem {
+ title: string;
+ description: string;
+}
+
+const iconsList = [CommunityIcon, FreeIcon, CapIcon, CurriculumIcon];
+
+const Benefits = (): JSX.Element => {
+ const { t } = useTranslation();
+ const benefitItems: BenefitsItem[] = t('landing.benefits.list', {
+ returnObjects: true
+ });
+
+ return (
+
+
+
+
+
+ {t('landing.benefits.heading')}
+
+
+
+
+
+
+ {benefitItems.map((benefit, index) => {
+ const IconComponent = iconsList[index % iconsList.length]; // Get the correct icon component based on index
+ return (
+