Sunday Afternoon FullStack Cont…

Sunday Afternoon FullStack Cont…

Scratchpad #10

// async function getData() {
//   try {
//     const { data: pokemon } = await axios.get(
//       'https://pokeapi.co/api/v2/pokemon/1'
//     );
//     console.log(pokemon);

//     const speciesUrl = data.species.url;
//     const { data: species } = await axios.get(speciesUrl);
//     console.log(species);
//   } catch (err) {
//     console.log('Something went wrong', err);
//   }
// }

// getData();

// async function getData() {
//   try {
//     const pokemon1Promise = axios.get('https://pokeapi.co/api/v2/pokemon/1');
//     const pokemon2Promise = axios.get('https://pokeapi.co/api/v2/pokemon/2');
//     const pokemon3Promise = axios.get('https://pokeapi.co/api/v2/pokemon/3');
//     const pokemon4Promise = axios.get('https://pokeapi.co/api/v2/pokemon/4');

// const pokemon1 = await pokemon1Promise;
// const pokemon2 = await pokemon2Promise;
// const pokemon3 = await pokemon3Promise;
// const pokemon4 = await pokemon4Promise;

// console.log(pokemon1);
// console.log(pokemon2);
// console.log(pokemon3);
// console.log(pokemon4);

//     const result = await Promise.all([
//       pokemon1Promise,
//       pokemon2Promise,
//       pokemon3Promise,
//       pokemon4Promise,
//     ]);

//     console.log(result);
//   } catch (err) {
//     console.log('Something went wrong', err);
//   }
// }

// getData();

function initializeDeck() {
  const deck = [];
  const suits = ['hearts', 'diamonds', 'spades', 'clubs'];
  const values = '2,3,4,5,6,7,8,9,10,J,Q,K,A';
  for (let value of values.split(',')) {
    for (let suit of suits) {
      deck.push({ value, suit });
    }
  }
  return deck;
}

function drawCard(deck, drawnCards) {
  const card = deck.pop();
  drawnCards.push(card);
  return card;
}

function drawMultiple(numCards, deck, drawnCards) {
  const cards = [];
  for (let i = 0; i < numCards; i++) {
    cards.push(drawCard(deck, drawnCards));
  }
  return cards;
}

function shuffle(deck) {
  // loop over array backwards
  for (let i = deck.length - 1; i > 0; i--) {
    // pick random index before current element
    let j = Math.floor(Math.random() * (i + 1));
    [deck[i], deck[j]] = [deck[j], deck[i]];
  }
  return deck;
}

// const deck1 = initializeDeck();
// const hand = [];

// // shuffle(deck1);

// // drawCard(deck1, hand);
// // drawCard(deck1, hand);
// // drawCard(deck1, hand);
// // drawMultiple(5, deck1, hand);

// // console.log(hand);
// // console.log(deck1.length);

// const makeDeck = () => {
//   return {
//     deck: [],
//     drawnCards: [],
//     suits: ['hearts', 'diamonds', 'spades', 'clubs'],
//     values: '2,3,4,5,6,7,8,9,10,J,Q,K,A',
//     initializeDeck() {
//       const { suits, values, deck } = this;
//       for (let value of values.split(',')) {
//         for (let suit of suits) {
//           deck.push({ value, suit });
//         }
//       }
//       return deck;
//     },
//     drawCard() {
//       const card = this.deck.pop();
//       this.drawnCards.push(card);
//       return card;
//     },
//     drawMultiple(numCards) {
//       const cards = [];
//       for (let i = 0; i < numCards; i++) {
//         cards.push(this.drawCard());
//       }
//       return cards;
//     },
//     shuffle() {
//       const { deck } = this;
//       for (let i = deck.length - 1; i > 0; i--) {
//         let j = Math.floor(Math.random() * (i + 1));
//         [deck[i], deck[j]] = [deck[j], deck[i]];
//       }
//     },
//   };
// };

// const deck1 = makeDeck();
// // deck1.initializeDeck();
// // deck1.shuffle();
// // deck1.drawCard();
// // deck1.drawMultiple(10);

// const deck2 = makeDeck();

// console.log(deck1);
// console.log(deck2);

// function Person(firstName, lastName, age) {
//   this.firstName = firstName;
//   this.lastName = lastName;
//   this.age = age;
// }

