Phase 2: Portfolio Project
Published: 2022-05-26 22:41:29

### ****
Hello there. I am excited to post about my first react project!
the project requirements as fallow :

1. You must make a single page application (only one index.html 
   file) using create-react-app.

2. Your app should use at least 5 components in a way that keeps 
   your code well organized.

3. There should be at least 3 client-side routes using React 
   Router. Be sure to include a nav bar or other UI element that 
   allows users to navigate between routes.

4. Use a json-server to create a RESTful API for your backend and 
   make both a GET and a POST request to the json server. Use a 
   form to make your post request, specifically a controlled 
   form/component. Additionally, you may choose to incorporate 
   data from an external API but it is not required.

5. Add some styling: you're encouraged to write your CSS from 
   scratch, either by using styled components or writing CSS 
   files and using id/className to style your elements. You can 
   also incorporate a UI framework (like React Bootstrap, 
   Semantic UI, or Material UI) if you prefer.

## INTRO
Before we start working on the project let's first give a brief introduction to React so we can understand what are we working with 

 <u>**<u>what is React</u>**</u>

React is a declarative, efficient, and flexible JavaScript library created by Facebook  to help make web applications fast and efficient with minimal coding effort. 

 
**Simple to learn and use**

React comes with an excellent deliver of documentation and tutorials. Anyone who know JavaScript can without difficulty apprehend React and begin the usage of it in only a few weeks.

**Reusable components**

React enables a developer to divide an app into smaller components that can be reused later, thereby reducing the codebase.

**virtual DOM**
For any framework, DOM manipulation is one of the most complex  tasks, especially when the application is large. React addresses this problem by using the a Virtual DOM, which is mainly a lightweight copy of the Real DOM. It is only an in-memory representation that is not displayed on the screen.

Rather than rendering the entire DOM again, React compares changes in the Virtual DOM and then renders it in the Real DOM similarly.

**phase2 project (coffee shop )**

Let's start talking about our project process now that we've established what react is and how functional it is.

In this blog we will create a simple React app that can be used Post/delete/update a coffee list .

**Setup**

 I used `npx create-react-app coffee-shop-phase2-project` to create my app. Then I used `cd coffee-shop-phase2-project` to get to my app repository, `code .` to open my app in Visual Studio, and `npm start` to load it in the browser.

After that, I deleted the following files:

- src/App.css

- src/App.test.js

- src/logo.svg

- src/setupTests.js


Then I adjusted my App.js file to look like this:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1201z5kdlxdn81syetax.png)


For this project, I used Material UI, a fantastic library for writing CSS-in-JS. You might want to use it as well if you're retracing my steps here. Run` npm install @material-ui/core` to get it. However, you can also use regular CSS. It makes no difference.


After this step ,I started building my other required components such as Crad.js, Home.js, ItemForm.js, MenuList, and NavBar using the command `touch component-name`.

**The App component**

 The` <App/>` component  was to be the main component (parent component). It would have a single state field, so I imported useState from react using `import React, {useState} from "react"` I then declared the state variable leaving my App.js component like this :


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pe5aquecy17m2axqzj14.png)

**The Menulist component**

The ` <App/>` component would then  pass dawn items as props to `<Menulist/> ` component which  would then map over the items array, and render a single <Cards /> component for each.
And i've used Material UI in this component to style my cards with Grids, it looked like this:



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kyronu0okgr4f8xtmy7e.png)


 **The Cards component**

I focused mainly on styling my cards in this component, and I destructed the item that was passed dawn as propas from the `<Menulist/>` component so that I could place each one in the correct area.
So after, the cards component looked like this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7aqzc5nsuiw0fayipzni.png)


**The JSON file**

My next step here was to create the Json file because it's one of the lab requirements I've chosen to create and start working on my fetch requests before moving on to the `<itemForm />` component.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0z4wy5hv15j62wpoq3lb.png)


**The ItemForm component**

Since our json file is now ready, we can make our fetch requests. The first one I want to work on is the post request in my `<itemform/>`. It's not the best thing to start with; you might want to start with a get request, but since my item form component will only be responsible for posting my data to the backend, I've decided to start with that.

The first step is to create a handleAddItem function in the App/> component, then send the entire function as props to the ItemForm/> component.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sruuswhqz8tbvmu19x81.png)

After passing down the handle add function, it's time to set the items Data state,  importing the usestate from react using `import React useState from "react"`; and also importing the styling tools from Matrial UI. After setting the state, styling, and sending the fetch request, the `<ItemForm/>` component should look like this:

