A modern, responsive web application for tracking and managing GitHub issues with an intuitive user interface built using HTML, Tailwind CSS (with DaisyUI), and vanilla JavaScript.
Okay, so this trips up a lot of people. Here's the deal: var is the old-school way of declaring variables in JavaScript. It's function-scoped, which means it doesn't care about block scope (like if statements or loops), and you can redeclare it without any errors. Kind of messy, honestly.
Then ES6 introduced let and const, which are way better. Both are block-scoped, so they only exist within the curly braces {} where you defined them. The difference? let lets you reassign the value later, but const doesn't - it's constant (hence the name).
Here's a quick example:
var name = "Afjal Hossain";
let age = 24;
const country = "USA"; I pretty much use const by default now, and only switch to let when I know the value needs to change. Haven't used var in ages.
The spread operator is one of those features that once you start using, you can't stop. Those three little dots ... basically "spread out" an array or object into individual elements. Super useful for copying stuff or combining things.
For arrays:
const numbers = [1, 2, 3];
const moreNumbers = [...numbers, 4, 5]; For objects:
const person = { name: "Sarah", age: 30 };
const updatedPerson = { ...person, city: "NYC" }; These three are your bread and butter for working with arrays. They look similar but do totally different things.
forEach() just loops through each item. It doesn't return anything - you use it when you want to do something with each element but don't need a new array:
issues.forEach(issue => console.log(issue.title)); map() transforms each element and returns a NEW array with the transformed values. Perfect when you need to create something based on the original array:
const titles = issues.map(issue => issue.title);filter() returns a NEW array with only the elements that pass your condition:
const openIssues = issues.filter(issue => issue.status === 'open');In this project, I use filter() a ton for the filtering functionality, and map() to generate the label HTML. They're incredibly powerful once you get the hang of them.
Arrow functions are just a shorter, cleaner way to write functions. Instead of typing function, you use => (looks like an arrow, right?). They're everywhere in modern JavaScript.
Old way:
function add(a, b) {
return a + b;
}Arrow function way:
const add = (a, b) => a + b; The cool thing is, if you only have one parameter, you can skip the parentheses. And if it's a single expression, you can skip the curly braces AND the return keyword - it's implicit:
const double = x => x * 2; I use arrow functions throughout this project, especially in array methods like map() and filter(). They also have some quirks with the this keyword compared to regular functions, but that's a whole other conversation.
Template literals changed the game for working with strings in JavaScript. Instead of regular quotes, you use backticks `, and then you can inject variables directly into the string using ${variable}.
Old way (gross):
const greeting = "Hello, " + name + "! You have " + count + " messages.";Template literal way (clean):
const greeting = `Hello, ${name}! You have ${count} messages.`; | Technology | Purpose |
|-----------|---------|
| HTML5 | Semantic markup structure |
| Tailwind CSS v4 | Utility-first CSS framework |
| DaisyUI v5 | Pre-built component library |
| Vanilla JavaScript | Pure JS without frameworks |
| REST API | External data fetching |
API Request → Loading Spinner → Data Fetch → Process Data → Render Cards → Hide Spinner
```javascript
{
"id": 1,
"title": "Fix navigation menu on mobile devices",
"description": "The navigation menu doesn't collapse properly...",
"status": "open" | "closed",
"labels": ["bug", "help wanted"],
"priority": "high" | "medium" | "low",
"author": "john_doe",
"assignee": "jane_smith",
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}
- If you found this helpful, please star the repository!**