Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion profiles/profiles.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@
"name": "YK aka CS Dojo",
"username": "ykdojo"
},
{
"image":"https://x.com/alexa45672/photo",
"name":"Manideep",
"username":"alexa45672"
},
{
"image": "https://pbs.twimg.com/profile_images/1641072404012343297/DTZ1DUF4_400x400.jpg",
"name": "Meadow",
Expand Down Expand Up @@ -308,7 +313,7 @@
"image": "https://avatars.githubusercontent.com/u/84437051?v=4",
"name": "Hello Faizan",
"username": "hellofaizaan"
}
},
{
"image": "https://avatars.githubusercontent.com/u/106791028?v=4",
"name": "Jack Archibald",
Expand Down
126 changes: 80 additions & 46 deletions scripts/app.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,99 @@
const allProfilesDiv = document.querySelector('.all-profiles-div');
const searchInput = document.querySelector('.search-input');
const btn = document.querySelector('.rounded')
const btnIcon = document.querySelector('.fa-solid')
const defaultImage = "https://res.cloudinary.com/djxkmpkuq/image/upload/v1680859085/R_kcyx7x.png"
const themeToggleBtn = document.querySelector('.rounded');
const themeToggleIcon = document.querySelector('.fa-solid');
const noProfileDiv = document.querySelector('.no-profile-div');
const defaultImage = "https://res.cloudinary.com/djxkmpkuq/image/upload/v1680859085/R_kcyx7x.png";

/**
* Redirects to the specified profile URL in a new tab.
* @param {string} url - The URL to open.
*/
const redirect = (url) => {
window.open(url, '_blank', 'noopener,noreferrer');
};

/**
* Fetches, sorts, and displays all profiles from the JSON file.
*/
const loadProfiles = async () => {
let data = await fetch('/profiles/profiles.json');
let profiles = await data.json();
let sortedProfiles = profiles.sort((a, b) => a.name.localeCompare(b.name));

sortedProfiles.forEach((profile) => {
let profileDiv = document.createElement('div');
let profileUrl = `https://twitter.com/${profile.username}`;
try {
const data = await fetch('/profiles/profiles.json');
const profiles = await data.json();
// Sort profiles alphabetically by name
const sortedProfiles = profiles.sort((a, b) => a.name.localeCompare(b.name));

profileDiv.innerHTML = `
<a href="${profileUrl}" target="_blank">
<img src="${profile.image}" onerror="this.onerror=null; this.src='${defaultImage}';"/>
</a>
<p class="profile-name" onclick="redirect(this)">${profile.name}</p>
<p class="profile-username" onclick="redirect(this)">@${profile.username}</p>
<a href="${profileUrl}" target="_blank"><button>Follow</button></a>
`;
profileDiv.classList.add('profile-div');
allProfilesDiv.append(profileDiv);

});
};
sortedProfiles.forEach((profile) => {
const profileDiv = document.createElement('div');
const profileUrl = `https://twitter.com/${profile.username}`;

searchInput.addEventListener('keyup', () => {
if (searchInput.value.length > 0) {
document.querySelectorAll('.profile-div').forEach((element) => {
element.style.display = 'none';
// We now call redirect() directly with the URL for cleaner code
profileDiv.innerHTML = `
<a href="${profileUrl}" target="_blank" rel="noopener noreferrer">
<img src="${profile.image}" alt="${profile.name}'s profile picture" onerror="this.onerror=null; this.src='${defaultImage}';"/>
</a>
<p class="profile-name" onclick="redirect('${profileUrl}')">${profile.name}</p>
<p class="profile-username" onclick="redirect('${profileUrl}')">@${profile.username}</p>
<a href="${profileUrl}" target="_blank" rel="noopener noreferrer"><button>Follow</button></a>
`;
profileDiv.classList.add('profile-div');
allProfilesDiv.append(profileDiv);
});
} catch (error) {
console.error("Failed to load profiles:", error);
noProfileDiv.innerText = "Could not load profiles. Please try again later.";
noProfileDiv.style.display = 'flex';
}
};

let profileNames = document.querySelectorAll('.profile-name');
/**
* Filters profiles based on search input (searches both name and username).
*/
const handleSearch = () => {
const searchTerm = searchInput.value.toLowerCase().trim();
const profileDivs = document.querySelectorAll('.profile-div');
let visibleProfiles = 0;
profileNames.forEach((profileElement) => {
if (
profileElement.innerText.toLowerCase().includes(searchInput.value.toLowerCase().trim())
) {
profileElement.parentElement.style.display = 'flex';

profileDivs.forEach((profile) => {
const name = profile.querySelector('.profile-name').innerText.toLowerCase();
const username = profile.querySelector('.profile-username').innerText.toLowerCase();

// Show profile if name or username includes the search term
if (name.includes(searchTerm) || username.includes(searchTerm)) {
profile.style.display = 'flex';
visibleProfiles++;
} else {
profile.style.display = 'none';
}
});

// if there is a profile to show, hide the no profile div
if (visibleProfiles !== 0) {
document.querySelector('.no-profile-div').style.display = 'none';
// Show/hide the 'No profile to show' message
noProfileDiv.style.display = visibleProfiles === 0 ? 'flex' : 'none';
};

/**
* Toggles the color theme between light and dark mode.
*/
const toggleTheme = () => {
document.body.classList.toggle('night-mode');

// Update the icon based on the new theme
if (document.body.classList.contains('night-mode')) {
themeToggleIcon.classList.remove('fa-sun');
themeToggleIcon.classList.add('fa-moon');
themeToggleBtn.classList.remove('background-sun');
themeToggleBtn.classList.add('background-moon');
} else {
document.querySelector('.no-profile-div').style.display = 'flex';
themeToggleIcon.classList.remove('fa-moon');
themeToggleIcon.classList.add('fa-sun');
themeToggleBtn.classList.remove('background-moon');
themeToggleBtn.classList.add('background-sun');
}
});

btn.addEventListener('click', e => {
btn.classList.toggle('background-moon')
btnIcon.classList.toggle('fa-moon')
document.body.classList.toggle('night-mode')
})
};

// load all profiles
loadProfiles();
// --- Event Listeners ---
searchInput.addEventListener('keyup', handleSearch);
themeToggleBtn.addEventListener('click', toggleTheme);

// --- Initial Load ---
loadProfiles();
Loading