diff --git a/index.html b/index.html new file mode 100644 index 0000000..d6b7d62 --- /dev/null +++ b/index.html @@ -0,0 +1,65 @@ + + + + + + + + Github Profiles + + + +

GitHub Profile Finder

+ +
+ +
+ +

LOADING...

+ +
+
+ +
+ +
+
+
Show
+ +
Per Page
+
+ +
+ +
+ +
+ +
+ +
+ +
+ +

Created By Aishwarya Upadhyay

+ + + + + + diff --git a/script.js b/script.js new file mode 100644 index 0000000..f8fb8fc --- /dev/null +++ b/script.js @@ -0,0 +1,298 @@ +const APIURL = 'https://api.github.com/users/' + +const loading = document.getElementById("loading") +const mainBody = document.getElementById('main') + +const form = document.getElementById('form') +const search = document.getElementById('search') +const main = document.getElementById('cardInfo') +const repoCard = document.getElementById('repoCard') +var datasetLength = 0 +var index = 1 +var itemsPerPage = 5 +var pageUI = document.querySelector('.pagination') +var itemShow = document.getElementById('itemperpage') + +var str = '' + +//Function to create a loader +function showLoader() { + loading.style.display = 'block'; +} + +//Function to hide the loader +function hideLoader() { + loading.style.display = 'none'; +} + +//Making API CALL to get a specific user from username. This endpoint does not require auth bearer token +async function getUser(username) { + try { + const { data } = await axios(APIURL + username) + + hideLoader() + mainBody.style.display = 'flex'; + + datasetLength = data.public_repos + createUserCard(data) + loadChangeValue() + //getRepos(str) + + } catch (error) { + if(error.response.status == 404) + { + createErrorCard('This username does not exist') + } + } +} + +//Making API CALL to get the repos. This endpoint does not require auth bearer token +async function getRepos(username) { + try { + const { data } = await axios(APIURL + username + '/repos?per_page=' + itemsPerPage + '&page=' + index) + + createRepoCard(data) + } catch (error) { + if(error.response.status == 404) + { + createErrorCard('Oops!! Something went wrong') + } + } +} + +//Function to display the user info +function createUserCard(user) { + const userHTML = ` +
+ ${user.name} +
+
+

${user.name}

+ ${user.bio}
+ +  ${user.location} +

Visit GitHub Profile

+

Twitter Username : ${user.twitter_username}

+ + +
+ ` + + main.innerHTML = userHTML + + const rpoHtml = ` +
+ ` + repoCard.innerHTML = rpoHtml + + +} + +//Function to display the repo info +function createRepoCard(repos) { + const reposLocation = document.getElementById('repos') + const len = repos.length - 1 + + repos + .slice(0, len) + .forEach(repo => { + var repoHtml = ` +
+

${repo.name}

+

${repo.description}

+

${repo.language}

+
+ ` + + reposLocation.innerHTML += repoHtml + + }) + +} + +//Function to display the error message +function createErrorCard(msg) { + const cardHTML = ` +
+

${msg}

