From 513f27e408b16d877766882b20167a76f9692729 Mon Sep 17 00:00:00 2001
From: Ahmad Abdolsaheb
Date: Tue, 30 Nov 2021 20:35:35 +0300
Subject: [PATCH] feat: add seasonal learn alert (#44335)
* feat: add seasonal learn alert
* Update client/src/components/Intro/index.tsx
Co-authored-by: Oliver Eyton-Williams
* Update client/src/pages/learn.tsx
Co-authored-by: Oliver Eyton-Williams
Co-authored-by: Oliver Eyton-Williams
---
client/i18n/locales/english/translations.json | 3 ++
client/src/components/Intro/index.tsx | 31 ++++++++++++++++++-
client/src/components/helpers/link.tsx | 1 +
client/src/components/layouts/global.css | 26 ++++++++++++++++
client/src/pages/learn.tsx | 25 +++++++++++++--
config/donation-settings.js | 2 +-
6 files changed, 84 insertions(+), 4 deletions(-)
diff --git a/client/i18n/locales/english/translations.json b/client/i18n/locales/english/translations.json
index b2baf28f22..bb7e7b5b60 100644
--- a/client/i18n/locales/english/translations.json
+++ b/client/i18n/locales/english/translations.json
@@ -32,6 +32,7 @@
"profile": "Profile",
"news": "News",
"donate": "Donate",
+ "support-our-nonprofit": "Support our non-profit",
"update-settings": "Update my account settings",
"sign-me-out": "Sign me out of freeCodeCamp",
"flag-user": "Flag This User's Account for Abuse",
@@ -290,6 +291,8 @@
},
"help-translate": "We are still translating the following certifications.",
"help-translate-link": "Help us translate.",
+ "season-greetings": "Season's Greetings to you and your family.",
+ "if-getting-value": "If you're getting a lot out of freeCodeCamp, now is a great time to donate to support our nonprofit's mission.",
"project-preview-title": "Here's a preview of what you will build"
},
"donate": {
diff --git a/client/src/components/Intro/index.tsx b/client/src/components/Intro/index.tsx
index 75ff90cddc..4255af0455 100644
--- a/client/src/components/Intro/index.tsx
+++ b/client/src/components/Intro/index.tsx
@@ -1,5 +1,7 @@
+import { Alert } from '@freecodecamp/react-bootstrap';
import React from 'react';
import { Trans, useTranslation } from 'react-i18next';
+import { emailToABVariant } from '../../utils/A-B-tester';
import { randomQuote } from '../../utils/get-words';
import Login from '../Header/components/Login';
import { Link, Spacer, Loader, FullWidthRow } from '../helpers';
@@ -16,6 +18,8 @@ interface IntroProps {
pending?: boolean;
slug?: string;
username?: string;
+ email?: string;
+ onAlertClick?: () => void;
}
const Intro = ({
@@ -24,9 +28,16 @@ const Intro = ({
pending,
complete,
completedChallengeCount,
- slug
+ slug,
+ email,
+ onAlertClick
}: IntroProps): JSX.Element => {
const { t } = useTranslation();
+ const buttonVariation = (email: string | undefined): string => {
+ if (!email || emailToABVariant(email).isAVariant)
+ return t('buttons.donate');
+ return t('buttons.support-our-nonprofit');
+ };
if (pending && !complete) {
return (
<>
@@ -78,6 +89,24 @@ const Intro = ({
) : (
''
)}
+
+
+ {t('learn.season-greetings')}
+
+ {t('learn.if-getting-value')}
+
+
+
+ {buttonVariation(email)}
+
+
+
>
);
} else {
diff --git a/client/src/components/helpers/link.tsx b/client/src/components/helpers/link.tsx
index bc9dd2d672..f9704f5f39 100644
--- a/client/src/components/helpers/link.tsx
+++ b/client/src/components/helpers/link.tsx
@@ -8,6 +8,7 @@ interface LinkProps {
sameTab?: boolean;
state?: Record;
to: string;
+ onClick?: () => void;
}
const Link = ({
diff --git a/client/src/components/layouts/global.css b/client/src/components/layouts/global.css
index 6564d5cfc6..80ec16ee42 100644
--- a/client/src/components/layouts/global.css
+++ b/client/src/components/layouts/global.css
@@ -589,6 +589,32 @@ blockquote .small {
overflow-wrap: break-word;
}
+.alert .btn {
+ background-color: #d9edf7;
+ color: #31708f;
+ border-color: #31708f;
+}
+.alert .btn:hover,
+.alert .btn:focus {
+ background-color: #31708f;
+ color: #d9edf7;
+ border-color: #31708f;
+}
+
+.annual-donation-alert {
+ background: linear-gradient(
+ -10deg,
+ rgba(217, 237, 247, 1) 35%,
+ rgba(237, 202, 216, 0) 75%,
+ rgb(255 215 224) 100%
+ ),
+ radial-gradient(
+ circle,
+ rgba(255, 202, 225, 1) 0%,
+ rgba(218, 234, 252, 1) 100%
+ );
+}
+
/* gatsby 404 */
#search {
background-color: var(--quaternary-background);
diff --git a/client/src/pages/learn.tsx b/client/src/pages/learn.tsx
index 8c250a3ced..13022530a7 100644
--- a/client/src/pages/learn.tsx
+++ b/client/src/pages/learn.tsx
@@ -4,6 +4,7 @@ import React from 'react';
import Helmet from 'react-helmet';
import { useTranslation } from 'react-i18next';
import { connect } from 'react-redux';
+import { bindActionCreators, Dispatch } from 'redux';
import { createSelector } from 'reselect';
import Intro from '../components/Intro';
@@ -13,7 +14,8 @@ import LearnLayout from '../components/layouts/learn';
import {
userFetchStateSelector,
isSignedInSelector,
- userSelector
+ userSelector,
+ executeGA
} from '../redux';
interface FetchState {
@@ -23,6 +25,7 @@ interface FetchState {
}
interface User {
+ email: string;
name: string;
username: string;
completedChallengeCount: number;
@@ -53,12 +56,18 @@ interface LearnPageProps {
fields: Slug;
};
};
+ executeGA: (payload: Record) => void;
}
+const mapDispatchToProps = (dispatch: Dispatch) =>
+ bindActionCreators({ executeGA }, dispatch);
+
function LearnPage({
isSignedIn,
+ user,
fetchState: { pending, complete },
user: { name = '', completedChallengeCount = 0 },
+ executeGA,
data: {
challengeNode: {
fields: { slug }
@@ -67,6 +76,16 @@ function LearnPage({
}: LearnPageProps) {
const { t } = useTranslation();
+ const onAlertClick = () => {
+ executeGA({
+ type: 'event',
+ data: {
+ category: 'Donation Related',
+ action: `learn donation alert click`
+ }
+ });
+ };
+
return (
@@ -76,8 +95,10 @@ function LearnPage({
@@ -92,7 +113,7 @@ function LearnPage({
LearnPage.displayName = 'LearnPage';
-export default connect(mapStateToProps)(LearnPage);
+export default connect(mapStateToProps, mapDispatchToProps)(LearnPage);
export const query = graphql`
query FirstChallenge {
diff --git a/config/donation-settings.js b/config/donation-settings.js
index ebe13a7f84..ab9bdd8367 100644
--- a/config/donation-settings.js
+++ b/config/donation-settings.js
@@ -94,7 +94,7 @@ const patreonDefaultPledgeAmount = 500;
const aBTestConfig = {
isTesting: true,
- type: 'DistributionTest'
+ type: 'LearnAlertCTA'
};
module.exports = {