-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from IndigoWizard/GitHub-profile-card
Added GitHub Profile Card web project
- Loading branch information
Showing
5 changed files
with
280 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# GitHub Profile Card | ||
This is a simple web project using html/css and vanilla javascript to learn how to use an API to search for any user profile. | ||
|
||
Here the GitHub API is used to search and retrieve a user's public info and display them such as; name, avatar, number of followers, bio, projects ..etc | ||
|
||
## Info | ||
This project uses the GitHub API, see more here: | ||
- [GitHub API - GitHub Developer](https://docs.github.com/en/rest) | ||
- [https://api.github.com/](https://api.github.com/) | ||
|
||
Unlike the original project by insaaFusion, I upgraded this one to not just display plain info but to also link to the user's profile, projects, followers/following and achievements. | ||
It only makes sense to be able to actually visit visit the user's profile to navigate on github website, this upgrade helps to do so. | ||
|
||
## Preview | ||
|
||
|Desktop|Mobile| | ||
|--|--| | ||
|![desktop](https://www.pixenli.com/image/ZAW_CSCX) |![mobile](https://www.pixenli.com/image/0GCdVuhU) | | ||
|
||
## Setup | ||
You can clone and open the project in a local server (e.g: liveserver) or you can host it somewhere like GitHub pages. | ||
|
||
## Contribution | ||
This project itself serves as learning material to know how to handle an API. Still, you may want to add more features as part of your web dev learning journey, try to: | ||
- Display user's achievements icons | ||
- Add feature to print the user card | ||
- Display a user's organizations on the card | ||
- Make GitHub Organizations searchable (only user profiles are supported as of now) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<link rel="stylesheet" href="style.css" /> | ||
<title>Github Profiles Card</title> | ||
</head> | ||
<body> | ||
<form class="user-form" id="form"> | ||
<input type="text" id="search" placeholder="Find a Github Profile"> | ||
</form> | ||
|
||
<main id="main"></main> | ||
|
||
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.0/axios.min.js" integrity="sha512-DZqqY3PiOvTP9HkjIWgjO6ouCbq+dxqWoJZ/Q+zPYNHmlnI2dQnbJ5bxAHpAMw+LXRm4D72EIRXzvcHQtE8/VQ==" crossorigin="anonymous"></script> | ||
<script src="script.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
const main = document.getElementById('main') | ||
const form = document.getElementById('form') | ||
const search = document.getElementById('search') | ||
const gh_url = 'https://api.github.com/users/' | ||
|
||
async function getUser(username) { | ||
try { | ||
const { data } = await axios(gh_url + username) | ||
createUserCard(data) | ||
getRepos(username) | ||
} catch(err) { | ||
if(err.response.status == 404) { | ||
createErrorCard('No profile found')} | ||
} | ||
} | ||
|
||
async function getRepos(username) { | ||
try { | ||
const { data } = await axios(gh_url + username + '/repos?sort=created') | ||
addReposToCard(data) | ||
} catch(err) { | ||
createErrorCard('Cant feth repos') | ||
} | ||
} | ||
|
||
function createUserCard(user) { | ||
const profileID = user.name || user.login || user.href | ||
const profileBio = user.bio ? `<p>${user.bio}</p>` : '' | ||
const cardHTML = ` | ||
<div class="card"> | ||
<div> | ||
<a href="${user.html_url}" target="_blank"> | ||
<img src="${user.avatar_url}" alt="${user.name}" class="avatar"> | ||
</a> | ||
</div> | ||
<div class="user-info"> | ||
<a href="${user.html_url}" target="_blank"> | ||
<h2>${profileID}</h2> | ||
</a> | ||
${profileBio} | ||
<ul> | ||
<li><a href="${user.html_url}?tab=followers" target="_blank">${user.followers} <strong>Followers</strong></a></li> | ||
<li><a href="${user.html_url}?tab=following" target="_blank">${user.following} <strong>Following</strong></a></li> | ||
<li><a href="${user.html_url}?tab=repositories" target="_blank">${user.public_repos} <strong>Repos</strong></a></li> | ||
<li><a href="${user.html_url}?tab=achievements" target="_blank"><strong>Achievements</strong></a></li> | ||
</ul> | ||
<div id="repos"></div> | ||
</div> | ||
</div> | ||
` | ||
main.innerHTML = cardHTML | ||
|
||
} | ||
|
||
function createErrorCard(msg) { | ||
const cardHTML = ` | ||
<div class="card"> | ||
<h1>${msg}</h1> | ||
</div> | ||
` | ||
|
||
main.innerHTML = cardHTML | ||
} | ||
|
||
function addReposToCard(repos) { | ||
const reposEl = document.getElementById('repos') | ||
|
||
repos | ||
.slice(0,6) | ||
.forEach(repo => { | ||
const repoEl = document.createElement('a') | ||
repoEl.classList.add('repo') | ||
repoEl.href = repo.html_url | ||
repoEl.target = '_blank' | ||
repoEl.innerText = repo.name | ||
|
||
reposEl.appendChild(repoEl) | ||
}) | ||
} | ||
|
||
form.addEventListener('submit', (e) => { | ||
e.preventDefault() | ||
|
||
const user = search.value | ||
|
||
if(user) { | ||
getUser(user) | ||
|
||
search.value = '' | ||
} | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;400&display=swap'); | ||
|
||
* { | ||
box-sizing: border-box; | ||
} | ||
|
||
body { | ||
background-image: url(https://github.blog/wp-content/uploads/2020/12/wallpaper_footer_4KUHD_16_9.png); | ||
background-position: bottom; | ||
background-size: cover; | ||
background-repeat: no-repeat; | ||
color: #fff; | ||
font-family: 'Poppins', sans-serif; | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
justify-content: center; | ||
height: 100vh; | ||
overflow: hidden; | ||
margin: 0; | ||
} | ||
|
||
.user-form { | ||
width: 100%; | ||
max-width: 800px; | ||
} | ||
|
||
.user-form input { | ||
width: 100%; | ||
display: block; | ||
background: linear-gradient(90deg, rgba(13, 9, 92, 0.65) 0%, rgba(31, 53, 93, 0.4) 48%, rgba(40, 20, 82, 0.65) 100%); | ||
background-color: rgba(38, 53, 98, 0.3); | ||
border: none; | ||
border-radius: 8px; | ||
color: #fff; | ||
padding: 1rem; | ||
margin-bottom: 2rem; | ||
font-family: inherit; | ||
font-size: 1rem; | ||
box-shadow: 5px 5px 15px rgba(38, 53, 98, 0.6); | ||
} | ||
|
||
.user-form input::placeholder { | ||
color: #bbb; | ||
} | ||
|
||
.user-form input:focus { | ||
outline: none; | ||
} | ||
|
||
.card { | ||
max-width: 800px; | ||
background: linear-gradient(90deg, rgba(13, 9, 92, 0.65) 0%, rgba(31, 53, 93, 0.4) 48%, rgba(40, 20, 82, 0.65) 100%); | ||
background-color: rgba(38, 53, 98, 0.3); | ||
border-radius: 8px; | ||
box-shadow: 5px 5px 15px rgba(38, 53, 98, 0.6); | ||
display: flex; | ||
padding: 1rem; | ||
margin: 0 1.5rem; | ||
} | ||
|
||
.avatar { | ||
border-radius: 50%; | ||
border: 5px solid rgba(22, 8, 63, 0.65); | ||
height: 150px; | ||
width: 150px; | ||
} | ||
|
||
.user-info { | ||
color: #eeee; | ||
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: 500px; | ||
} | ||
|
||
.user-info ul li { | ||
display: flex; | ||
align-items: end; | ||
} | ||
|
||
.user-info ul li strong { | ||
font-size: 0.9rem; | ||
margin-left: 0.5rem; | ||
} | ||
|
||
.repo { | ||
text-decoration: none; | ||
color: #fff; | ||
background-color: rgba(22, 8, 63, 0.65); | ||
font-size: 0.7rem; | ||
padding: 0.25rem 0.5rem; | ||
margin-right: 0.5rem; | ||
margin-bottom: 0.5rem; | ||
display: inline-block; | ||
border-radius: 4px; | ||
} | ||
|
||
a | ||
{ | ||
text-decoration:none; | ||
color: #fff; | ||
} | ||
|
||
a:visited { | ||
text-decoration: none; | ||
color: #fff; | ||
} | ||
|
||
@media (max-width: 500px) { | ||
.card { | ||
flex-direction: column; | ||
align-items: center; | ||
} | ||
|
||
.user-form { | ||
max-width: 350px; | ||
} | ||
|
||
.user-info{ | ||
margin: auto; | ||
margin-inline: 1rem; | ||
} | ||
|
||
.user-info h2 { | ||
text-align: center; | ||
} | ||
|
||
.user-info ul li strong{ | ||
font-size:0.7rem; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters