Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
Binary file added src/assets/down.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/up-arrow.png
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be better/easier to just use a library like react-icons or fontawesome.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or even just use something stupid like ^ and v lol, or check if the font supports emojis

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Emojis look like garbage on Windows. And icons can be used for other things later.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in that case react-icons is already a dependency, so should be an easy change @Waqibsk

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
61 changes: 61 additions & 0 deletions src/components/SortDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React, { useState } from "react";
import "../styles/components/SortDropdown.css";
import downArrow from "../assets/down.png";
import upArrow from "../assets/up-arrow.png";
import { SortDropdownProps } from "../utils/types";
const SortDropdown: React.FC<SortDropdownProps> = ({
setSortField,
setSortType,
sortField,
sortType,
}) => {
const [showMenu, setShowMenu] = useState(false);

const toggleSort = () => {
setSortType(sortType === "desc" ? "asc" : "desc");
}
const toggleDropdown = () => {
setShowMenu(!showMenu);
};
const handleSortField = (field: string) => {
setSortField(field);
};

return (
<div className={`dropdown ${showMenu ? "show" : ""}`}>
<div className="sort-button">
<button disabled={window.innerWidth >= 760} onClick={toggleDropdown}>
Sort by:{" "}{sortField.charAt(0).toUpperCase()+sortField.slice(1)}
</button>
<div className="sort-Arrow-container" onClick={(e) => {
e.stopPropagation();
toggleSort();
}}>
<img src={sortType === "desc" ? downArrow : upArrow} className="sort-Arrow" alt="▼" />

</div>

</div>
<div className={`dropdown-content ${showMenu ? "show" : ""}`}>
<div className={`dropdown-item ${"name" === sortField ? "selected" : ""}`} onClick={() => handleSortField("name")}>
{" "}

Name
</div>
<div className={`dropdown-item ${"forks" === sortField ? "selected" : ""}`} onClick={() => handleSortField("forks")}>
<span

></span>
Forks
</div>
<div className={`dropdown-item ${"stars" === sortField ? "selected" : ""}`} onClick={() => handleSortField("stars")}>

Stars
</div>

</div>
</div>
);
};

export default SortDropdown;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add another field? current behaviour is to fetch repo data by last updated, which means we get to see currently active repos on the top

in get_repos.py

    # notice sort:updated
    response = requests.get(url, params={'sort':'updated', 'per_page': 100, 'type': 'public'}) 

if that could be the default that would be great, feel free to add other fields if you like

also while your dropdown is nice and simple, could you look into a more modular filter system like as below?

image

let me know if you feel like any other fields are necessary. If you think these are enough then a dropdown is sufficient

64 changes: 54 additions & 10 deletions src/pages/Projects.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,51 @@
import { useState } from "react";
import { useEffect, useState } from "react";
import CardGrid from "../sections/CardGrid";
import "../styles/pages/Projects.css";
import { REPO_DATA_TYPE } from "../utils/types";
import RepoData from '../data/repo_data.json';

import SortDropdown from "../components/SortDropdown";
const Projects = () => {
const repoList: REPO_DATA_TYPE[] = RepoData as REPO_DATA_TYPE[]

const [sortField, setSortField] = useState("name");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

set the default field as the updated one as mentioned above

const [sortType,setSortType]=useState("asc")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and for forks, stars and updated it would be better to set the default order as descending

const languages = [...new Set(repoList.map(repo => repo.language))];
const [selectedLanguage, setSelectedLanguage] = useState<string[]>([]);
const [FilteredRepos, setFilteredRepos] = useState<REPO_DATA_TYPE[]>(repoList);


//sorting based on STARS ,FORKS , NAME
// and Also filtered by Language
useEffect ( () => {
let result = repoList.filter((repo) =>
selectedLanguage.length === 0 || selectedLanguage.includes(repo.language)
);

if (sortField === "name") {

result.sort((a, b) => {
const cmp = a.name.toLowerCase().localeCompare(b.name.toLowerCase());
return sortType === "asc" ? cmp : -cmp;
});

}
else if (sortField === "stars") {
result.sort((a, b) => {
const cmp = a.stars-b.stars;
return sortType === "asc" ? cmp : -cmp;
});
}
else if (sortField === "forks") {
result.sort((a, b) => {
const cmp = a.forks-b.forks;
return sortType === "asc" ? cmp : -cmp;
});

}
setFilteredRepos(result)

},[selectedLanguage,sortField,sortType])




const toggleLanguage = (lang: string) => {
Expand All @@ -22,11 +59,7 @@ const Projects = () => {
});
};

