Fitboard

project / March 24th, 2021

Fitboard Home Page

GitHub

Background

The Fitboard is a multi-page MERN stack web app that allows users to log their exercises, which are then added to a list that is posted on the home page. For each exercise, a description, duration (in minutes), and date are entered. Users can add their name to a list of names in a drop-down menu for convenience when logging an exercise and filling out the name field. There are also options to edit or delete a logged exercise.

Users will be able to view all logged exercises on the home page, which can serve as motivation and inspiration for those seeking new exercises or goals to get fit.

Guidance for building this project was provided from a MERN stack lesson on FreeCodeCamp, which was an excellent resource for learning how to organize back end files and connecting them to the front end.

Purpose

The desire to create a fitness-based app originated from a past work experience, where my colleagues ran a competition to see who could record the most steps over one summer. An Excel spreadsheet was used to record this information and I thought it would translate well as an app idea. Fortunately, FreeCodeCamp had a lesson for building an exercise tracker as MERN stack app, which aligned with my interests. I had also yet to build a full-stack app with React, and felt this would be a excellent way to really put everything I had learned in the Complete 2021 Web Development Bootcamp from Udemy together.

I wanted to learn the steps a developer would take when starting a MERN stack project and how they would organize the back end and front end files and connect the two sides together. Additionally, I had learned about using React functional components in the Udemy bootcamp, but did not build any projects using class components and only briefly discussed it. This project was a good opportunity to explore that and further expand my knowledge of class components, as I felt it would enhance my understanding of functional components. I also wanted to learn about React routing in this project.

Concepts and Tools Used

  • MERN stack development

  • MongoDB and Mongoose

  • Express.js

  • React (especially class components)

  • React routing

  • Node.js

  • Bootstrap

  • CSS

  • Axios

  • Postman

Scope and Modifications Made

Originally I wanted each exercise to have a steps field instead of the duration field that FreeCodeCamp used, but decided to stick with the latter since not all exercises (eg. cycling, swimming) utilize steps as a primary activity. I also considered a field to list calories burned, but ultimately thought time would be an easier measurement for users to track.

Because this was my first time creating a MERN stack app from start to finish, I followed the tutorial very closely and paid attention to the process of creating the back end, front end, and then putting everything together. As I accumulate knowledge, I will start to look for ways to incorporate my own ideas or experiences into a new project.

One small modification I made was adjusting the state in CreateUsers to display a status message below the textbox, in order to let the user know if their username has been submitted or not.

Process

Part 1: Back end

After the React project template is initially created, the back end is built first by creating a separate folder dedicated to it. A server file is created inside it and the Express, Mongoose, dotenv (for loading environment variables), and cors (cross-origin resource sharing, which allows access to resources from external hosts and data to be sent and retrieved asynchronously in the background without interfering with the display and behavior of an existing page) dependencies are installed.

The back end is then connected to MongoDB Atlas using Mongoose and a database is created. Once a connection is established, collections for the exercises and users are created inside the database by creating models from Mongoose schemas for each collection. Next, Router files with API endpoint routes to perform create, read, update, and delete operations for the Exercises collection and create and read operations for the Users collection are created and added to the server file. Postman is then used to test the server API without a front end.

Part 2: Front end

First, the Bootstrap CSS framework is installed in the project and imported to the main app React component to make styling easier. React router is then imported to make it easier to route different links to different React components. A Router element is used to route to each component of the Fitboard - the exercises list, editing the exercises, adding an exercise, and adding a new user. Each of these components are then created, starting with CreateExercise. The initial state of the class component is set by assigning an object to it inside the constructor of the CreateExercise class.

Next in CreateExercise, methods to update fields like username, exercise description, exercise duration, and date are added using the setState method. With the exception of date, the methods are set up such that when information is sent through a textbox to update each field, an event is triggered and calls a method to set the state. In other words, the corresponding field in the state is updated to the value inside the textbox. For date, the value is updated using a date-picker component which is essentially a calendar, imported from a React library of the same name.

Fitboard CreateExercise Page

Once these methods are added, another method is added to handle the submit event on the form. Inside, a preventDefault method is called to prevent the default HTML form submission behaviour of automatically refreshing. Instead, the exercise is first submitted to the database using an Axios POST method to the route for adding an exercise, before redirecting the user back to the homepage which is the list of exercises. Then, a React lifecycle method componentDidMount is added so that just before the createExercise component is loaded, an Axios GET request is made to grab the array of current users from the MongoDB Atlas database. The list of users is then used to populate a drop-down menu, so that a user can select their name from the menu when logging an exercise. Lastly, a standard HTML form that incorporates all of these fields and methods to allow the user to submit an exercise is written to be rendered in the return statement. This completes the CreateExercise component.

