diff --git a/README.md b/README.md
index 1613a3b0..c015204b 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,11 @@
# GitHub Tracker
-Replace this readme with your own information about your project.
-
-Start by briefly describing the assignment in a sentence or two. Keep it short and to the point.
+A GitHub clone website to practice REST API with vanilla Javascript.
## The problem
-Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next?
+The biggest challenge was rate limit boundary even though the request header contains authentication token. In case of exceeding rate limit boundary, the website will display an error message and ask users to visit after an hour. The issue is caused by sending too many requests when page is loading and this was not avoidable because the website requires data from different paths. So for the display purpose, the deployed website is based on a dummy data.
## View it live
-Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about.
+https://github-clone-2022.netlify.app
diff --git a/code/.babelrc b/code/.babelrc
new file mode 100644
index 00000000..897c585c
--- /dev/null
+++ b/code/.babelrc
@@ -0,0 +1,4 @@
+{
+ "presets": ["@babel/env"],
+ "plugins": ["@babel/plugin-transform-runtime"]
+}
diff --git a/code/.gitignore b/code/.gitignore
new file mode 100644
index 00000000..178eb0ec
--- /dev/null
+++ b/code/.gitignore
@@ -0,0 +1,5 @@
+node_modules
+build
+.env
+dummyData
+.netlify
\ No newline at end of file
diff --git a/code/assets/dummy.png b/code/assets/dummy.png
new file mode 100644
index 00000000..55b68c0e
Binary files /dev/null and b/code/assets/dummy.png differ
diff --git a/code/assets/icons/arrow-down.svg b/code/assets/icons/arrow-down.svg
new file mode 100644
index 00000000..1980ab34
--- /dev/null
+++ b/code/assets/icons/arrow-down.svg
@@ -0,0 +1,3 @@
+
diff --git a/code/assets/icons/bars-solid.svg b/code/assets/icons/bars-solid.svg
new file mode 100644
index 00000000..79881b04
--- /dev/null
+++ b/code/assets/icons/bars-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/code/assets/icons/bell-regular.svg b/code/assets/icons/bell-regular.svg
new file mode 100644
index 00000000..1db17a7d
--- /dev/null
+++ b/code/assets/icons/bell-regular.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/code/assets/icons/checked.svg b/code/assets/icons/checked.svg
new file mode 100644
index 00000000..b8b982cd
--- /dev/null
+++ b/code/assets/icons/checked.svg
@@ -0,0 +1,3 @@
+
diff --git a/code/assets/icons/code-commit-solid.svg b/code/assets/icons/code-commit-solid.svg
new file mode 100644
index 00000000..36088ff0
--- /dev/null
+++ b/code/assets/icons/code-commit-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/code/assets/icons/code-fork-solid.svg b/code/assets/icons/code-fork-solid.svg
new file mode 100644
index 00000000..580b7f4d
--- /dev/null
+++ b/code/assets/icons/code-fork-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/code/assets/icons/code-pull-request-solid.svg b/code/assets/icons/code-pull-request-solid.svg
new file mode 100644
index 00000000..dc1d3c29
--- /dev/null
+++ b/code/assets/icons/code-pull-request-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/code/assets/icons/favicon.ico b/code/assets/icons/favicon.ico
new file mode 100644
index 00000000..5cfb07e1
Binary files /dev/null and b/code/assets/icons/favicon.ico differ
diff --git a/code/assets/icons/github-brands.svg b/code/assets/icons/github-brands.svg
new file mode 100644
index 00000000..c54e144e
--- /dev/null
+++ b/code/assets/icons/github-brands.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/code/chart.js b/code/chart.js
deleted file mode 100644
index 92e85a30..00000000
--- a/code/chart.js
+++ /dev/null
@@ -1,4 +0,0 @@
-//DOM-selector for the canvas π
-const ctx = document.getElementById('chart').getContext('2d')
-
-//"Draw" the chart here π
diff --git a/code/components/filter.js b/code/components/filter.js
new file mode 100644
index 00000000..7789f0dd
--- /dev/null
+++ b/code/components/filter.js
@@ -0,0 +1,40 @@
+import { createElement } from "../utility/createElem";
+import FilterButtonComp from "./filterButton";
+export default function FilterComp() {
+ const filterContainer = createElement("div", "filter-container");
+ const filterForm = createElement("form", "filter-form");
+ const filterFormInput = createElement("input", "filter-input");
+ filterFormInput.setAttribute("type", "text");
+ filterFormInput.setAttribute("placeholder", "Find a repository..");
+ filterForm.appendChild(filterFormInput);
+
+ const sortByLanguage = ["javascript", "typescript", "html", "css"];
+ const sortBy = ["last updated", "name"];
+
+ const filterByLanguage = FilterButtonComp(
+ "Language",
+ "languageSelector",
+ "programing-language",
+ "language-item",
+ sortByLanguage
+ );
+ const filterByDate = FilterButtonComp(
+ "Sort",
+ "sortSelector",
+ "sort-by",
+ "sort-item",
+ sortBy
+ );
+
+ filterForm.appendChild(filterByLanguage);
+ filterForm.appendChild(filterByDate);
+
+ filterForm.addEventListener("submit", (e) => {
+ e.preventDefault();
+ console.log("filter form submitted");
+ filterForm.reset();
+ });
+
+ filterContainer.appendChild(filterForm);
+ return filterContainer;
+}
diff --git a/code/components/filterButton.js b/code/components/filterButton.js
new file mode 100644
index 00000000..f41b9f69
--- /dev/null
+++ b/code/components/filterButton.js
@@ -0,0 +1,89 @@
+import arrowButton from "../assets/icons/arrow-down.svg";
+import checkedIcon from "../assets/icons/checked.svg";
+import { createElement } from "../utility/createElem";
+import { capitalizeFirstLetter } from "../utility/capitalizeFirst";
+
+export default function FilterButtonComp(
+ buttonName,
+ filterId,
+ filterTypeClassname,
+ listItemClassname,
+ filterLists
+) {
+ const filterBtnContainer = createElement("div", "filter-btn-container");
+ const filterBtn = createElement("button", "filter-btn");
+ filterBtn.setAttribute("type", "button");
+
+ filterBtn.id = "languageBtn";
+ filterBtn.innerHTML = `
+ ${buttonName}
+ `;
+
+ const filterBtnPositioner = createElement("div", "filter-btn-positioner");
+ const filterSelectorLists = createElement("ul", filterTypeClassname);
+ filterSelectorLists.id = filterId;
+
+ const filterTitleContainer = createElement("li", listItemClassname);
+ filterTitleContainer.classList.add("filter-title");
+
+ const filterTitle = createElement("span", "span-title");
+ filterTitle.innerText = "Select type";
+
+ const closeBtn = createElement("button", "close-btn");
+ closeBtn.setAttribute("type", "button");
+ closeBtn.innerHTML = "×";
+
+ filterTitleContainer.appendChild(filterTitle);
+ filterTitleContainer.appendChild(closeBtn);
+ filterSelectorLists.appendChild(filterTitleContainer);
+
+ const listAttributes = filterLists;
+ listAttributes.forEach((item) => {
+ const li = createList(listItemClassname, item);
+ filterSelectorLists.appendChild(li);
+ });
+ filterBtnPositioner.appendChild(filterSelectorLists);
+
+ filterBtnContainer.appendChild(filterBtn);
+ filterBtnContainer.appendChild(filterBtnPositioner);
+
+ // addEventlisteners
+ filterSelectorLists.addEventListener("click", (e) => {
+ if (e.target.nodeName !== "BUTTON" && e.target.nodeName !== "LI") {
+ return;
+ }
+ if (e.target.id !== "") {
+ console.log("filter by", e.target.id);
+ }
+ filterSelectorLists.classList.remove("active");
+ });
+
+ filterBtn.onclick = function displaySelection() {
+ const sortBtn = document.querySelector("#sortSelector");
+ const languageBtn = document.querySelector("#languageSelector");
+ if (
+ sortBtn.className.includes("active") ||
+ languageBtn.className.includes("active")
+ ) {
+ sortBtn.classList.remove("active");
+ languageBtn.classList.remove("active");
+ } else {
+ filterSelectorLists.classList.add("active");
+ }
+ };
+ return filterBtnContainer;
+}
+
+function createList(classname, text) {
+ const listItem = createElement("li", classname);
+ listItem.id = text.replace(/\s/g, "");
+ listItem.innerHTML = `
+
+ ${capitalizeFirstLetter(text)}
+ `;
+ return listItem;
+}
diff --git a/code/components/header.js b/code/components/header.js
new file mode 100644
index 00000000..f56cc73c
--- /dev/null
+++ b/code/components/header.js
@@ -0,0 +1,72 @@
+import notificationIconSrc from "../assets/icons/bell-regular.svg";
+import githugLogoSrc from "../assets/icons/github-brands.svg";
+import { createElement } from "../utility/createElem";
+
+export default function HeaderComp(userProfileImage) {
+ const header = createElement("header", "header");
+ //[todo] unable to change color in svg when it is in img tag. update it later
+ const barIcon = `
+
+ `;
+
+ const headerContainer = createElement("div", "header-container");
+
+ const githubLogo = createElement("img", "logo");
+ githubLogo.src = githugLogoSrc;
+
+ const searchForm = createElement("form", "search-container");
+ searchForm.innerHTML = `
+
+ `;
+ searchForm.onsubmit = (e) => {
+ e.preventDefault();
+ //[todo] update function
+ console.log("search form is called");
+ searchForm.reset();
+ };
+
+ const nav = createElement("nav", "nav");
+ const ul = createElement("ul", "nav-list");
+ ul.innerHTML = `
+
Forked from ${forkedFrom}
+ Branch: ${branch} + `; + + const spec = createElement("article", "card-spec"); + + const languageSpec = createElement("div", "spec-container"); + const languageId = languageIdentity || "unknown"; + languageSpec.innerHTML = ` + + ${capitalizeFirstLetter(languageId)} + `; + + const forkedContent = `