Booting Up: Bootcamp Week 12 - Project Week + Redux
Published: 2020-01-07 19:20:16

#Hello Friends

As you may know, every third week here at Flatiron's bootcamp concludes with a project that utilizes what we learned during the previous two weeks.

![alt text](https://media.giphy.com/media/Zxo0sziR6WDDOSd0Wy/giphy.gif)

These past two weeks we learned about React, and so it was time to build my first project in React!

##Compass - My first React application

I decided to build a simple educational platform centered around life purpose. This was inspired by my volunteer work with a non-profit called nXu.

If you'd like to play around with it, feel free to grab it from the following links:

Frontend: https://github.com/shawnhuangfernandes/compass-frontend
Backend: https://github.com/shawnhuangfernandes/compass-backend

### User Story

The user should be able to:
- Create an Account, and return to their account at a later time
- Sign in to their account
- Complete 3 types of activities: Readings, Videos and Activities
- Mark their activities as complete and return to them later

### Design Strategy

Our instructor laid out a good project management strategy for building a simple full stack application, it went something like this:

- Imagine a user using your app, what does each page look like? Mock it up! I used a neat website called [Ninja Mock](https://ninjamock.com/) to create each website view

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/r5wxnzesaxya70ewpynv.png)

- Break up each view into their building blocks, these will be your components (Navbar, Card, Descriptions etc)
- Figure out what data you'll need to populate the components with their information, and abstract them into models for your backend. I drew representations of my models using [Draw.io](https://www.draw.io/).

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/x302h042wqkhsg35zhmj.png)

- Use some sort of project management software to divide your project into manageable tasks. I used [Trello](https://trello.com/) to do this.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/l0dtjqkw1hwemwg3qnhx.png)

- Build your project view by view, and test before you move on!

### Project Kickoff

**First thing**, I picked a **styling library** before diving into the coding. One week is not a lot of time to both build site functionality and styling from scratch, so I wanted to lean on some library to provide cookie-cutter components that came pre-styled.

I decided to use [Semantic UI](https://react.semantic-ui.com/) for my project's styling.

I then setup my project's backend and frontend folder structure.

Backend
```terminal
 rails new <my-project> --api -T --database=postgresql
```

Frontend
```terminal
npm install -g create-react-app
create-react-app my-project-client
```

### Building the Backend
- I created my models (based on my plan) along with their associations and attributes
- I created my routes to access the data from my models
- I created my controllers to handle what to do when a route was 'activated'
- I created seed data (like dummy users with fake names) to test my model functionality using 
```terminal 
rails c
```
and running the rails console suite to run the methods of my models
- I used [Postman](https://www.getpostman.com/) to test my routes and controllers to make sure that I could get the data properly from my server (aka backend) for my frontend.

### Preparing The Frontend Structure
I worked on the frontend view by view. The order I did things in was as follows:
- Create container components for each and every one of my views (e.g LandingContainer, LoginContainer, SignUpContainer, LessonContainer, SettingsContainer etc.)

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/1q1xkknkri3ake617bzx.png)

- In my 'Routing' container (in my case I called it MainContainer), I set up my front-end routes to render each container component appropriately.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/xmt43ea0b9omhvbtswil.png)

Now I could do the hard part: building out each component!

### Building Each Component Out

The overall process for building a single component out was:
1) Importing whatever dependencies/components I might need
2) Creating a constructor if needed ([React Snippets](https://marketplace.visualstudio.com/items?itemName=xabikos.ReactSnippets) made this painless)
3) Adding state to the component (For a form, storing a user etc.)
4) Adding event handler methods (for form submissions, button clicks)
5) Adding lifecycle methods (make sure data could be used at the right time)
6) Adding custom methods as needed
7) Add the render method (so that I could take the data from the component and display it)

Here's a sample of what that looked like for one of my components:
``` react
import React, { Component } from "react";
import PageTitle from "./PageTitle";
import { Message, Form, TextArea, Button } from "semantic-ui-react";
import { Link } from "react-router-dom";
import VideoPromptContainer from "./VideoPromptContainer";

class PromptContainer extends Component {
  previousLink = `/users/${this.props.match.params.user_id}/prompts`;

  constructor(props) { // constructor
    super(props);
    this.state = { // state
      prompt: {},
      userInput: "",
      isComplete: false
    };
  }

  determineMediaType = () => { // custom method
    switch (this.state.prompt.category) {
      case "Reading":
        return (
          <Message
            color="violet"
            size="massive"
            header={this.state.prompt.header}
            content={this.state.prompt.body}
          />
        );
      case "Video":
        return (
          <div className="prompt-video-container">
            <VideoPromptContainer videoId={this.state.prompt.body} />
          </div>
        );
      case "Activity":
        return (
          <Form size="massive">
            <Form.Field
              onChange={this.handleTextInput}
              control={TextArea}
              label={this.state.prompt.body}
              value={this.state.userInput}
              rows={20}
            />
          </Form>
        );
      default:
      // code block
    }
  };

  handleTextInput = async e => { // event handler method
    await this.setState({
      userInput: e.target.value
    });
  };

  handleCompletionClick = async e => { // event handler method
    await this.setState({
      isComplete: true
    });

    const fetchResponse = await fetch(`http://localhost:3000/responses`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        user_id: this.props.match.params.user_id,
        prompt_id: this.props.match.params.prompt_id,
        body: this.state.userInput,
        complete: this.state.isComplete
      })
    });

    console.log(await fetchResponse.json());
  };

  componentDidMount() { // lifecycle method
    this.fetchPrompt();
  }

  fetchPrompt = async () => { // custom method for http request
    const promptFetched = await fetch(
      `http://localhost:3000/users/${this.props.match.params.user_id}/prompts/${this.props.match.params.prompt_id}`
    );
    const promptObj = await promptFetched.json();

    await this.setState({
      prompt: promptObj,
      isComplete: promptObj.response ? promptObj.response.complete : false,
      userInput: promptObj.response ? promptObj.response.body : ""
    });
  };

  render() { // render method
    return (
      <div className="prompt-container">
        <PageTitle titleText={this.state.prompt.title} />
        <div className="prompt-body-container">{this.determineMediaType()}</div>
        <div className="prompt-button-container">
          <Button
            toggle
            active={this.state.isComplete}
            onClick={this.handleCompletionClick}
            size="massive"
            content={
              this.state.isComplete ? "Click To Update" : "Click To Save"
            }
          />
          <Link to={this.previousLink}>
            <Button
              size="massive"
              basic
              inverted
              color="violet"
              content="Go Back"
            />
          </Link>
        </div>
      </div>
    );
  }
}

export default PromptContainer;

```

### What Did It Look Like

Here are a couple snips of the project itself!

#### Landing Page

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/hruydpyiz90o2inpeeja.png)

#### User Dashboard

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/50xlfd7biqxgebx7241v.png)

#### Prompt Selection

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/r27xlba40bs65wdi4ak8.png)

#### Video Prompt

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/1oewd0fgcrbfbdo6xc0b.png)

### Takeaways

- Planning is good, but don't expect to stick to your plan
- Styling libraries are convenient, but give yourself at least 1-2 days to work with the library before trying to implement it in your project
- Create a realistic scope, and be prepared to cut features
- Minimal Viable Product is top priority, then make it look polished, then implement stretch goals

This was a good learning project, and can definitely be improved. I am very much looking forward to building better React apps in the future!

Hopefully this was enlightening or interesting for you!

Good luck with your own endeavors,
Shawn