The CreateUser component is built in a similar manner, except that it only contains a simple web form with a username field and will only have two methods: one to add the username using an Axios POST method and one to handle the submit event. The method to handle the submit event is slightly different in that the user will remain on this page after submitting a user, rather than be redirected back to the home page.

Fitboard CreateUser Page

A navigation bar component with links to each component is also created and imported to the main app component.

It's important to note that the Axios methods are not implemented until part 3, when the front end is connected to the back end. For testing in step 2, I simply logged the information submitted in each form.

Part 3: Connecting the Front end to the Back end

In this step, the Axios library is used to make the POST and GET requests to the server endpoints in the backend for the CreateExercise and CreateUser components that were described (but not yet implemented) in part 2. The endpoints are expecting a JSON object in the request body, and the Mongoose CRUD operations assigned to them in the exercises and users Router files are executed to make the desired changes in the database.

The next goal is to complete the ExercisesList component, which also acts as the home page for the app. First, a componentDidMount method is added with an Axios GET request in order to load the list of exercises from the database to the state before the page is rendered, just like how the load of users was loaded in the drop-down menu for the CreateExercises component. A delete button for each exercise in the list of exercises is then added by creating a method to delete the exercise. This method will take the ID of the exercise that will be deleted and it will be used in order to send an Axios DELETE request to the exercises route. After the exercise is deleted in the database, the exercise is then deleted from the list displayed to the user by updating the array of exercises to filter out the one with the matching ID. Additionally, an Exercise functional component is created to take in props like the method to delete the exercise and the exercise object itself. A method is then written to map out each exercise in the stateful array of exercises as an Exercise component and return it to be rendered as a table row, each with buttons to edit the exercise and delete the exercise.

Next, the EditExercise component is created, which is very similar in structure to the CreateExercise component. This time, Axios uses the exercise ID to GET the exercise that needs to be edited and display it by updating the state. And submitting form information will make a POST request to update that specific exercise. The app is now complete.

Outcome and Takeaways

The process of building this app was difficult, since it was my first time connecting a React front end to a back end and required writing a high volume of code compared to previous projects. However, it was also extremely rewarding to learn how each tool fit in the overall structure of the project and the order of steps to follow. This project also helped familiarize me with using React class components, which in turn improved my understanding of the React functional components I learned about in the 2021 Complete Web Development Bootcamp.

Since this project was based off a MERN stack lesson on FreeCodeCamp, I am considering the idea of applying the concepts from this lesson to an existing project, the Floatpad which was built during the Web Development Bootcamp. Currently, the Floatpad is purely a front-end app that was built using React, and lacks the ability to persist data after being closed in the browser. If I choose to revisit the Floatpad, I would see if I could add a back-end and organize the files in the same manner it was done for this app. In terms of the front-end, I wanted to see if the concepts from this project would work with the React functional components used in the bootcamp.

Possible Improvements Going Forward

If I wanted to refactor, I could combine the CreateExercise and EditExercise in a single component. It would also be helpful to add authentication and security to allow only registered users of the app to log, edit, and delete exercises. The exercise list would be more useful if there were sorting and filtering options in order to cut the list down when it gets too large. Another idea to consider is to dynamically generate individual pages for each user to display their statistics and the exercises that they've logged.


External Link

Because Heroku cannot run the Express server and React app (which are in separate directories) at the same time, I cannot deploy this app for the time being. I have spent a lot of time researching and trying numerous solutions, but have none have worked so far. When I have time, I would like to try deploying this app again.

In the meantime, anyone who is interested in exploring the app locally can follow the instructions below.

Instructions for Running Locally

  1. Clone the GitHub repository in the above link

  2. Go to the root directory of the project folder in a terminal using the cd command

  3. Install all project dependencies with:

    'npm install'

  4. Use the cd command to enter the backend folder inside the project directory

  5. Install all project dependencies for the back end with:

    'npm install'

  6. Install the nodemon utility globally with:

    'npm install -g nodemon'

  7. In your terminal, open another tab and cd to the backend folder in the project directory. Run the Express server by entering the following command:

    'nodemon server.js'

  8. In your original tab, cd back to the root directory of the project and run the React app by entering:

    'npm start'