Giter Club home page Giter Club logo

m3-3-node--facespace's Introduction

Facespace!

Goal

To create a site that will serve up Facespace! Oh, and learn a little more about Node, routing, EJS, and CSS along the way.

Setup

  • yarn install
  • yarn dev to launch the server.

About the Data

There is a file /data/users.js that contains an array of users. Each user looks like this.

{
  _id: '1008',
  name: 'Fletcher',
  friends: ['1006', '1007', '1009'], // array of the ids of user's friends
  avatarUrl: '/images/profile-pics/000003.jpg',
},

About the CSS

The project is coming to you entirely styled! Let me repeat that: All of the CSS is done for you. ๐Ÿ˜ฑ I know, right! But because nothing is free, you will have to figure out the classes that go with each element. You are able to achieve the same look by assigning the css classes to the right element.

The Workshop

Exercise 1 - The Homepage

The homepage should show a grid of all of the users in the system.

1.1 Create the homepage endpoint

Create a GET endpoint for the homepage. Update your server.js file to match this.

  'use strict';

  const express = require('express');
  const morgan = require('morgan');

  const { users } = require('./data/users');

  // declare the 404 function
  const handleFourOhFour = (req, res) => {
    res.status(404).send("I couldn't find what you're looking for.");
  };

+ const handleHomepage = (req, res) => {
+   res.status(200).send('homepage');
+ };

  // -----------------------------------------------------
  // server endpoints
  express()
    .use(morgan('dev'))
    .use(express.static('public'))
    .use(express.urlencoded({ extended: false }))
    .set('view engine', 'ejs')

    // endpoints
+  .get('/', handleHomepage)

    // a catchall endpoint that will send the 404 message.
    .get('*', handleFourOhFour)

    .listen(8000, () => console.log('Listening on port 8000'));

Once you've added this right code, load the homepage at http://localhost:8000. You should see this.

1.2 Create the homepage.ejs template

  • In views/pages/ there is a file called homepage.ejs
  • Add this code to that file.
<!-- note that all of our page templates will include a header and footer partial -->
<%- include('../partials/header') %>
<div class="home-page">
  <h2>All Facespace members</h2>
  <!-- content here -->
</div>
<%- include('../partials/footer') %>

1.3 Render the homepage

To render the homepage, you will need to modify the handleHomepage function. Instead of sending something. Let's render the homepage.ejs file that we just created.

  const handleHomepage = (req, res) => {
-   res.status(200).send('homepage');
+   res.status(200).render('pages/homepage');
  };

You should now see this in the browser:

1.4 Render all of the users

First we need to pass the users data to the ejs template. When rendering an ejs template, we can pass it an object as the second argument that can contain anything we like. In this case, we want to pass the entire users array.

res.status(200).render('pages/homepage', { users: users });

Once the data is available to the template, we need to loop through the array and render all of the images.

<ul class="homepage__all">
  <% users.forEach(user => { %>
  <li class="homepage__all--user">
    <img src="<%= user.avatarUrl %>" />
  </li>
  <% }) %>
</ul>

You should now see this in the browser:


Exercise 2 - The Profile Page

Let's create a profile page that will be unique to each user. Our endpoint should contain the user's _id, which will allow us to "know" which data to use.

2.1 Create a users endpoint

Create a GET endpoint that we can use to show the user's profile page. Your endpoint should start with /users/ and end with a url param for the _id.

This endpoint will trigger a function handleProfilePage that you will need to create as well. For now, have that function res.send the _id that is in the url.

2.2 Create the Profile Page and render it

In /views/page/, create a file called profile.ejs. This will be the page that we render, at the endpoint we created above.

Here is the beginning of the code, you will need for this file.

<%- include('../partials/header') %>
<div class="profile-page">
  <%= user.name %>
</div>
<%- include('../partials/footer') %>

Convert the res.send you have in handleProfilePage to a res.render of that profile page.

Notice the temporary insertion of the user.name into the ejs template. You can use that to confirm that your endpoint is functioning properly. Currently, it should not be working. We need to send the user data to the ejs template.

Add the user's data to that object. You will need to figure out which user data to send based on the provided _id in the url params.

2.3 Render all of the user's data to the page.

  • Render the user's avatar, and name.

  • ๐Ÿ’Ž Render the list of friends.

