Back to Freecodecamp

Step 44

curriculum/challenges/english/blocks/learn-asynchronous-programming-by-building-an-fcc-forum-leaderboard/645f06144bc0dc0143a5a3a2.md

latest6.8 KB
Original Source

--description--

Each forum post will include a list of user avatar images which represent all of the users participating in the conversation for that topic.

Start by creating an arrow function called avatars, with two parameters called posters and users.

--hints--

You should have an empty arrow function called avatars.

js
assert.match(code, /const\s+avatars\s*=\s*\([\s\S]*\)\s*=>\s*{\s*}/);

You should have the parameters named posters and users in the function named avatars.

js
assert.match(code, /const\s+avatars\s*=\s*\(\s*(posters|users)\s*,\s*(posters|users)\s*\)\s*=>\s*{\s*}/);

--seed--

--seed-contents--

html
<!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>fCC Forum Leaderboard</title>
    <link rel="stylesheet" href="./styles.css" />
  </head>
  <body>
    <header>
      <nav>
        
      </nav>
      <h1 class="title">Latest Topics</h1>
    </header>
    <main>
      <div class="table-wrapper">
        <table>
          <thead>
            <tr>
              <th id="topics">Topics</th>
              <th id="avatars">Avatars</th>
              <th id="replies">Replies</th>
              <th id="views">Views</th>
              <th id="activity">Activity</th>
            </tr>
          </thead>
          <tbody id="posts-container"></tbody>
        </table>
      </div>
    </main>
    <script src="./script.js"></script>
  </body>
</html>
css
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

:root {
  --main-bg-color: #2a2a40;
  --black: #000;
  --dark-navy: #0a0a23;
  --dark-grey: #d0d0d5;
  --medium-grey: #dfdfe2;
  --light-grey: #f5f6f7;
  --peach: #f28373;
  --salmon-color: #f0aea9;
  --light-blue: #8bd9f6;
  --light-orange: #f8b172;
  --light-green: #93cb5b;
  --golden-yellow: #f1ba33;
  --gold: #f9aa23;
  --green: #6bca6b;
}

body {
  background-color: var(--main-bg-color);
}

nav {
  background-color: var(--dark-navy);
  padding: 10px 0;
}

.fcc-logo {
  width: 210px;
  display: block;
  margin: auto;
}

.title {
  margin: 25px 0;
  text-align: center;
  color: var(--light-grey);
}

.table-wrapper {
  padding: 0 25px;
  overflow-x: auto;
}

table {
  width: 100%;
  color: var(--dark-grey);
  margin: auto;
  table-layout: fixed;
  border-collapse: collapse;
  overflow-x: scroll;
}

#topics {
  text-align: start;
  width: 60%;
}

th {
  border-bottom: 2px solid var(--dark-grey);
  padding-bottom: 10px;
  font-size: 1.3rem;
}

td:not(:first-child) {
  text-align: center;
}

td {
  border-bottom: 1px solid var(--dark-grey);
  padding: 20px 0;
}

.post-title {
  font-size: 1.2rem;
  color: var(--medium-grey);
  text-decoration: none;
}

.category {
  padding: 3px;
  color: var(--black);
  text-decoration: none;
  display: block;
  width: fit-content;
  margin: 10px 0 10px;
}

.career {
  background-color: var(--salmon-color);
}

.feedback,
.html-css {
  background-color: var(--light-blue);
}

.support {
  background-color: var(--light-orange);
}

.general {
  background-color: var(--light-green);
}

.javascript {
  background-color: var(--golden-yellow);
}

.backend {
  background-color: var(--gold);
}

.python {
  background-color: var(--green);
}

.motivation {
  background-color: var(--peach);
}

.avatar-container {
  display: flex;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
}

.avatar-container img {
  width: 30px;
  height: 30px;
}

@media (max-width: 750px) {
  .table-wrapper {
    padding: 0 15px;
  }

  table {
    width: 700px;
  }

  th {
    font-size: 1.2rem;
  }

  .post-title {
    font-size: 1.1rem;
  }
}
js
const forumLatest = "https://cdn.freecodecamp.org/curriculum/forum-latest/latest.json";
const forumTopicUrl = "https://forum.freecodecamp.org/t/";
const forumCategoryUrl = "https://forum.freecodecamp.org/c/";
const avatarUrl = "https://sea1.discourse-cdn.com/freecodecamp";

const postsContainer = document.getElementById("posts-container");

const allCategories = {
  299: { category: "Career Advice", className: "career" },
  409: { category: "Project Feedback", className: "feedback" },
  417: { category: "freeCodeCamp Support", className: "support" },
  421: { category: "JavaScript", className: "javascript" },
  423: { category: "HTML - CSS", className: "html-css" },
  424: { category: "Python", className: "python" },
  432: { category: "You Can Do This!", className: "motivation" },
  560: { category: "Back-End Development", className: "backend" },
};

const forumCategory = (id) => {
  let selectedCategory = {};

  if (allCategories.hasOwnProperty(id)) {
    const { className, category } = allCategories[id];

    selectedCategory.className = className;
    selectedCategory.category = category;
  } else {
    selectedCategory.className = "general";
    selectedCategory.category = "General";
    selectedCategory.id = 1;
  }
  const url = `${forumCategoryUrl}${selectedCategory.className}/${id}`;
  const linkText = selectedCategory.category;
  const linkClass = `category ${selectedCategory.className}`;

  return `<a href="${url}" class="${linkClass}" target="_blank">
    ${linkText}
  </a>`;
};

const timeAgo = (time) => {
  const currentTime = new Date();
  const lastPost = new Date(time);

  const timeDifference = currentTime - lastPost;
  const msPerMinute = 1000 * 60;

  const minutesAgo = Math.floor(timeDifference / msPerMinute);
  const hoursAgo = Math.floor(minutesAgo / 60);
  const daysAgo = Math.floor(hoursAgo / 24);

  if (minutesAgo < 60) {
    return `${minutesAgo}m ago`;
  }

  if (hoursAgo < 24) {
    return `${hoursAgo}h ago`;
  }

  return `${daysAgo}d ago`;
};

const viewCount = (views) => {
  const thousands = Math.floor(views / 1000);

  if (views >= 1000) {
    return `${thousands}k`;
  }

  return views;
};

--fcc-editable-region--

--fcc-editable-region--

const fetchData = async () => {
  try {
    const res = await fetch(forumLatest);
    const data = await res.json();
    showLatestPosts(data);
  } catch (err) {
    console.log(err);
  }
};

fetchData();

const showLatestPosts = (data) => {
  const { topic_list, users } = data;
  const { topics } = topic_list;

  postsContainer.innerHTML = topics.map((item) => {
    const {
      id,
      title,
      views,
      posts_count,
      slug,
      posters,
      category_id,
      bumped_at,
    } = item;

    return `
    <tr>
      <td>
        <p class="post-title">${title}</p>
        ${forumCategory(category_id)}
      </td>
      <td></td>
      <td>${posts_count - 1}</td>
      <td>${viewCount(views)}</td>
      <td>${timeAgo(bumped_at)}</td>
    </tr>`;
  }).join("");
};