Skip to content

Commit

Permalink
fallback image & search fuction (#259)
Browse files Browse the repository at this point in the history
- Added a search function
- Added GitHub as fallback if image is not provided and if that is not found it will use the defaultimage variable
  • Loading branch information
YouFoundAlpha authored Sep 10, 2024
1 parent 528f66c commit 9d59816
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 45 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ Join our Discord server for any kind of help. <br>
Don't forget to leave a star ⭐

<a href="#"> <img src="https://oyepriyansh.pages.dev/i/895dfb4d98fgcf5e.gif" alt="star repo gif"> </a>
## Star History

[![Star History Chart](https://api.star-history.com/svg?repos=oyepriyansh/DevProfiles&type=Date)](https://star-history.com/#oyepriyansh/DevProfiles&Date)
## 💳 Author
> <a href="https://oyepriyansh.github.io">Priyansh Prajapat (@oyepriyansh)</a>
139 changes: 94 additions & 45 deletions scripts/app.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,81 @@
const container = document.querySelector('.container');
const defaultImage = "https://oyepriyansh.pages.dev/i/5nf5fd.png";
const searchInput = document.getElementById('searchInput'); // Assuming there's an input field for searching
const noProfileMessage = document.querySelector('.no-profile'); // Message element
const fabButton = document.getElementById("backToTopBtn");

// Load profiles from JSON file
const loadProfiles = async () => {
// Fetching data from JSON file
let data = await fetch('/data.json');
let profiles = await data.json();

profiles = shuffleArray(profiles);
try {
const response = await fetch('/data.json');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const profiles = await response.json();
displayProfiles(shuffleArray(profiles));
} catch (error) {
console.error('Error fetching profiles:', error);
noProfileMessage.textContent = 'Failed to load profiles. Please try again later.';
noProfileMessage.style.display = 'block'; // Show error message
}
};


profiles.forEach((profile) => {
let profileDiv = document.createElement('div');
// Display profiles on the page
const displayProfiles = async (profiles) => {
container.innerHTML = ''; // Clear existing profiles
for (const profile of profiles) {
const profileDiv = document.createElement('div');
profileDiv.classList.add('profile');

//skills
let skills = profile.skills.map(skill => `<span class="skill">${skill}</span>`).join('');
// Determine the image source
let imageSrc = profile.image || await fetchGitHubImage(profile.github);

// social links
let social = '';
if (profile.github) {
social += `<a href="${profile.github}" target="_blank"><i class="fa-brands fa-github"></i></a>`;
}
if (profile.twitter) {
social += `<a href="${profile.twitter}" target="_blank"><i class="fa-brands fa-x-twitter"></i></a>`;
}
if (profile.linkedin) {
social += `<a href="${profile.linkedin}" target="_blank"><i class="fa-brands fa-linkedin-in"></i></a>`;
}
// Skills
const skills = profile.skills.map(skill => `<span class="skill">${skill}</span>`).join('');

// Social links
const social = `
${profile.github ? `<a href="${profile.github}" target="_blank" aria-label="GitHub"><i class="fa-brands fa-github"></i></a>` : ''}
${profile.twitter ? `<a href="${profile.twitter}" target="_blank" aria-label="Twitter"><i class="fa-brands fa-x-twitter"></i></a>` : ''}
${profile.linkedin ? `<a href="${profile.linkedin}" target="_blank" aria-label="LinkedIn"><i class="fa-brands fa-linkedin-in"></i></a>` : ''}
`;

// adding profile HTML content
// Adding profile HTML content
profileDiv.innerHTML = `
<div class="pfp">
<img src="${profile.image}" alt="User Image" onerror="this.onerror=null; this.src='${defaultImage}';">
<img src="${imageSrc}" alt="${profile.name}'s Profile Picture" onerror="this.onerror=null; this.src='${defaultImage}';" />
</div>
<h2 class="name">${profile.name}</h2>
<div class="skills">${skills}</div>
<div class="social">${social}</div>
`;

container.append(profileDiv);
});
}
};

// Function to fetch GitHub image
const fetchGitHubImage = async (githubUrl) => {
if (!githubUrl) return defaultImage; // Return default if no GitHub URL

// Extract username from GitHub URL
const username = githubUrl.split('/').pop();
const apiUrl = `https://api.github.com/users/${username}`;

try {
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error('GitHub user not found');
}
const userData = await response.json();
return userData.avatar_url || defaultImage; // Return avatar URL or default image
} catch (error) {
console.error('Error fetching GitHub image:', error);
return defaultImage; // Fallback to default image on error
}
};

// Function to shuffle
// Shuffle array function
const shuffleArray = (array) => {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
Expand All @@ -51,15 +84,29 @@ const shuffleArray = (array) => {
return array;
};

loadProfiles();

// Search function
// Search function with debouncing and URL update
let debounceTimer;
searchInput.addEventListener('keyup', () => {
clearTimeout(debounceTimer);
const searchTerm = searchInput.value.trim().toLowerCase();
const profiles = document.querySelectorAll('.profile');
let visibleProfiles = 0;
updateURL(searchTerm); // Update the URL with the search term

debounceTimer = setTimeout(() => {
filterProfiles(searchTerm);
}, 300); // 300ms debounce time
});

// Function to update the URL
const updateURL = (searchTerm) => {
const url = new URL(window.location);
url.searchParams.set('search', searchTerm);
window.history.pushState({}, '', url);
};

// Filter profiles based on search term
const filterProfiles = (searchTerm) => {
const profiles = document.querySelectorAll('.profile');
let visibleProfiles = 0;

profiles.forEach((profile) => {
const profileName = profile.querySelector('.name').innerText.trim().toLowerCase();
Expand All @@ -73,29 +120,31 @@ searchInput.addEventListener('keyup', () => {
}
});

// no profiles
const noProfileMessage = document.querySelector('.no-profile');
if (visibleProfiles > 0) {
noProfileMessage.style.display = 'none';
// Show or hide the no profiles message based on search results
if (visibleProfiles === 0 && searchTerm !== '') {
noProfileMessage.style.display = 'block'; // Show message if no profiles found
} else {
noProfileMessage.style.display = 'block';
noProfileMessage.style.display = 'none'; // Hide message if profiles are found
}
});

// Scroll to top button
var fabButton = document.getElementById("backToTopBtn");
};

// Scroll to top button functionality
window.onscroll = function () {
if (window.scrollY > 20) {
fabButton.style.display = "block";
} else {
fabButton.style.display = "none";
}
fabButton.style.display = window.scrollY > 20 ? "block" : "none";
};

fabButton.addEventListener("click", function () {
window.scrollTo({ top: 0, behavior: "smooth" });
});

// footer year
// Footer year display
document.getElementById("currentYear").textContent = new Date().getFullYear();

// Load profiles when the page is ready
loadProfiles();

// Load search term from URL on page load
const urlParams = new URLSearchParams(window.location.search);
const searchTerm = urlParams.get('search') || '';
searchInput.value = searchTerm; // Set the input value from the URL
filterProfiles(searchTerm); // Filter profiles based on the URL search term

0 comments on commit 9d59816

Please sign in to comment.