refactor: EditProfile folder

This commit is contained in:
Ruidy Nemausat 2020-06-02 19:22:15 +02:00
parent b3faf506f2
commit 80895656b6
3 changed files with 358 additions and 319 deletions

View file

@ -1,319 +0,0 @@
import React, {FC, useState} from 'react';
import {Link} from 'react-router-dom';
import Routes from '../constants/routes';
// Redux
import {enhance} from '../store/firebase';
import {WithFirebaseProps} from 'react-redux-firebase';
// Style
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {
faTwitter,
faFacebook,
faYoutube,
faLinkedin,
faInstagram,
} from '@fortawesome/free-brands-svg-icons';
import FormHeader from '../components/FormHeader';
import Alert from '../components/Alert';
import Statuses from '../constants/statuses';
// Form
import useForm from '../hooks';
import getGithubRepos from '../services/github';
// Typing
import Dev from '../models/Dev';
import User from '../models/User';
import Links, {parseLink, getGithubLink} from '../types/Links';
import IAlert, {formAlert} from '../types/Alert';
interface FormData {
status: string;
company: string;
website: string;
location: string;
skills: string;
github: string;
bio: string;
facebook: string;
linkedin: string;
instagram: string;
twitter: string;
youtube: string;
}
interface IProps extends Dev, WithFirebaseProps<User> {}
/**
* Form to update dev's personal information.
*/
const EditProfile: FC<IProps> = ({
firebase,
status,
skills,
company,
links,
location,
bio,
github,
}) => {
const [showLinks, setShowLinks] = useState(false);
const [alert, setAlert] = useState<IAlert>(formAlert);
const initFormData = {
status: status ?? 'Developer',
company: company,
location: location ?? '',
bio: bio ?? '',
skills: skills?.toString() ?? '',
website: links?.website ?? '',
github: github ?? '',
facebook: links?.facebook ?? '',
linkedin: links?.linkedin ?? '',
instagram: links?.instagram ?? '',
twitter: links?.twitter ?? '',
youtube: links?.youtube ?? '',
};
const {formData, handleChange} = useForm<FormData>(initFormData);
/** construct profile object from formData */
const makeProfile = async ({
status,
company,
location,
bio,
website,
instagram,
facebook,
linkedin,
twitter,
github,
youtube,
skills,
}: FormData) => {
const newLinks: Links = {
website: parseLink(website),
instagram: parseLink(instagram),
facebook: parseLink(facebook),
linkedin: parseLink(linkedin),
twitter: parseLink(twitter),
github: getGithubLink(github),
youtube: parseLink(youtube),
};
const newSkills: string[] = skills?.split(',');
const newRepos = await getGithubRepos(github);
return {
status,
company,
location,
bio,
github,
links: newLinks,
skills: newSkills,
repos: newRepos,
};
};
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const updatedDev = await makeProfile(formData);
try {
firebase.updateProfile(updatedDev, {useSet: true, merge: true});
setAlert({
show: true,
color: 'success',
text:
'Profile successfully updated. You may go back to your dashboard.',
});
} catch (err) {
console.error(err);
setAlert({...alert, show: true});
}
};
const isDisabled: boolean = formData.status === '' || formData.skills === '';
const toggleSocialLinks = () => setShowLinks(!showLinks);
return (
<section className="container">
<FormHeader
title="Edit your profile"
lead="Let's get some information to make your profile stand out"
/>
<form className="form" onSubmit={handleSubmit}>
<div className="form-group">
<select
name="status"
required
onChange={handleChange}
defaultValue={formData.status}
>
<option disabled>* Select Professional Status</option>
{Statuses.map((s: string, i: number) => (
<option value={s} key={i}>
{s}
</option>
))}
</select>
<small className="form-text">
Give us an idea of where you are at in your career
</small>
</div>
<div className="form-group">
<input
type="text"
placeholder="Company"
name="company"
value={formData.company}
// value={variable}
onChange={handleChange}
/>
<small className="form-text">
Could be your own company or one you work for
</small>
</div>
<div className="form-group">
<input
type="text"
placeholder="Website"
name="website"
value={formData.website}
onChange={handleChange}
/>
<small className="form-text">
Could be your own or a company website
</small>
</div>
<div className="form-group">
<input
type="text"
placeholder="Location"
name="location"
value={formData.location}
onChange={handleChange}
/>
<small className="form-text">
City & state suggested (eg. Boston, MA)
</small>
</div>
<div className="form-group">
<input
type="text"
placeholder="* Skills"
name="skills"
required
value={formData.skills}
onChange={handleChange}
/>
<small className="form-text">
Please use comma separated values (eg. HTML,CSS,JavaScript,PHP)
</small>
</div>
<div className="form-group">
<input
type="text"
placeholder="Github Username"
name="github"
value={formData.github}
onChange={handleChange}
/>
<small className="form-text">
If you want your latest repos and a Github link, include your
username
</small>
</div>
<div className="form-group">
<textarea
placeholder="A short bio of yourself"
name="bio"
value={formData.bio}
onChange={handleChange}
></textarea>
<small className="form-text">Tell us a little about yourself</small>
</div>
<div className="my-2">
<button
type="button"
className="btn btn-light"
onClick={toggleSocialLinks}
>
{showLinks ? 'Hide' : 'Add'} Social Network Links
</button>
<span>Optional</span>
</div>
{showLinks && (
<>
<div className="form-group social-input">
<FontAwesomeIcon icon={faFacebook} size="2x" />
<input
type="text"
placeholder="Facebook URL"
name="facebook"
value={formData.facebook}
onChange={handleChange}
/>
</div>
<div className="form-group social-input">
<FontAwesomeIcon icon={faInstagram} size="2x" />
<input
type="text"
placeholder="Instagram URL"
name="instagram"
value={formData.instagram}
onChange={handleChange}
/>
</div>
<div className="form-group social-input">
<FontAwesomeIcon icon={faLinkedin} size="2x" />
<input
type="text"
placeholder="Linkedin URL"
name="linkedin"
value={formData.linkedin}
onChange={handleChange}
/>
</div>
<div className="form-group social-input">
<FontAwesomeIcon icon={faTwitter} size="2x" />
<input
type="text"
placeholder="Twitter URL"
name="twitter"
value={formData.twitter}
onChange={handleChange}
/>
</div>
<div className="form-group social-input">
<FontAwesomeIcon icon={faYoutube} size="2x" />
<input
type="text"
placeholder="YouTube URL"
name="youtube"
value={formData.youtube}
onChange={handleChange}
/>
</div>
</>
)}
{alert.show && <Alert text={alert.text} color={alert.color} />}
<input
type="submit"
className="btn btn-primary my-1"
value="Submit"
disabled={isDisabled}
/>
<Link to={Routes.DASHBOARD} className="btn btn-light my-1">
Go Back
</Link>
</form>
</section>
);
};
export default enhance(EditProfile);