// Person.prototype.greet = function () {
//   console.log(
//     `Hello, my name is ${this.firstName} ${this.lastName} and I am ${this.age} years old.`
//   );
// };

// class Person {
//   constructor(firstName, lastName, age) {
//     this.firstName = firstName;
//     this.lastName = lastName;
//     this.age = age;
//   }

//   greet() {
//     console.log(
//       `Hello, my name is ${this.firstName} ${this.lastName} and I am ${this.age} years old.`
//     );
//   }
// }

// const john = new Person('John', 'Doe', 25);
// const jack = new Person('Jack', 'Smith', 30);

// jack.greet();
// john.greet();

// console.log(john, jack);

// class User {
//   constructor(username, password) {
//     this.username = username;
//     this.password = password;
//   }

//   login(pass) {
//     if (pass === this.password) {
//       console.log('Welcome back');
//     } else {
//       console.log('Incorrect password entered.');
//     }
//   }
// }

// class Subscriber extends User {
//   logout() {
//     console.log('You have successfully logged out, Subscriber');
//   }
// }

// class Creator extends User {
//   constructor(username, password, totalVideos = 0) {
//     super(username, password);
//     this.totalVideos = totalVideos;
//   }

//   uploadVideo(videoName) {
//     this.totalVideos++;
//     console.log(
//       `Thank you for uploading ${videoName}.\nChannel: ${this.totalVideos} video(s)`
//     );
//   }

//   logout() {
//     console.log('You have successfully logged out, Creator');
//   }
// }

// const john = new User('john', 'john123');
// const jack = new Subscriber('jack', 'jack123');
// const jane = new Creator('jane', 'doe', 10);

// john.login('john1234');
// jack.login('jack123');
// jane.logout();

// console.log(jane.totalVideos);

React #1

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>React</title>
  </head>
  <body>
    <div id="root"></div>

    <script src="https://unpkg.com/react@^16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@^16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <script type="text/babel">
      // const root = document.querySelector('#root');
      // const p = document.createElement('p');
      // p.innerText = 'Hello World';
      // root.append(p);

      // const h1 = React.createElement(
      //   'h1',
      //   {
      //     className: 'intro-title',
      //     id: 'imp',
      //   },
      //   'Hello World'
      // );

      // const p = React.createElement('p', {}, 'This is a sample para');
      // const div = React.createElement('div', { children: [h1, p] });

      const h2 = <h2 className='very-imp'>Hello Universe. I'm JSX.</h2>;

      ReactDOM.render(h2, document.querySelector('#root'));
    </script>
  </body>
</html>

