From 829668c00f71b5b5c0699cae477873b76a67f5f1 Mon Sep 17 00:00:00 2001 From: Ruidy Nemausat Date: Tue, 2 Jun 2020 22:37:02 +0200 Subject: [PATCH] refactor: Profile folder --- src/pages/Profile.tsx | 239 ------------------------------- src/pages/Profile/About.tsx | 26 ++++ src/pages/Profile/Education.tsx | 38 +++++ src/pages/Profile/Experience.tsx | 34 +++++ src/pages/Profile/Github.tsx | 50 +++++++ src/pages/Profile/Top.tsx | 68 +++++++++ src/pages/Profile/index.tsx | 69 +++++++++ src/static/img/education.svg | 1 + src/static/img/experience.svg | 1 + src/static/img/github.svg | 1 + 10 files changed, 288 insertions(+), 239 deletions(-) delete mode 100644 src/pages/Profile.tsx create mode 100644 src/pages/Profile/About.tsx create mode 100644 src/pages/Profile/Education.tsx create mode 100644 src/pages/Profile/Experience.tsx create mode 100644 src/pages/Profile/Github.tsx create mode 100644 src/pages/Profile/Top.tsx create mode 100644 src/pages/Profile/index.tsx create mode 100644 src/static/img/education.svg create mode 100644 src/static/img/experience.svg create mode 100644 src/static/img/github.svg diff --git a/src/pages/Profile.tsx b/src/pages/Profile.tsx deleted file mode 100644 index 2f781e8..0000000 --- a/src/pages/Profile.tsx +++ /dev/null @@ -1,239 +0,0 @@ -import React, {FC} from 'react'; -// Redux -import {compose} from '@reduxjs/toolkit'; -import {firestoreConnect} from 'react-redux-firebase'; -import {connect} from 'react-redux'; -import {RootState} from '../store'; -// Routing -import {Link, useParams} from 'react-router-dom'; -import Routes from '../constants/routes'; -import NotFound from './NotFound'; -// Style -import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; -import { - faGithub, - faFacebook, - faInstagram, - faLinkedin, - faTwitter, - faYoutube, -} from '@fortawesome/free-brands-svg-icons'; -import { - faGlobe, - IconDefinition, - faCheck, - faStar, - faEye, - faCodeBranch, -} from '@fortawesome/free-solid-svg-icons'; -// Typing -import IDev, {getDescription} from '../models/Dev'; -import Experience from '../types/Experience'; -import {getTimePeriod} from '../types/TimePeriod'; -import Education from '../types/Education'; -import Repo from '../types/Repo'; - -interface IProps { - dev: IDev; -} - -/** - * Dev personal profile as seen by other people. - */ -const Profile: FC = ({dev}) => { - // display 404 page if dev is null - if (dev === null) { - return ; - } - - /** return the icon corresponding to the social name */ - const renderSocialIcon = (name: string): IconDefinition => { - switch (name) { - case 'facebook': - return faFacebook; - case 'github': - return faGithub; - case 'instagram': - return faInstagram; - case 'linkedin': - return faLinkedin; - case 'twitter': - return faTwitter; - case 'youtube': - return faYoutube; - default: - return faGlobe; - } - }; - - return dev === undefined ? ( -
Loading ...
- ) : ( -
- - Back to profiles - - -
-
- {dev.displayName} -

{dev.displayName}

-

{getDescription(dev.status, dev.company)}

-

{dev.location}

-
- {Object.entries(dev.links) - .sort() - .map(([icon, webAddress], i: number) => ( - - - - ))} -
-
- -
-

{`${dev.displayName}'s Bio`}

-

- {dev.bio.length === 0 - ? 'Add a short bio to present yourself!' - : dev.bio} -

-
-

Skill Set

-
- {dev.skills.length === 0 - ? 'Let us know about your skills!' - : dev.skills?.map((s: string, i: number) => ( -
- {s} -
- ))} -
-
- -
-

Experiences

- {dev.experiences.length === 0 ? ( -
- no experiences -
- ) : ( - dev.experiences.map((exp: Experience, i: number) => ( -
-

{exp.company}

-

{getTimePeriod(exp.from, exp.to)}

-

- Position: - {exp.position} -

-

- Description: - {exp.description} -

-
- )) - )} -
- -
-

Education

- {dev.educations.length === 0 ? ( -
- no educations -
- ) : ( - dev.educations.map((edu: Education, i: number) => ( -
-

{edu.school}

-

{getTimePeriod(edu.from, edu.to)}

-

- Degree: - {edu.degree} -

-

- Field: - {edu.field} -

-

- Description: - {edu.description} -

-
- )) - )} -
- -
-

- GitHub Repos -

- - {dev.repos?.length === 0 ? ( -
- no repositories -
- ) : ( - dev.repos.map((r: Repo, i: number) => ( -
-
-

- - {r.name} - -

-

{r.description}

-
-
-
    -
  • - Stars: {r.stars} -
  • -
  • - Watchers: {r.watchers} -
  • -
  • - Forks: {r.forks} -
  • -
-
-
- )) - )} -
-
-
- ); -}; - -/** - * Container to fetch id params from thr URI and pass it to Profile page - */ -const ProfileContainer: FC = () => { - const {id} = useParams(); - - const Component = compose( - firestoreConnect(() => [`users/${id}`]), - connect(({firestore: {data}}: RootState) => ({ - dev: data.users && data.users[id], - })), - )(Profile); - - return ; -}; - -export default ProfileContainer; diff --git a/src/pages/Profile/About.tsx b/src/pages/Profile/About.tsx new file mode 100644 index 0000000..bc7d6dc --- /dev/null +++ b/src/pages/Profile/About.tsx @@ -0,0 +1,26 @@ +import React, {FC} from 'react'; +// Styling +import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; +import {faCheck} from '@fortawesome/free-solid-svg-icons'; + +import IDev from '../../models/Dev'; + +const ProfileAbout: FC = ({displayName, bio, skills}) => ( +
+