View file

@ -0,0 +1,211 @@
import React, {FC} from 'react';
// Routing
import {Link} from 'react-router-dom';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {
faFacebook,
faInstagram,
faLinkedin,
faTwitter,
faYoutube,
} from '@fortawesome/free-brands-svg-icons';
import {IProfileForm} from '.';
import Routes from '../../constants/routes';
import Statuses from '../../constants/statuses';
interface IProps {
showLinks: boolean;
isDisabled: boolean;
formData: IProfileForm;
handleSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
handleChange: (
e: React.ChangeEvent<
HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
>,
) => void;
toggleSocialLinks: () => void;
}
const EditProfileForm: FC<IProps> = ({
showLinks,
handleSubmit,
formData,
handleChange,
isDisabled,
toggleSocialLinks,
}) => (
<form className="form" onSubmit={handleSubmit}>
<div className="form-group">
<select
name="status"
required
onChange={handleChange}
defaultValue={formData.status}
>
<option disabled>* Select Professional Status</option>
{Statuses.map((s: string, i: number) => (
<option value={s} key={i}>
{s}
</option>
))}
</select>
<small className="form-text">
Give us an idea of where you are at in your career
</small>
</div>
<div className="form-group">
<input
type="text"
placeholder="Company"
name="company"
value={formData.company}
// value={variable}
onChange={handleChange}
/>
<small className="form-text">
Could be your own company or one you work for
</small>
</div>
<div className="form-group">
<input
type="text"
placeholder="Website"
name="website"
value={formData.website}
onChange={handleChange}
/>
<small className="form-text">
Could be your own or a company website
</small>
</div>
<div className="form-group">
<input
type="text"
placeholder="Location"
name="location"
value={formData.location}
onChange={handleChange}
/>
<small className="form-text">
City & state suggested (eg. Boston, MA)
</small>
</div>
<div className="form-group">
<input
type="text"
placeholder="* Skills"
name="skills"
required
value={formData.skills}
onChange={handleChange}
/>
<small className="form-text">
Please use comma separated values (eg. HTML,CSS,JavaScript,PHP)
</small>
</div>
<div className="form-group">
<input
type="text"
placeholder="Github Username"
name="github"
value={formData.github}
onChange={handleChange}
/>
<small className="form-text">
If you want your latest repos and a Github link, include your username
</small>
</div>
<div className="form-group">
<textarea
placeholder="A short bio of yourself"
name="bio"
value={formData.bio}
onChange={handleChange}
></textarea>
<small className="form-text">Tell us a little about yourself</small>
</div>
<div className="my-2">
<button
type="button"
className="btn btn-light"
onClick={toggleSocialLinks}
>
{showLinks ? 'Hide' : 'Add'} Social Network Links
</button>
<span>Optional</span>
</div>
{showLinks && (
<>
<div className="form-group social-input">
<FontAwesomeIcon icon={faFacebook} size="2x" />
<input
type="text"
placeholder="Facebook URL"
name="facebook"
value={formData.facebook}
onChange={handleChange}
/>
</div>
<div className="form-group social-input">
<FontAwesomeIcon icon={faInstagram} size="2x" />
<input
type="text"
placeholder="Instagram URL"
name="instagram"
value={formData.instagram}
onChange={handleChange}
/>
</div>
<div className="form-group social-input">
<FontAwesomeIcon icon={faLinkedin} size="2x" />
<input
type="text"
placeholder="Linkedin URL"
name="linkedin"
value={formData.linkedin}
onChange={handleChange}
/>
</div>
<div className="form-group social-input">
<FontAwesomeIcon icon={faTwitter} size="2x" />
<input
type="text"
placeholder="Twitter URL"
name="twitter"
value={formData.twitter}
onChange={handleChange}
/>
</div>
<div className="form-group social-input">
<FontAwesomeIcon icon={faYoutube} size="2x" />
<input
type="text"
placeholder="YouTube URL"
name="youtube"
value={formData.youtube}
onChange={handleChange}
/>
</div>
</>
)}
<input
type="submit"
className="btn btn-primary my-1"
value="Submit"
disabled={isDisabled}
/>
<Link to={Routes.DASHBOARD} className="btn btn-light my-1">
Go Back
</Link>
</form>
);
export default EditProfileForm;