const filteredRepos = repoList.filter(repo => {
if (selectedLanguage.length === 0)
return true;
return selectedLanguage.includes(repo.language);
})


return (
<div className="page-container">
Expand All @@ -36,7 +69,7 @@ const Projects = () => {
Explore our repositories for projects that may help you, feel free to contribute to which ever ones suit you!
</p>
</section>

<div className="filter-container">
<div className="language-filter">
{languages.map(lang => (
<button
Expand All @@ -47,8 +80,19 @@ const Projects = () => {
{lang}
</button>
))}

</div>

<SortDropdown
setSortField={setSortField}
setSortType={setSortType}
sortField={sortField}
sortType={sortType}
/>


</div>
<CardGrid repos={filteredRepos} displayMode="all" />
<CardGrid repos={FilteredRepos} displayMode="all" />
</div>
)
}
Expand Down
113 changes: 113 additions & 0 deletions src/styles/components/SortDropdown.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
.dropdown {
position: relative;
display: inline-block;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;

padding: 10px;
}

.selected {
background-color: #393737;
border-radius: 0 0 5px 5px;
}
.sort-button {
background-color: #2f2f2f;
color: #fcfcfc;
border: none;
padding: 8px 15px;
font-size: 14px;
border-radius: 5px;

cursor: pointer;
width: 200px;
transition: background 300ms, color 300ms, scale 300ms;

display: flex;
justify-content: space-between;

}
.sort-button button{
color: #fcfcfc;
background-color: #2f2f2f;
width: 100%;
text-align: left;
border: none;
}
.sort-Arrow-container{
display: flex;
}

.sort-Arrow {
width: 15px;

filter: brightness(0) invert(1);
color: white;
}

.dropdown-content {
opacity: 0;
transition: opacity 0.3s ease, transform 0.3s ease;
position: absolute;
border-radius: 0 0 5px 5px;
background-color: #2f2f2f;
color: #fcfcfc;
width: 230px;

z-index: 1;
}

.dropdown-content div {
padding: 10px 20px;
cursor: pointer;
display: flex;

align-items: center;
}

.dropdown-item {
text-align: center;
font-size: small;
transition: background 300ms, color 300ms, scale 300ms;
}
.dropdown-item:hover {
background-color: #393737;
border-radius: 0 0 5px 5px;
}


/*
for large screens toggle on hover */
.dropdown:hover .dropdown-content {
opacity: 1;
transform: translateY(0);
}

.dropdown:hover .sort-button{
border-radius: 5px 5px 0 0;
}

/*
for small screens toggling on click */
.dropdown-content.show {
opacity: 1;
transform: translateY(0);

}
.dropdown.show .sort-button{
border-radius: 5px 5px 0 0 ;

}







@media (max-width: 768px) {
.dropdown:hover .dropdown-content {
display: none;
}

}
12 changes: 11 additions & 1 deletion src/styles/pages/Projects.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
overflow-x: auto;
white-space: nowrap;
}

.filter-container{

display: flex;
justify-content: space-between;
}
.filter-button {
border: none;
padding: 8px 15px;
Expand All @@ -30,3 +34,9 @@
color: #f3f3f3;
font-weight: bold;
}

@media (max-width:1024px){
.filter-container{
flex-direction: column;
}
}
4 changes: 3 additions & 1 deletion src/styles/sections/CardGrid.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
display: grid;
gap: 1rem;
padding: 1rem;

justify-content: center;
}

/* Default layout for all cards */
.gh-card-grid.all {
grid-template-columns: repeat(3, 1fr);

grid-template-columns: repeat(2, 1fr);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you make this more responsive? 3, 1fr on large screens, 2 on medium etc

}

/* Prominent layout for fewer cards */
Expand Down
7 changes: 7 additions & 0 deletions src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,10 @@ export interface FEATURED_REPO {
usage: string;
repo: REPO_DATA_TYPE;
}

export interface SortDropdownProps {
setSortField: (field: string) => void;
setSortType: (type: "asc" | "desc") => void;
sortField: string;
sortType: string;
}