```
import React, { useState } from "react";
import { FormControl, Input, InputLabel, Button, makeStyles } from '@material-ui/core'



const useStyles = makeStyles((theme) => ({
  root: {
    "& > *": {
      margin: theme.spacing(5),

    }
  }
}));

const image = "https://images5.alphacoders.com/905/905439.jpg"
const styles = {
  container: {
    backgroundImage: `url(${image})`,
    backgroundRepeat: "no-repeat",
    backgroundSize: "contain",
    height: "100vh",
    width: "cover",
    backgroundSize: "cover",
    backgroundPosition: 'center',

  },
}

function ItemForm({ handleAddItem }) {
  const [name, setName] = useState("");
  const [description, SetDescription] = useState("")
  const [image, setImage] = useState("")
  const [price, setPrice] = useState("")

  function handleSubmit(e) {
    e.preventDefault();
  
    const itemData = {
      name: name,
      image: image,
      description: description,
      price: `${price}$`,
      isInCart: false,
    };
  //clear all input values in the form
  setName('');
  SetDescription('');
  setImage('');
  setPrice('');


 


    // console.log("name:", name);
    // console.log("discribtion:", discribtion);

    fetch(" http://localhost:3001/coffies", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(itemData),
    })
      .then((r) => r.json())
      .then((newItem) => handleAddItem(newItem));

     
  }

  const classes = useStyles();



  return (
    <>

      <form className={classes.root} onSubmit={handleSubmit}>
        <FormControl

        >
          <InputLabel>Name</InputLabel>
          <Input
            value={name}
            onChange={(e) => setName(e.target.value)} />
        </FormControl>
        <FormControl>
          <InputLabel>image_url</InputLabel>
          <Input
            value={image}
            onChange={(e) => setImage(e.target.value)} />
        </FormControl>

        <FormControl variant="outlined" color="white">
          <InputLabel>description</InputLabel>
          <Input
            value={description}
            onChange={(e) => SetDescription(e.target.value)}
            label="describtion"
          />
        </FormControl>
        <FormControl variant="outlined">
          <InputLabel>price</InputLabel>
          <Input
            id="component-filled"
            value={price}
            onChange={(e) => setPrice(e.target.value)}
            label="price"
          />
        </FormControl>
        <Button color="primary" type="submit"
          style={{ top: 15, right: 20 }}
        >Add to List</Button>
      </form>

      <div style={styles.container}>

      </div>
    </>
  );
}

export default ItemForm;
```
 **The Get/Detete/Patch Ftech request **

The last thing I needed to do , at that point, was make the fetch get/delete requests in the `<App/>` component 

1. <u>The Get request</u> :

In this case, the useEffect hook is required, so the first step is to import it from React with `import React, {useEffect, useState} from "react"`;then the get request:

```
useEffect(() => {
        fetch("http://localhost:3001/coffies")
            .then((r) => r.json())
            .then((items) => setItems(items));
    }, []);
```
Our page browser would look like this as a result of the Get request:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1108s8d12csrrhvnmymk.png)



2. <u>The Delete request</u>:

 The delete request function (handleDeletetItem function in this case) will take id as an argument and send a delete request to the specific id. After the second `.then `The array of items will then be iterated through, returning only those that do not match the id of the delete request.

```
function handleDeleteItem(id) {
        fetch(` http://localhost:3001/coffies/${id}`, {
            method: "DELETE",
        })
            .then((r) => r.json())
            .then(() => {
                const updatedQuestions = items.filter((item) => item.id !== id);
                setItems(updatedQuestions);
            })


    }
```

This handleDeleteItem function will be passed dawn as a prop to `<Menulist/>`component , who will then pass dawn to the `<Card/> `component, leaving the `<Card/>` component fallow.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/28iopg5uqm8t1cwkthd1.png)


3. <u>The Patch request</u>:

The Patch request will be located in the `<Cards/> `component because this is where the `Add to card` button is located and I wanted to change the text content on the button every time it was clicked as well as change the `isInCart` value from false to true, 

In order for our state to be updated with changing values, we must create a function in the App component called handleUpdateItem, which will map through the array of items and return the updated value of each item.

```
 function handleUpdateItem(updatedItem) {
        const updatedItems = items.map((item) => {
            if (item.id === updatedItem.id) {
                return updatedItem;
            } else {
                return item;
            }
        });
        setItems(updatedItems);
    }