Scratchpad React #2

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>React</title>
  </head>
  <body>
    <div id="root"></div>

    <script src="https://unpkg.com/react@^16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@^16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/prop-types@^15/prop-types.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
    <script type="text/babel">
      // const root = document.querySelector('#root');
      // const p = document.createElement('p');
      // p.innerText = 'Hello World';
      // root.append(p);

      // const h1 = React.createElement(
      //   'h1',
      //   {
      //     className: 'intro-title',
      //     id: 'imp',
      //   },
      //   'Hello World'
      // );

      // const p = React.createElement('p', {}, 'This is a sample para');
      // const div = React.createElement('div', { children: [h1, p] });

      // const h2 = <h2 className='very-imp'>Hello Universe. I'm JSX.</h2>;

      // const h2 = React.createElement('h2', {className: 'very-imp'}, 'Hello Universe')

      // const children = 'Hello World. This is the page title';
      // const className = 'title';
      // const props = { children, className };

      // const heading = <h1 {...props} id='hello' />;
      // React.createElement('h1', {className: 'title', children: 'Hello World'})
      // <h1 class="title">Hello World</h1>

      // const message = 'Hello World';
      // const myClassName = 'special';

      // const h1 = <h1 className={myClassName}>{message}</h1>;

      // function message(props) {
      //   return <p className='message'>{props.children}</p>;
      // }

      // function Post(props) {
      //   return (
      //     <article>
      //       <h4>{props.title}</h4>
      //       <p>
      //         Published on {props.date} by {props.author}
      //       </p>
      //       <p>{props.description}</p>
      //       <a href={props.url}>Read more</a>
      //     </article>
      //   );
      // }

      // const msg = message({ children: 'Hello John' });

      // const data = (
      //   <div>
      //     {message({ children: 'Hello John' })}
      //     {message({ children: 'Hello Jane' })}
      //     {message({ children: 'Hello Jack' })}
      //   </div>
      // );

      // const content = (
      //   <div>
      //     {post({
      //       title: 'News article #1',
      //       date: '26th December',
      //       author: 'John Doe',
      //       description: 'Lorem ipsum',
      //       url: 'https://asdasd.com',
      //     })}
      //   </div>
      // );

      // {React.createElement(Post, {
      //       title: 'News article #1',
      //       date: '26th December',
      //       author: 'Jane Doe',
      //       description: 'Lorem ipsum',
      //       url: 'https://asdasd.com',
      //     })}

      // const Post = ({ title, date, author, url, children }) => {
      //   return (
      //     <article>
      //       <h4>{title}</h4>
      //       <p>
      //         Published on {date} by {author}
      //       </p>
      //       <p>{children}</p>
      //       <a href={url}>Read more</a>
      //     </article>
      //   );
      // };

      // Post.propTypes = {
      //   title: PropTypes.string.isRequired,
      // };

      // const content = (
      //   <div>
      //     <Post date='27th December' author='Jane Doe' url='https://asdasd.com'>
      //       Lorem ipsum
      //     </Post>
      //   </div>
      // );

      const Greet = ({ name, message, imp }) =>
        imp ? (
          <h2 style={{ color: imp ? 'red' : 'blue' }}>
            {message}, {name}
          </h2>
        ) : (
          <p>You're not an imp</p>
        );

      // const content = (
      //   <React.Fragment>
      //     <Greet name='John' message='Hello' />
      //     <Greet name='Peter' message='Hello' />
      //   </React.Fragment>
      // );

      const content = (
        <>
          <Greet name='John' message='Hello' imp={true} />
          <Greet name='Peter' message='Hello' />
        </>
      );

      ReactDOM.render(content, document.querySelector('#root'));
    </script>
  </body>
</html>

Scratchpad #12

const http = require('http');
const fs = require('fs');

// const server = http.createServer((req, res) => {
//   // console.log(req);
//   // process.exit();
//   // console.log(req.url, req.method, req.headers);

//   res.setHeader('Content-Type', 'text/html');

//   res.write('<html>');
//   res.write('<head><title>Hello World</title></head>');
//   res.write('<body>');
//   res.write('<h1>Hello World</h1>');
//   res.write('</body>');
//   res.write('</html>');

//   res.end();
// });

const server = http.createServer((req, res) => {
  const url = req.url;
  const method = req.method;

  if (url === '/') {
    res.setHeader('Content-Type', 'text/html');
    res.write(`<html>
      <head><title>Enter Message</title></head>
      <body>
        <form action="/message" method="POST">
          <input type="text" name="message" />
          <button type="submit">Send</button>
        </form>
      </body>
    </html>`);
    return res.end();
  }

  if (url === '/message' && method === 'POST') {
    const body = [];

    req.on('data', (chunk) => {
      console.log(chunk);
      body.push(chunk);
    });

    req.on('end', () => {
      // To work with all the chunks we need to buffer them
      const parsedBody = Buffer.concat(body).toString();
      console.log(parsedBody);
      const message = parsedBody.split('=')[1];
      fs.writeFileSync('message.txt', message);
    });

    res.statusCode = 302;
    res.setHeader('Location', '/'); // redirect to homepage
    return res.end();
  }
});

server.listen(3000);

Project

  1. Generate some boilerplate for a basic React application.
    • Go into your workspace/projects directory using the terminal.
    • cd ~/Documents/FullStack/Workspace
    • mkdir rststore
    • npx create-react-app@latest frontend –use-npm
    • code .
    • cd frontend
    • npm start
    • Open public/index.html and clean up the file. Remove all the comments and change the title and meta content.
    • Delete all the files in the src folder. Create and add basic boilerplate code to App.js and index.js.

2. Chakra UI Installation and Setup

  • npm i @chakra-ui/react @emotion/react @emotion/styled framer-motion
  • npm install react-icons –save
  • Edit index.js file. Import ChakraProvider component and wrap the App component with it.

3. Create Header and Footer components

  • Create a folder called src/components in the src folder and add all components in that.