{`${displayName}'s Bio`}

+

{bio.length === 0 ? 'Add a short bio to present yourself!' : bio}

+
+

Skill Set

+
+ {skills.length === 0 + ? 'Let us know about your skills!' + : skills?.map((s: string, i: number) => ( +
+ {s} +
+ ))} +
+
+); + +export default React.memo(ProfileAbout); diff --git a/src/pages/Profile/Education.tsx b/src/pages/Profile/Education.tsx new file mode 100644 index 0000000..20d253f --- /dev/null +++ b/src/pages/Profile/Education.tsx @@ -0,0 +1,38 @@ +import React, {FC} from 'react'; + +import Education from '../../types/Education'; +import {getTimePeriod} from '../../types/TimePeriod'; + +import educationPicture from '../../static/img/education.svg'; + +const ProfileEducation: FC<{educations: Education[]}> = ({educations}) => ( +
+

Education

+ {educations.length === 0 ? ( +
+ no educations +
+ ) : ( + educations.map((edu: Education, i: number) => ( +
+

{edu.school}

+

{getTimePeriod(edu.from, edu.to)}

+

+ Degree: + {edu.degree} +

+

+ Field: + {edu.field} +

+

+ Description: + {edu.description} +

+
+ )) + )} +
+); + +export default React.memo(ProfileEducation); diff --git a/src/pages/Profile/Experience.tsx b/src/pages/Profile/Experience.tsx new file mode 100644 index 0000000..2c06733 --- /dev/null +++ b/src/pages/Profile/Experience.tsx @@ -0,0 +1,34 @@ +import React, {FC} from 'react'; + +import Experience from '../../types/Experience'; +import {getTimePeriod} from '../../types/TimePeriod'; + +import expPicture from '../../static/img/experience.svg'; + +const ProfileExperience: FC<{experiences: Experience[]}> = ({experiences}) => ( +
+

Experiences

+ {experiences.length === 0 ? ( +
+ no experiences +
+ ) : ( + experiences.map((exp: Experience, i: number) => ( +
+

{exp.company}

+

{getTimePeriod(exp.from, exp.to)}

+

+ Position: + {exp.position} +

+

+ Description: + {exp.description} +

+
+ )) + )} +
+); + +export default ProfileExperience; diff --git a/src/pages/Profile/Github.tsx b/src/pages/Profile/Github.tsx new file mode 100644 index 0000000..27d120f --- /dev/null +++ b/src/pages/Profile/Github.tsx @@ -0,0 +1,50 @@ +import React, {FC} from 'react'; +import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; +import {faGithub} from '@fortawesome/free-brands-svg-icons'; +import {faStar, faEye, faCodeBranch} from '@fortawesome/free-solid-svg-icons'; + +import Repo from '../../types/Repo'; + +import githubPicture from '../../static/img/github.svg'; + +const ProfileGithub: FC<{repos: Repo[]}> = ({repos}) => ( +
+

+ GitHub Repos +

+ + {repos?.length === 0 ? ( +
+ no repositories +
+ ) : ( + repos.map((r: Repo, i: number) => ( +
+
+

+ + {r.name} + +

+

{r.description}

+
+
+
    +
  • + Stars: {r.stars} +
  • +
  • + Watchers: {r.watchers} +
  • +
  • + Forks: {r.forks} +
  • +
+
+
+ )) + )} +
+); + +export default React.memo(ProfileGithub); diff --git a/src/pages/Profile/Top.tsx b/src/pages/Profile/Top.tsx new file mode 100644 index 0000000..7355f9a --- /dev/null +++ b/src/pages/Profile/Top.tsx @@ -0,0 +1,68 @@ +import React, {FC} from 'react'; +// Styling +import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; +import {IconDefinition} from '@fortawesome/fontawesome-svg-core'; +import { + faFacebook, + faGithub, + faInstagram, + faLinkedin, + faTwitter, + faYoutube, +} from '@fortawesome/free-brands-svg-icons'; +import {faGlobe} from '@fortawesome/free-solid-svg-icons'; + +import IDev, {getDescription} from '../../models/Dev'; + +const ProfileTop: FC = ({ + avatarUrl, + displayName, + status, + company, + links, + location, +}) => { + /** return the icon corresponding to the social name */ + const renderSocialIcon = (name: string): IconDefinition => { + switch (name) { + case 'facebook': + return faFacebook; + case 'github': + return faGithub; + case 'instagram': + return faInstagram; + case 'linkedin': + return faLinkedin; + case 'twitter': + return faTwitter; + case 'youtube': + return faYoutube; + default: + return faGlobe; + } + }; + return ( +
+ {displayName} +