View file

@ -0,0 +1,147 @@
import React, {FC, useState} from 'react';
// Redux
import {enhance} from '../../store/firebase';
import {WithFirebaseProps} from 'react-redux-firebase';
// Style
import FormHeader from '../../components/FormHeader';
import Alert from '../../components/Alert';
// Form
import useForm from '../../hooks';
import getGithubRepos from '../../services/github';
// Typing
import Dev from '../../models/Dev';
import User from '../../models/User';
import Links, {parseLink, getGithubLink} from '../../types/Links';
import IAlert, {formAlert} from '../../types/Alert';
import EditProfileForm from './Form';
export interface IProfileForm {
status: string;
company: string;
website: string;
location: string;
skills: string;
github: string;
bio: string;
facebook: string;
linkedin: string;
instagram: string;
twitter: string;
youtube: string;
}
interface IProps extends Dev, WithFirebaseProps<User> {}
/**
* Form to update dev's personal information.
*/
const EditProfile: FC<IProps> = ({
firebase,
status,
skills,
company,
links,
location,
bio,
github,
}) => {
const [showLinks, setShowLinks] = useState(false);
const [alert, setAlert] = useState<IAlert>(formAlert);
const initFormData = {
status: status ?? 'Developer',
company: company,
location: location ?? '',
bio: bio ?? '',
skills: skills?.toString() ?? '',
website: links?.website ?? '',
github: github ?? '',
facebook: links?.facebook ?? '',
linkedin: links?.linkedin ?? '',
instagram: links?.instagram ?? '',
twitter: links?.twitter ?? '',
youtube: links?.youtube ?? '',
};
const {formData, handleChange} = useForm<IProfileForm>(initFormData);
/** construct profile object from formData */
const makeProfile = async ({
status,
company,
location,
bio,
website,
instagram,
facebook,
linkedin,
twitter,
github,
youtube,
skills,
}: IProfileForm) => {
const newLinks: Links = {
website: parseLink(website),
instagram: parseLink(instagram),
facebook: parseLink(facebook),
linkedin: parseLink(linkedin),
twitter: parseLink(twitter),
github: getGithubLink(github),
youtube: parseLink(youtube),
};
const newSkills: string[] = skills?.split(',');
const newRepos = await getGithubRepos(github);
return {
status,
company,
location,
bio,
github,
links: newLinks,
skills: newSkills,
repos: newRepos,
};
};
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const updatedDev = await makeProfile(formData);
try {
firebase.updateProfile(updatedDev, {useSet: true, merge: true});
setAlert({
show: true,
color: 'success',
text:
'Profile successfully updated. You may go back to your dashboard.',
});
} catch (err) {
console.error(err);
setAlert({...alert, show: true});
}
};
const isDisabled: boolean = formData.status === '' || formData.skills === '';
const toggleSocialLinks = () => setShowLinks(!showLinks);
return (
<section className="container">
<FormHeader
title="Edit your profile"
lead="Let's get some information to make your profile stand out"
/>
{alert.show && <Alert text={alert.text} color={alert.color} />}
<EditProfileForm
formData={formData}
handleChange={handleChange}
handleSubmit={handleSubmit}
isDisabled={isDisabled}
toggleSocialLinks={toggleSocialLinks}
showLinks={showLinks}
/>
</section>
);
};
export default enhance(EditProfile);