+
+ ` + + main.innerHTML = cardHTML + + const rpoHtml = ` +
+ ` + repoCard.innerHTML = rpoHtml +} + +//Function to update the repo info on pagination +function loadChangeValue() { + itemsPerPage = itemShow.value + + const rpoHtml = ` +
+ ` + repoCard.innerHTML = rpoHtml + + getRepos(str) + + //First of all clearing all the existing page buttons generated from previous events + const pageNum = pageUI.querySelectorAll('.list') + pageNum.forEach(n=>n.remove()) + + //Then creating the new page btns for the current event + pageBtnGenerator(itemsPerPage) + + // Set the first page button as active without triggering a click + const firstPageButton = pageUI.querySelector('a[data-page="1"]'); + //firstPageButton.click(); + firstPageButton.classList.add('active'); + firstPageButton.style.backgroundColor = 'blue'; + firstPageButton.style.color = 'white'; + + + // Adding an event listener to the search input for filtering + const searchInput = document.getElementById('searchrepo'); + searchInput.addEventListener('input', function () { + const searchTerm = this.value.trim(); + filterRepos(searchTerm); + }); +} + +//Function to search the repository and filter it out +function filterRepos(searchTerm) { + // Get all repositories + const allRepos = document.querySelectorAll('.repoCard'); + + // Hide or show repositories based on the search term + allRepos.forEach(repo => { + const repoName = repo.querySelector('a').innerText.toLowerCase(); + if (repoName.includes(searchTerm.toLowerCase())) { + repo.style.display = 'block'; + } else { + repo.style.display = 'none'; + } + }); + +} + +//To dynamically create page buttons +function pageBtnGenerator(getitem) { + console.log("datasetLength = " + datasetLength) + console.log("getitem = " + getitem) + if(datasetLength <= getitem) { + pageUI.style.display = 'none'; + } + else { + pageUI.style.display = 'flex'; + const num_of_page = Math.ceil(datasetLength/getitem); + for(let i=1; i<=num_of_page; i++) { + const li = document.createElement('li'); + li.className = 'list'; + const a = document.createElement('a'); + a.href = '#'; + a.innerText = i; + a.setAttribute('data-page', i); + li.appendChild(a); + pageUI.insertBefore(li, pageUI.querySelector('.next')); + } + + // Update pageLink after adding new buttons + var pageLink = pageUI.querySelectorAll("a"); + console.log("pageLink.length " + pageLink.length) + // Calling pageRunner to handle click events + pageRunner(pageLink, getitem, num_of_page); + } +} + +//To mark the page being shown on page button +function pageRunner(page, items, lastPage) { + for (button of page) { + button.onclick = e => { + const page_num = e.target.getAttribute('data-page'); + const page_mover = e.target.getAttribute('id'); + + // Removing the 'active' class and reset styling from all buttons + page.forEach(btn => { + btn.classList.remove('active'); + btn.style.backgroundColor = ''; // Reseting background color + btn.style.color = ''; // Reseting text color + }); + + if (page_num != null) { + index = page_num; + // Adding the 'active' class and styling to the clicked button + e.target.classList.add('active'); + e.target.style.backgroundColor = 'blue'; // Changing the color of btns + e.target.style.color = 'white'; + + } else { + if (page_mover === "next") { + index++; + if (index > lastPage) { + index = lastPage; + } + } else { + index--; + if (index < 1) { + index = 1; + } + } + + // Find the button corresponding to the new index and add 'active' class and styling + const newActiveButton = pageUI.querySelector(`a[data-page="${index}"]`); + newActiveButton.classList.add('active'); + newActiveButton.style.backgroundColor = 'blue'; // Change the color + newActiveButton.style.color = 'white'; + + } + + // Calling function to display content for the selected page + displayPageContent(index, items); + }; + } +} + +//Making api call for server side pagination +async function displayPageContent(pageNumber, itemsPerPage) { + //To fetch and display content for the selected page + console.log(`Fetching and displaying content for page ${pageNumber} with ${itemsPerPage} items per page.`); + // updating the UI to make additional API calls + + const rpoHtml = ` +
+ ` + repoCard.innerHTML = rpoHtml + + try { + const { data } = await axios(APIURL + str + '/repos?per_page=' + itemsPerPage + '&page=' + pageNumber) + + createRepoCard(data) + } catch (error) { + if(error.response.status == 404) + { + createErrorCard('Oops!! Something went wrong') + } + } +} + + +form.addEventListener('submit', (e) => { + e.preventDefault() + + showLoader() + + const username = search.value + str = username + if(username) { + getUser(username) + + search.value = '' + } +}) + diff --git a/style.css b/style.css new file mode 100644 index 0000000..f987c2b --- /dev/null +++ b/style.css @@ -0,0 +1,237 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;400&display=swap'); + +* { + box-sizing: border-box; +} + +body { + background-color: #231F20; + color: #fff; + font-family: 'Poppins', sans-serif; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: max-content; + overflow: auto; + margin: 0; + margin-top: 2%; +} + +.user-form { + width: 100%; + max-width: 700px; +} + +.user-form input { + width: 100%; + display: block; + background-color: #362F32; + border: none; + border-radius: 10px; + color: #fff; + padding: 1rem; + margin-bottom: 2rem; + font-family: inherit; + font-size: 1rem; + box-shadow: 0 5px 10px rgba(154, 160, 185, 0.05), + 0 15px 40px rgba(0, 0, 0, 0.1); +} + +.user-form input::placeholder { + color: #bbb; +} + +.user-form input:focus { + outline: none; +} + +.card { + max-width: 800px; + background-color: #362F32; + border-radius: 20px; + box-shadow: 0 5px 10px rgba(154, 160, 185, 0.05), + 0 15px 40px rgba(0, 0, 0, 0.1); + padding: 3rem; + margin: 0 1.5rem; + +} + +.cardInfo { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; +} + +.avatar { + border-radius: 50%; + border: 5px solid #2b2b2c; + height: 200px; + width: 200px; +} + +.user-info { + color: #eee; + margin-left: 2rem; +} + +.user-info h2 { + margin-top: 0; +} + +.user-info ul { + list-style-type: none; + display: flex; + justify-content: space-between; + padding: 0; + max-width: 400px; +} + +.user-info ul li { + display: flex; + align-items: center; +} + +.user-info ul li strong { + font-size: 0.9rem; + margin-left: 0.5rem; +} + +.repos { + display: flex; + flex-direction: column; +} + +.repoCard { + max-width: 800px; + background-color: #B45F5F; + border-radius: 20px; + box-shadow: 0 5px 10px rgba(154, 160, 185, 0.05), + 0 15px 40px rgba(0, 0, 0, 0.1); + padding: 1.5rem; + margin: 2% 1.5rem; + +} + +a { + text-decoration: none; + color: white; +} + +@media (max-width: 500px) { + .card { + flex-direction: column; + align-items: center; + } + + .user-form { + max-width: 400px; + } +} + + +.header { + width: 90%; + height: 100px; + margin: auto; + display: flex; + justify-content: space-between; + align-items: center; +} + +.items-controller, +.search { + flex-shrink: 0; + display: flex; + justify-content: center; + align-items: center; +} + +select { + padding: 2px; + margin: 0 10px; + outline: none; + border: none; + cursor: pointer; + background: transparent; + font-weight: bolder; + color: tomato; +} + +.search>input { + outline: none; + border: none; + padding: 8px; + margin: 0 0 0 20px; + background: white; +} + +.bottom-field { + width: 100%; + padding: 20px; + margin-top: 20px; +} + +.pagination { + display: flex; + justify-content: center; + align-items: center; +} + +.pagination li { + list-style: none; + padding: 2px; + margin: 10px; + flex-shrink: 0; + text-align: center; + border-radius: 5px; + border: 1px solid #999; + color: #999; +} + +.pagination li.active { + background: #32d6aa; + color: white; + border-color: #32d6aa; +} + +.pagination li a { + text-decoration: none; + color: inherit; + padding: 3px 8px; + display: block; + font-family: sans-serif; + font-size: 13px; +} + +.repoLang { + font-size: 14px; + background-color: #27275a; + color: white; + border-radius: 5px; + width: fit-content; + padding: 5px; +} + +.repoName a { + color: #f7b605; + font-size: 20px; + font-family: cursive; + font-weight: bold; +} + +.loading { + display: none; +} + +#main { + display: none; +} + +.website { + font-family: cursive; + color: rgb(241, 147, 5); + font-style: italic; + font-size: 50px; +}