In this final lab, you are going to create a portfolio page for yourself. You will be using the skills you have learned in this course to create a page that showcases your work. The portfolio page will be a single page that will contain the following sections:
- A header with external links to social media accounts and internal links to other sections of the page
- A landing section with an avatar picture and a short bio
- A section to display your featured projects as cards in a grid fashion
- A contact me section with a form to allow visitors to contact you
Here you will have the opportunity to use some popular open source libraries that will help you to have a more polished and professional looking page.
Before proceeding further, let's provide an introduction to the libraries you will be using.
Chakra UI comes pre-configured with this lab, so you don't have to worry about installing it or setting it up.
The components from this library you will need to use are already imported from the @chakra-ui/react
package at the top of each corresponding file.
If you don't see a component already imported, it's because you probably won't need it.
In any case, feel free to check their official documentation to see all the components at your disposal and their corresponding props.
The Formik library is already set up in the project as well, so no extra configuration is needed.
In this lab, you will be only using the useFormik
hook from the Formik library, as well as the global Yup
object to define the Contact Me form validation rules.
The form UI will be implemented using Chakra UI components.
Before you begin, if you run npm start
and view the app in the browser, you'll notice that the starting React app works as is.
The app outputs a page with an empty header, 3 different full-height sections and a footer. Every section has a different background color. The first 2 sections will be empty and the third section will contain all the UI elements for the Contact Me form.
Once you open the code lab, you need to install the Chakra UI and other referenced libraries by running the npm install
command from the built-in terminal in the code lab. To toggle the built-in terminal, you need to click the View menu item, then choose the Terminal in the dropdown.
Once the terminal is open (visible), you can run the npm install
command. This will install all the required missing dependencies, so that you can begin working on the task.
Open Header.js
file. You will see a header component with black background, but no content.
a) Add external social media links to the header on the left side of the page.
The implementation should be placed inside the first nav
element. The data is already provided in the socials
array at the top of the file.
Use the HStack
component to stack the links horizontally.
Each social should be a a
tag with a href
attribute pointing to the corresponding social media page. The a
tag should have as children a FontAwesomeIcon
component, which is already imported for you.
The FontAwesomeIcon
component takes 2 props:
icon
: The icon to be displayed. In this case, you should use theicon
prop from thesocial
object.size
: The size of the icon. You can use the2x
value.
You can check below an example of how to render it:
<FontAwesomeIcon icon="fab" size="2x" />
b) Add internal links to the Projects section and Contact Me section
Each link should be a a
tag. Each a
tag should have as children the name of the section: "Contact Me" and "Projects".
When clicking on the link, the url should show the corresponding section. For example, when clicking on the "Contact Me" link, the url path should be /#contact-me
.
Also, the click should scroll to the corresponding section with a smooth animation. The code for that has been provided for you via the handleClick
function. You need to hook that function with the a
tag onClick
event.
Bear in mind the Projects section has an id called projects-section
and the Contact Me section has an id called contactme-section
.
Avoid any key related warnings when opening the console.
The final header UI should look like below:
Open the LandingSection.js
file. Implement the below UI to provide a landing section for the app with an avatar, a greeting and a brief role description.
For the data, use the variables provided at the top of the file (greeting
, bio1
and bio2
) and not personal data.
For the avatar you can use the next url: https://i.pravatar.cc/150?img=7
All the components you need have been already imported for you.
Open the ProjectsSection.js
component. This component is already implemented, however the Card
component that it uses to display information about each project it's not.
The ProjectsSection
component already defines a projects
array with the data for each project and that information is passed to each Card
component as props.
Open the Card.js
component and implement the UI for the card. Each card should look like the image below:
You can use the following components from Chakra UI that have been already imported for you:
- HStack,
- VStack,
- Image,
- Heading,
- Text,
For the right arrow, use the below component. The necessary imports are already provided for you as well.
<FontAwesomeIcon icon={faArrowRight} size="1x" />
Avoid any key related warnings when opening the console.
Open the ContactMeSection.js
component. Implement the remaining requirements of the form according to the below specifications.
The form contains 4 input fields: name, email address, type of enquiry and message.
The whole UI of the form is defined for you. You need to implement some missing business logic.
a) Add the proper configuration to the useFormik
hook, passing an object with 3 properties: initialValues
, onSubmit
and validationSchema
.
The initialValues
object should have the following fields:
firstName
: The name of the useremail
: The email of the usertype
: 'hireMe' | 'openSource' | 'other'comment
: A message from the user
The onSubmit
function should perform an API call by using the submit
helper from useSubmit
hook.
Inspect the useSubmit
custom hook to see the arguments the submit
function expects.
The validationSchema
should be a Yup schema that validates the form fields. The validation rules are as follows:
firstName
: required field. Otherwise, the error message should be "Required".email
: required field and a valid email. If empty, the error message should be "Required". If not a valid email, the error message should be "Invalid email address".type
: Optional fieldcomment
: required field and with a minimum of 25 characters. If empty, the error message should be "Required". If less than 25 characters, the error message should be "Must be at least 25 characters".
b) Make the Input
components from Chakra UI controlled components.
useFormik
hook returns an object with a function called getFieldProps
that when called, returns an object with the necessary props to make the input controlled.
c) Show the error messages for each field when the field is touched and the validation fails.
Each field is grouped in a FormControl
component. The FormControl
component takes a isInvalid
prop that you can use to show the error message.
The isInvalid
prop should be true
when the field is touched and the validation fails.
The FormErrorMessage
component from Chakra UI should display the corresponding error message if the isInvalid
prop from the parent FormControl
component is true.
Below is an example of how the UI should look like when the validation fails for the firstName
field:
d) Connect the form
onSubmit prop with Formik's handleSubmit
function.
Make sure the default HTML form behaviour is prevented when a submission occurs.
e) Show an alert when the form is submitted successfully.
You need to listen to changes in the response
object from the useSubmit
hook. Also, when the form is submitted, a loading indicator should be shown in the Submit button. You can use the isLoading
property from the useSubmit
hook.
The useSubmit
hook is implemented in a way that 50% of the times it will return a successful response and 50% of the times it will return an error response.
The response
object from the API has 2 properties:
type
: 'success' | 'error'message
: Extra contextual information about the response
You can use the provided useAlertContext
hook to show the alert. The hook returns a function named onOpen
that you can call to display it.
Check the alertContext.js
file to see the arguments the onOpen
function expects.
If the response is successful, the alert should display in its content the first name of the user, according to the value typed in the form 1st field, so make sure you are passing the right arguments to the submit
function returned from the useSubmit
hook.
In addition, the form has to be reset if the response is successful. For that use the resetForm
function from the object returned from the useFormik
hook.
This is how the UI should look for both cases:
Implement a header show/hide animation depending on the scroll direction. The header should slide up with some animation and be hidden when scrolling down the page. When scrolling up, the header should slide down and be visible.
For that, the outermost Box component has some transition properties already defined. Your logic should change the transform
property of the underlying Box
DOM element depending on the scroll direction.
When scrolling up, the transform
style property from the Box
DOM element should be translateY(0)
.
When scrolling down, the transform
style property from the Box
DOM element should be translateY(-200px)
.
Here are some of the elements you may need for the implementation:
- The
useEffect
hook - The
useRef
hook - Setting up listeners for the scroll event
window.addEventListener('scroll', handleScroll)
- Removing listeners for the scroll event:
window.removeEventListener('scroll', handleScroll)
- Keeping track of the previous scroll position in a variable