{displayName}

+

{getDescription(status, company)}

+

{location}

+
+ {Object.entries(links) + .sort() + .map(([icon, webAddress], i: number) => ( + + + + ))} +
+
+ ); +}; + +export default React.memo(ProfileTop); diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx new file mode 100644 index 0000000..5afe4b6 --- /dev/null +++ b/src/pages/Profile/index.tsx @@ -0,0 +1,69 @@ +import React, {FC} from 'react'; +// Redux +import {compose} from '@reduxjs/toolkit'; +import {firestoreConnect} from 'react-redux-firebase'; +import {connect} from 'react-redux'; +import {RootState} from '../../store'; +// Routing +import {Link, useParams} from 'react-router-dom'; +import Routes from '../../constants/routes'; +import NotFound from '../NotFound'; +// Typing +import IDev from '../../models/Dev'; + +import ProfileTop from './Top'; +import ProfileAbout from './About'; +import ProfileExperience from './Experience'; +import ProfileEducation from './Education'; +import ProfileGithub from './Github'; +import Collections from '../../constants/collections'; + +interface IProps { + dev: IDev; +} + +/** + * Dev personal profile as seen by other people. + */ +const ProfileComponent: FC = ({dev}) => { + // display 404 page if dev is null + if (dev === null) { + return ; + } + + return dev === undefined ? ( +
Loading ...
+ ) : ( +
+ + Back to profiles + + +
+ + + + + +
+
+ ); +}; + +/** + * Container to fetch id params from thr URI and pass it to Profile page + */ +const Profile: FC = () => { + const {id} = useParams(); + + const Component = compose( + firestoreConnect(() => [`${Collections.USERS}/${id}`]), + connect(({firestore: {data}}: RootState) => ({ + dev: data.users && data.users[id], + })), + )(ProfileComponent); + + return ; +}; + +export default Profile; diff --git a/src/static/img/education.svg b/src/static/img/education.svg new file mode 100644 index 0000000..23e7b84 --- /dev/null +++ b/src/static/img/education.svg @@ -0,0 +1 @@ +Graduation \ No newline at end of file diff --git a/src/static/img/experience.svg b/src/static/img/experience.svg new file mode 100644 index 0000000..61279e7 --- /dev/null +++ b/src/static/img/experience.svg @@ -0,0 +1 @@ +updated_resume \ No newline at end of file diff --git a/src/static/img/github.svg b/src/static/img/github.svg new file mode 100644 index 0000000..b86dc96 --- /dev/null +++ b/src/static/img/github.svg @@ -0,0 +1 @@ +version control \ No newline at end of file