```

This function will then be passed as a prop to the cards component, which will use it to update the state value with the patch request made here. 


```
import React from 'react';
import { Card, CardActions, CardContent, Button, CardMedia, Typography } from "@material-ui/core";


function Cards({ item, handleDeleteItem, handleUpdateItem }) {

    const { id, description, name, image, price } = item


    function handleDeleteClick() {
        handleDeleteItem(id)

    }

    function handleAddToCartClick() {

        fetch(`http://localhost:3001/coffies/${item.id}`, {
            method: "PATCH",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify({
                isInCart: !item.isInCart,
            }),
        })
            .then((r) => r.json())
            .then((updatedItem) => handleUpdateItem(updatedItem));
    }


    return (
      

        <Card
        >


            <CardMedia
                component="img"
                height="350"
                image={image}
            />
            <CardContent>
                <Typography gutterBottom variant="h5" component="div">
                    {name}
                </Typography>
                <Typography variant="body2" color="text.secondary">
                    {description}
                </Typography>
                <Typography>
                    {price}
                </Typography>
            </CardContent>
            <CardActions>
                <Button size="small" className={item.isInCart ? "remove" : "add"} onClick={handleAddToCartClick}>
                    {item.isInCart ? "Remove From" : "Add to"}</Button>
                <Button size="small" onClick={handleDeleteClick}>delete</Button>
            </CardActions>
        </Card>
       
    );
}
export default Cards

```


**The NavBar component** :

I know I said earlier that it was "the last thing I needed to do" but that was a dirty lie. I still needed to create a way for the user to navigate  between browser components, and I needed to install React Router. To accomplish this, I Run `npm install react-router-dom `in the terminal.
After that, I imported Link from react-router-dom and styled it with Matrial UI.

The <Navbar/> would look as follows:

```
import React from "react";
import { Link } from "react-router-dom"
import { makeStyles, AppBar, Toolbar, Typography, CssBaseline } from "@material-ui/core"

const useStyles = makeStyles((theme) => ({
    navlinks: {
        marginLeft: theme.spacing(10),
        display: "flex",
    },
    link: {
        textDecoration: "none",
        color: "white",
        fontSize: "20px",
        marginLeft: theme.spacing(20),
        "&:hover": {
            color: "yellow",
            borderBottom: "1px solid white",
        },
    },
    logo: {
        flexGrow: "1",
        cursor: "pointer",
    },

    title: {
        flexGrow: 5
    }
}));


function NavBar() {
    const classes = useStyles();


    return (


        <AppBar position="static">
            <CssBaseline />
            <Toolbar>
                <Typography variant="h6" className={classes.logo}>
                    <h3 className={classes.title}> The Friendly Bean Coffee Shope</h3>
                </Typography>
                <div className={classes.navlinks} >
                    <nav>
                        <Link to="/"className={classes.link}>Home</Link>
                        <Link to="/ItemForm"className={classes.link}>ItemForm</Link>
                        <Link to="/MenuList"className={classes.link}>Menulist</Link>
                    </nav>
                </div>

            </Toolbar>
        </AppBar>


    );
}

export default NavBar;
```

in the App component we well also need to import Switch and Route from Rreact router dom `import { Switch, Route } from "react-router-dom";` the return of this componentr would look like this :

```
 return (

        <div>
            <NavBar  />
            <Switch>
                <Route exact path="/">
                    <Home />
                </Route>

                <Route path="/MenuList">
                    <MenuList handleDeleteItem={handleDeleteItem} items={items} handleUpdateItem={handleUpdateItem} />
                </Route>
                <Route path="/ItemForm">
                    <ItemForm handleAddItem={handleAddItem} />
                </Route>
                <Route path="*">
                    <h1>404 not found</h1>
                </Route>

            </Switch>

        </div>
    );
```

We are not finished yet; one more step is required for it to function properly in our` index.js` We must import BrowserRouter from react router Dom `import BrowserRouter from'react-router-dom;` and place it around our App component, as shown:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n4t49tkit8xso8gvw8jt.png)


After that, when we run npm start, our browser page will look like this:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/okk3kpsre8vv5pii8zq9.gif)


This experience taught me a lot. It wasn't the most difficult task, but it allowed me to use many different React features and required a lot of thought about how to make components. I also liked how I was able to develop my styling ability using material ui for sure that was the fun part of all of this .
Thank you for reading you're welcome to check my git hub link for more details.

[https://github.com/vatimetou-ebeke/Coffee-shop-phase2-project](url)