<div>
  <h3><%= user.name %>'s Friends</h3>
  <ul>
    <!-- loop over the array of friends -->
    <!-- each friend's image and name should be visible. -->
  </ul>
</div>

2.4 Create the HTML and CSS for the Profile page

Below is what the profile page should look like. While it doesn't need to be pixel-perfect, it should be close enough as to not look different from the images below. I've provided the mobile version as well.


Exercise 3 - The Sign in page

Our security system will be total crap, but will work for our purposes. True site security is too important for us to implement ourselves! When the time comes, we'll leverage code from experts in the field.

For this workshop, we're going to simply ask for the user's first name and if it's in the users array, we'll assume that that is the person that is logging in.

3.1 Create the endpoint

In server.js we need to have an endpoint that will receive requests for the signin page. This endpoint will call a function called handleSignin. For testing purposes, do a res.send('ok') in that function. This will allow us to confirm that the signin endpoint works.

3.2 Create the form

In views/pages, create a new file called signin.ejs. Add the following ejs code to the file. Take a few minutes to go over this code and make sure you understand what it's doing.

<%- include('../partials/header') %>
<div>
  <form method="get" action="/getname">
    <label for="firstName">First name</label>
    <input type="text" name="firstName" placeholder="Your first name" />
    <button type="submit">Submit</button>
  </form>
</div>
<%- include('../partials/footer') %>

3.3 Render the signin page.

The form we've just added doesn't yet render on the /signin page. We need to tell handleSign to render that particular ejs page template.

3.4 Receive the data from the form

Our form looks good but it doesn't yet do anything. We need the form to send the input to the server.

Notice that the form (in signin.ejs) has action attribute. That is the endpoint that the form will contact when a user submits the form. Let's create a GET endpoint that will receive the data from the form.

.get('/getname', handleName)

This type of HTML form sends the data from the form as query parameters in the request.

  1. Define a variable firstName and assign the value of req.query.firstName. You can also write a temporary console.log() to make sure that your function works and that you have access to the value of firstName.
  2. Use the firstName to find() that user's data in users.js. That array is already imported and available to you. (See line 6 of server.js).
  3. If it exists redirect to that user's profile page.
  4. If it doesn't exist, redirect to the signin page. (This is a reload of the signin page.)

We can redirect the browser to an endpoint with the following code.

res.redirect('/the-endpoint');
  1. You should also return a status code to the browser.
res.status(200); // when the request is successful
res.status(404); // when the request is not successful. In this case, the user was not found.

It is good practice to chain our status and our render like so:

res.status(404).render('/signin');

๐ŸŸก - Minimally complete workshop (75%) - ๐ŸŸก

Exercise 4 Tying all of the pages together.

We now have a functioning app! ๐Ÿ™Œ Let's add more functionality to the make it better.

โš ๏ธ As of now, you are on your own for the CSS of any added functionality.

4.1 - A link to the signin page in the header

We should have a link to the signin page in the header.

When the user is signed in, the "sign in" link should be replaced by a greeting and the user's name.

This will mean storing the user data in memory, and passing it to header.ejs. You can store the current user object in currentUser variable that is defined in the server.js file. This will store the current user in the server memory until the server is restarted.

While you're in the header, it would be good to turn the title into a link to the homepage.

Hint: Passing data to a page template also makes it accessible all partials included that page.

4.2 Faces on the homepage

  • Faces on the homepage should link to that person's profile page.
  • Let's also add a little UX tweak on hover. Give the image some sort of effect on hover.

4.3 My Friends!

When a user is signed in and looking at the homepage, it would be great if there were some visual indication as to who their friends are in the grid of faces. My example is a ribbon on the image, but feel free to do whatever you like.

4.4 No Sign in for you!

If someone is already signed in, they should not be able to see the signin page. Currently, if a user signs in and navigates to http://localhost:8000/signin, they will see the sign in page.

Prevent this from happening.


๐ŸŸข - Complete workshop (100%) - ๐ŸŸข

Stretch Goals

Here are some other features that you could add to the app. None of these have any solutions.

  1. User can add/remove friends. This should update the friends array of both users. Being friends is reciprocal.
  2. If a user adds a friend, they are not automatically added. The other user needs to accept this first. It would be useful to create a new array of pendingFriends in the user object.
  3. A sign up page... that does exactly what you would expect.
  4. What else can you think of?

m3-3-node--facespace's People

Contributors

scottanthonymorin avatar

Stargazers

 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.