diff --git a/client/src/client-only-routes/show-profile-or-four-oh-four.tsx b/client/src/client-only-routes/show-profile-or-four-oh-four.tsx
index 59c01ace546..278babafdde 100644
--- a/client/src/client-only-routes/show-profile-or-four-oh-four.tsx
+++ b/client/src/client-only-routes/show-profile-or-four-oh-four.tsx
@@ -7,12 +7,6 @@ import FourOhFour from '../components/FourOhFour';
import Loader from '../components/helpers/loader';
import Profile from '../components/profile/profile';
import { fetchProfileForUser } from '../redux/actions';
-
-import {
- submitNewAbout,
- updateMyPortfolio,
- updateMySocials
-} from '../redux/settings/actions';
import {
usernameSelector,
userByNameSelector,
@@ -63,23 +57,14 @@ const makeMapStateToProps =
const mapDispatchToProps: {
fetchProfileForUser: ShowProfileOrFourOhFourProps['fetchProfileForUser'];
- submitNewAbout: () => void;
- updateMyPortfolio: () => void;
- updateMySocials: (formValues: Socials) => void;
} = {
- fetchProfileForUser,
- submitNewAbout,
- updateMyPortfolio,
- updateMySocials
+ fetchProfileForUser
};
function ShowProfileOrFourOhFour({
requestedUser,
maybeUser,
fetchProfileForUser,
- submitNewAbout,
- updateMyPortfolio,
- updateMySocials,
isSessionUser,
showLoading
}: ShowProfileOrFourOhFourProps) {
@@ -104,13 +89,7 @@ function ShowProfileOrFourOhFour({
)
) : (
-
+
);
}
diff --git a/client/src/components/profile/__snapshots__/profile.test.tsx.snap b/client/src/components/profile/__snapshots__/profile.test.tsx.snap
index 522fc732f30..cdba6c2afb4 100644
--- a/client/src/components/profile/__snapshots__/profile.test.tsx.snap
+++ b/client/src/components/profile/__snapshots__/profile.test.tsx.snap
@@ -187,17 +187,12 @@ exports[` renders correctly 1`] = `
string
-
-
-
-
-
+ />
diff --git a/client/src/components/profile/components/about.tsx b/client/src/components/profile/components/about.tsx
index 953219f683e..d6e53d47510 100644
--- a/client/src/components/profile/components/about.tsx
+++ b/client/src/components/profile/components/about.tsx
@@ -10,27 +10,32 @@ import type { TFunction } from 'i18next';
import { withTranslation } from 'react-i18next';
import isURL from 'validator/lib/isURL';
+import { connect } from 'react-redux';
import { FullWidthRow } from '../../helpers';
import BlockSaveButton from '../../helpers/form/block-save-button';
import SectionHeader from '../../settings/section-header';
-import type { CamperProps } from './camper';
+import { User } from '../../../redux/prop-types';
+import { submitNewAbout } from '../../../redux/settings/actions';
-type AboutProps = Omit<
- CamperProps,
- | 'linkedin'
- | 'joinDate'
- | 'isDonating'
- | 'githubProfile'
- | 'twitter'
- | 'website'
- | 'yearsTopContributor'
-> & {
+type AboutProps = {
+ user: User;
t: TFunction;
submitNewAbout: (formValues: FormValues) => void;
setIsEditing: (isEditing: boolean) => void;
};
-type FormValues = Pick
;
+type FormValues = {
+ name: string;
+ location: string;
+ picture: string;
+ about: string;
+};
+
+const mapDispatchToProps: {
+ submitNewAbout: () => void;
+} = {
+ submitNewAbout
+};
const ShowImageValidationWarning = ({
alertContent
@@ -45,14 +50,13 @@ const ShowImageValidationWarning = ({
};
const AboutSettings = ({
+ user,
t,
- name = '',
- location = '',
- picture = '',
- about = '',
submitNewAbout,
setIsEditing
}: AboutProps) => {
+ const { name = '', location = '', picture = '', about = '' } = user;
+
const [formValues, setFormValues] = useState({
name,
location,
@@ -235,4 +239,6 @@ const AboutSettings = ({
AboutSettings.displayName = 'AboutSettings';
-export default withTranslation()(AboutSettings);
+export default withTranslation()(
+ connect(null, mapDispatchToProps)(AboutSettings)
+);
diff --git a/client/src/components/profile/components/bio.tsx b/client/src/components/profile/components/bio.tsx
index 9c142695fad..7cc4d0aeb6d 100644
--- a/client/src/components/profile/components/bio.tsx
+++ b/client/src/components/profile/components/bio.tsx
@@ -8,25 +8,33 @@ import {
import { useTranslation } from 'react-i18next';
import { Button, Spacer } from '@freecodecamp/ui';
import { AvatarRenderer, FullWidthRow } from '../../helpers';
+import { User } from '../../../redux/prop-types';
import { parseDate } from './utils';
import SocialIcons from './social-icons';
-import { type CamperProps } from './camper';
-const Bio = ({
- joinDate,
- location,
- username,
- name,
- about,
- githubProfile,
- linkedin,
- twitter,
- website,
- isDonating,
- yearsTopContributor,
- picture,
- setIsEditing,
- isSessionUser
-}: CamperProps) => {
+
+type BioProps = {
+ user: User;
+ setIsEditing: (value: boolean) => void;
+ isSessionUser: boolean;
+};
+
+const Bio = ({ user, setIsEditing, isSessionUser }: BioProps) => {
+ const {
+ joinDate,
+ location,
+ username,
+ name,
+ about,
+ githubProfile,
+ linkedin,
+ twitter,
+ website,
+ isDonating,
+ yearsTopContributor,
+ picture,
+ profileUI: { showAbout, showLocation, showDonation }
+ } = user;
+
const { t } = useTranslation();
const isTopContributor =
@@ -38,7 +46,7 @@ const Bio = ({
@@ -56,17 +64,17 @@ const Bio = ({
)}
- {name && {name}
}
+ {name && showAbout && {name}
}
- {about && {about}
}
+ {showAbout && {about}
}
- {joinDate && (
+ {joinDate && showAbout && (
{parseDate(joinDate, t)}
)}
- {location && (
+ {location && showLocation && (
{t('profile.from', { location })}
diff --git a/client/src/components/profile/components/camper.tsx b/client/src/components/profile/components/camper.tsx
index 54b637a8fc6..c03c619e041 100644
--- a/client/src/components/profile/components/camper.tsx
+++ b/client/src/components/profile/components/camper.tsx
@@ -7,64 +7,35 @@ import SupporterBadgeEmblem from '../../../assets/icons/supporter-badge-emblem';
import TopContibutorBadgeEmblem from '../../../assets/icons/top-contributor-badge-emblem';
import Bio from './bio';
-export type CamperProps = Pick<
- User,
- | 'about'
- | 'githubProfile'
- | 'isDonating'
- | 'linkedin'
- | 'username'
- | 'twitter'
- | 'yearsTopContributor'
- | 'location'
- | 'website'
- | 'picture'
- | 'name'
- | 'joinDate'
-> & {
+export type CamperProps = {
+ user: User;
setIsEditing: (value: boolean) => void;
isSessionUser: boolean;
};
function Camper({
- name,
- username,
- location,
- picture,
- about,
- yearsTopContributor,
- githubProfile,
- isDonating,
- joinDate,
- linkedin,
- twitter,
- website,
+ user,
isSessionUser,
setIsEditing
}: CamperProps): JSX.Element {
+ const {
+ isDonating,
+ yearsTopContributor,
+ profileUI: { showDonation }
+ } = user;
+
const { t } = useTranslation();
const isTopContributor = yearsTopContributor.filter(Boolean).length > 0;
return (
<>
- {(isDonating || isTopContributor) && (
+ {((isDonating && showDonation) || isTopContributor) && (
{t('profile.badges')}
diff --git a/client/src/components/profile/components/internet.tsx b/client/src/components/profile/components/internet.tsx
index 322b8776f55..5220ad42619 100644
--- a/client/src/components/profile/components/internet.tsx
+++ b/client/src/components/profile/components/internet.tsx
@@ -12,11 +12,14 @@ import {
type FormGroupProps
} from '@freecodecamp/ui';
+import { connect } from 'react-redux';
import { maybeUrlRE } from '../../../utils';
import { FullWidthRow } from '../../helpers';
import BlockSaveButton from '../../helpers/form/block-save-button';
import SectionHeader from '../../settings/section-header';
+import { User } from '../../../redux/prop-types';
+import { updateMySocials } from '../../../redux/settings/actions';
export interface Socials {
githubProfile: string;
@@ -25,9 +28,10 @@ export interface Socials {
website: string;
}
-interface InternetProps extends Socials {
+interface InternetProps {
+ user: User;
t: TFunction;
- updateSocials: (formValues: Socials) => void;
+ updateMySocials: (formValues: Socials) => void;
setIsEditing: (isEditing: boolean) => void;
}
@@ -40,15 +44,25 @@ function Info({ message }: { message: string }) {
return message ? {message} : null;
}
+const mapDispatchToProps: {
+ updateMySocials: (formValues: Socials) => void;
+} = {
+ updateMySocials
+};
+
const InternetSettings = ({
- githubProfile = '',
- linkedin = '',
- twitter = '',
- website = '',
+ user,
t,
- updateSocials,
+ updateMySocials,
setIsEditing
}: InternetProps) => {
+ const {
+ githubProfile = '',
+ linkedin = '',
+ twitter = '',
+ website = ''
+ } = user;
+
const [formValues, setFormValues] = useState({
githubProfile,
linkedin,
@@ -101,7 +115,7 @@ const InternetSettings = ({
e.preventDefault();
if (!isFormPristine() && isFormValid()) {
// Only submit the form if is has changed, and if it is valid
- updateSocials({ ...formValues });
+ updateMySocials({ ...formValues });
}
setIsEditing(false);
};
@@ -256,4 +270,6 @@ const Check = ({
InternetSettings.displayName = 'InternetSettings';
-export default withTranslation()(InternetSettings);
+export default withTranslation()(
+ connect(null, mapDispatchToProps)(InternetSettings)
+);
diff --git a/client/src/components/profile/components/portfolio.tsx b/client/src/components/profile/components/portfolio.tsx
index 5686a690b19..e4f65d16210 100644
--- a/client/src/components/profile/components/portfolio.tsx
+++ b/client/src/components/profile/components/portfolio.tsx
@@ -13,6 +13,7 @@ import {
} from '@freecodecamp/ui';
import { withTranslation } from 'react-i18next';
import isURL from 'validator/lib/isURL';
+import { connect } from 'react-redux';
import { PortfolioProjectData } from '../../../redux/prop-types';
import { hasProtocolRE } from '../../../utils';
@@ -20,12 +21,13 @@ import { hasProtocolRE } from '../../../utils';
import { FullWidthRow } from '../../helpers';
import BlockSaveButton from '../../helpers/form/block-save-button';
import SectionHeader from '../../settings/section-header';
+import { updateMyPortfolio } from '../../../redux/settings/actions';
type PortfolioProps = {
picture?: string;
portfolio: PortfolioProjectData[];
t: TFunction;
- updatePortfolio: (obj: { portfolio: PortfolioProjectData[] }) => void;
+ updateMyPortfolio: (obj: { portfolio: PortfolioProjectData[] }) => void;
username?: string;
setIsEditing: (isEditing: boolean) => void;
};
@@ -35,6 +37,12 @@ interface ProfileValidation {
message: string;
}
+const mapDispatchToProps: {
+ updateMyPortfolio: () => void;
+} = {
+ updateMyPortfolio
+};
+
function createEmptyPortfolioItem(): PortfolioProjectData {
return {
id: nanoid(),
@@ -54,7 +62,7 @@ const PortfolioSettings = (props: PortfolioProps) => {
t,
portfolio: initialPortfolio = [],
setIsEditing,
- updatePortfolio
+ updateMyPortfolio
} = props;
const [portfolio, setPortfolio] = useState(initialPortfolio);
const [unsavedItemId, setUnsavedItemId] = useState(null);
@@ -105,7 +113,7 @@ const PortfolioSettings = (props: PortfolioProps) => {
setUnsavedItemId(null);
}
const portfolioToUpdate = updatedPortfolio || portfolio;
- updatePortfolio({ portfolio: portfolioToUpdate });
+ updateMyPortfolio({ portfolio: portfolioToUpdate });
setIsEditing(false);
};
@@ -384,4 +392,6 @@ const PortfolioSettings = (props: PortfolioProps) => {
PortfolioSettings.displayName = 'PortfolioSettings';
-export default withTranslation()(PortfolioSettings);
+export default withTranslation()(
+ connect(null, mapDispatchToProps)(PortfolioSettings)
+);
diff --git a/client/src/components/profile/profile.tsx b/client/src/components/profile/profile.tsx
index fb36b1772e6..73d0ab97d1c 100644
--- a/client/src/components/profile/profile.tsx
+++ b/client/src/components/profile/profile.tsx
@@ -8,7 +8,7 @@ import Portfolio from './components/portfolio';
import UsernameSettings from './components/username';
import About from './components/about';
-import Internet, { Socials } from './components/internet';
+import Internet from './components/internet';
import { User } from './../../redux/prop-types';
import Timeline from './components/time-line';
import Camper from './components/camper';
@@ -21,9 +21,6 @@ import { PortfolioProjects } from './components/portfolio-projects';
interface ProfileProps {
isSessionUser: boolean;
user: User;
- updateMyPortfolio: () => void;
- updateMySocials: (formValues: Socials) => void;
- submitNewAbout: () => void;
}
interface EditModalProps {
@@ -31,9 +28,6 @@ interface EditModalProps {
isEditing: boolean;
isSessionUser: boolean;
setIsEditing: (isEditing: boolean) => void;
- updateMySocials: (formValues: Socials) => void;
- updateMyPortfolio: () => void;
- submitNewAbout: () => void;
}
interface MessageProps {
isSessionUser: boolean;
@@ -50,27 +44,8 @@ const UserMessage = ({ t }: Pick) => {
);
};
-const EditModal = ({
- user,
- isEditing,
- isSessionUser,
- setIsEditing,
- updateMyPortfolio,
- updateMySocials,
- submitNewAbout
-}: EditModalProps) => {
- const {
- portfolio,
- username,
- about,
- location,
- name,
- picture,
- githubProfile,
- linkedin,
- twitter,
- website
- } = user;
+const EditModal = ({ user, isEditing, setIsEditing }: EditModalProps) => {
+ const { portfolio, username } = user;
const { t } = useTranslation();
return (
setIsEditing(false)} open={isEditing} size='large'>
@@ -78,31 +53,11 @@ const EditModal = ({
-
+
-
+
-
+
);
@@ -129,43 +84,22 @@ const Message = ({ isSessionUser, t, username }: MessageProps) => {
return ;
};
-function UserProfile({
- user,
- isSessionUser,
- updateMyPortfolio,
- updateMySocials,
- submitNewAbout
-}: ProfileProps): JSX.Element {
+function UserProfile({ user, isSessionUser }: ProfileProps): JSX.Element {
const [isEditing, setIsEditing] = useState(false);
const {
profileUI: {
- showAbout,
showCerts,
- showDonation,
showHeatMap,
- showLocation,
- showName,
showPoints,
showPortfolio,
showTimeLine
},
calendar,
completedChallenges,
- githubProfile,
- linkedin,
- twitter,
- website,
- name,
username,
- joinDate,
- location,
points,
- picture,
- portfolio,
- about,
- yearsTopContributor,
- isDonating
+ portfolio
} = user;
return (
@@ -176,24 +110,10 @@ function UserProfile({
isEditing={isEditing}
isSessionUser={isSessionUser}
setIsEditing={setIsEditing}
- updateMyPortfolio={updateMyPortfolio}
- updateMySocials={updateMySocials}
- submitNewAbout={submitNewAbout}
/>
)}
@@ -211,13 +131,7 @@ function UserProfile({
);
}
-function Profile({
- user,
- isSessionUser,
- updateMyPortfolio,
- updateMySocials,
- submitNewAbout
-}: ProfileProps): JSX.Element {
+function Profile({ user, isSessionUser }: ProfileProps): JSX.Element {
const { t } = useTranslation();
const {
profileUI: { isLocked },
@@ -238,13 +152,7 @@ function Profile({
)}
{showUserProfile && (
-
+
)}
{!isSessionUser && (