4. Create HomeScreen product listings

  • Create the HomeScreen component (all display/screen components will go in the /screens folder), along with the product and ratings components.

5. Install and Implement React Router

  • npm install react-router-dom
  • Complete all the React Router setup on the App page.
  • Modify Product cards, Header links etc. Use React Routers Link component instead.

6. Design and build the ProductScreen component.

  1. Setting up the backend
    • Close the React server.
    • Create a folder named backend outside the frontend folder in the root of our project.
    • npm init in the root. (not inside the backend or frontend folders, but outside in the root directory)
    • During npm init setup the main will be server.js
    • npm install express (in the root folder)
    • Create a file backend/server.js in the backend folder and a folder data and copy products.js to this folder.
    • Create some routes to serve the data from the backend
    • Create a script for start in package.json
    • Create 2 basic routes for ‘/’ and ‘/api/products’
    • Convert products.js export statement to commonjs format.
    • Create another route to fetch single product by id.
  1. Fetching data from our backend using React
    • Inside the frontend folder, run npm install axios
    • Modify the HomeScreen component to fetch and store data in the component.
    • To fix the issue of our backend address for now, we’ll add a proxy to the frontend’s package.json. Add this “proxy”: “http://127.0.0.1:5000”, to frontend/package.json
    • Make sure both frontend and backend are running in two terminals and test it out.
    • Modify the ProductScreen component to also make a request to our backend to fetch data.
    • Delete the projects.js file from our frontend’s src folder as we no longer need it.

9. More backend setup

  • In the root directory: run
  • npm install -D nodemon concurrently. ‘-D’ is a dev dependency, meaning we only need these modules during development.
  • These above packages will help us auto restart our server when we change our code, so we don’t have to do it manually.
  • Modify scripts in package.json (root folder) to add some scripts to use our npm command directly to work them.

10. Setup environment variables

  • npm install dotenv
  • Do the dotenv setup in server.js file and create a .env file in the root folder.

11. Convert imports to ES Modules

  • Add “type”: “module” to package.json file. Change all import and export statements to ES module style.
  • Note: You will have to add .js extension while using ES modules in the backend.

12. Install and setup MongoDB

  • After installation, setup MongoDB Compass
  • Use this as the connection string: mongodb://localhost:27017/rststore
  • Add the following in the .env
    MONGO_URI = mongodb://localhost:27017/rststore

13. Connect to the database

  • Install mongoose: npm install mongoose (in the root folder)
  • Create a folder named config in the backend folder and create a file named backend/config/db.js inside it.
  • Do all the mongoDB connection setup
  • Import db.js into server.js and run the connectDB function.
  • Start the server and check if any error.

14. Improve console log messages.

  • Run this command in the root folder: npm install colors
  • Add stylings to server and db console messages.

15. Create database models for data

  • Create a models folder inside the backend folder.
  • Create all our data model schemas.

16. Prepare sample data for the backend data seeding

  • Delete all the _id key-values from the products.js as MongoDB
    will automatically create it for us.
  • Create data/users.js file and fill it with a few user objects.
  • npm install bcryptjs – for password hashing
  • Use bcryptjs for the password fields to encrypt the password. (temporary)

17. Create database seeder for quick sample data generation (optional)

  • Create backend/seeder.js file inside the backend folder.
  • Add seeding logic and create import and destroy scripts.

18. Fetching products from the database

  • Create a folder named backend/routes in the backend folder.
  • Create a file named backend/routes/productRoutes.js
  • npm install express-async-handler – we will wrap our callbacks with this function so that we can do error handler in a better way.
  • Move the products and single product fetch routes to this file and add all the logic for now.
  • Test the routes in Postman

19. Do Postman setup to work with our API (optional)Custom error handling. Run the following in the root folder.

20. Custom error handling. Run the following in the root folder.

  • npm install express-async-handler
  • Create a folder named backend/middleware in the backend folder
  • Create an errorMiddleware.js and add logic to handle errors.

21. Introduction to Redux

  • The Redux Pattern
  • Download the Redux DevTools brower extension.
  • Go to the frontend folder. cd frontend
  • npm install redux react-redux redux-thunk redux-devtools-extension
  • In the src folder, create a file named store.js
  • Import Provider and store into the index.js and do all the setup.