Skip to content

Commit

Permalink
fix ArslanYM#340: project filtering by language, project bookmarking,…
Browse files Browse the repository at this point in the history
… and nd resolved card Responsiveness
  • Loading branch information
amanrajrana committed Sep 25, 2023
1 parent 3e6837e commit bf80339
Show file tree
Hide file tree
Showing 3 changed files with 229 additions and 3 deletions.
86 changes: 86 additions & 0 deletions web/src/pages/Issues/LanguageDropDown.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import PropTypes from 'prop-types';
import { useEffect, useState } from 'react';
import { BsCheck2 } from 'react-icons/bs';
import { MdArrowDropDown } from 'react-icons/md';

const LanguageDropDown = ({
languages,
selectedLanguage,
setSelectedLanguage,
}) => {
const [isDropDownVisible, setIsDropDownVisible] = useState(false); // To toggle dropdown

// Close dropdown when clicked outside
document.addEventListener('click', (e) => {
if (!isDropDownVisible) return; // If dropdown is not visible, do nothing
if (e.target.classList.contains('dropdown-container')) return; // If clicked on dropdown, do nothing
setIsDropDownVisible(false); // Else close the dropdown
});

// Sort languages alphabetically
useEffect(() => {
languages.sort();
}, [languages]);

// When a language is clicked
const onLanguageClick = (language) => {
setIsDropDownVisible(false);

// If the same language is clicked again, set selected language to 'All'
if (selectedLanguage === language) {
setSelectedLanguage('All');
return;
}

// Else set the selected language to the clicked language
setSelectedLanguage(language);
};

return (
<div className="max-w-full w-max border-2 border-yellow-400 relative text-white py-1 px-2 rounded-lg">
<div
className="dropdown-container flex flex-wrap justify-center items-center cursor-pointer"
onClick={() => setIsDropDownVisible(!isDropDownVisible)}
>
<span className="dropdown-container opacity-60 text-sm block mr-2">
Language/Topic:{' '}
</span>
<span className="dropdown-container flex">
{selectedLanguage}
<MdArrowDropDown className="dropdown-container text-2xl" />
</span>
</div>
{isDropDownVisible && (
<div
className={`max-h-96 overflow-x-auto absolute top-10 flex w-64 flex-col ju bg-gray-800 border border-gray-700 shadow-xl rounded-md z-10`}
>
<div className="px-4 py-2 border-b border-gray-700 opacity-60 text-sm">
Filter By Language / Topic
</div>
{languages.map((language, key) => {
return (
<div
key={key}
className="flex justify-between items-center border-b border-gray-700 px-4 py-2 cursor-pointer hover:bg-gray-600 duration-500 gap-x-1"
onClick={() => onLanguageClick(language)}
>
<span className="w-4 mt-1">
{selectedLanguage === language && <BsCheck2 />}
</span>
<span className="flex-1">{language}</span>
</div>
);
})}
</div>
)}
</div>
);
};

export default LanguageDropDown;

LanguageDropDown.propTypes = {
languages: PropTypes.array.isRequired,
selectedLanguage: PropTypes.string.isRequired,
setSelectedLanguage: PropTypes.func.isRequired,
};
55 changes: 54 additions & 1 deletion web/src/pages/Issues/ListOfOrgs/ProjectCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
import Placeholder from "../../../assets/img-placeholder.jpg"
import axios from 'axios';
import { useState } from 'react';
import { BsBookmark, BsFillBookmarkCheckFill } from 'react-icons/bs';
import { useNavigate } from 'react-router-dom';

const ProjectCard = ({
Expand All @@ -10,10 +11,15 @@ const ProjectCard = ({
name,
description,
tags: propsTags,
bookMarkProjects,
getBookMarkProjects,
}) => {


const [issues, setIssues] = useState(null);
const [isBookmarked, setIsBookmarked] = useState(
bookMarkProjects.includes(projectLink)
);

async function getIssues() {
const getLastTwoHeaders = (link) => link.split('/').slice(-2);
Expand All @@ -38,8 +44,53 @@ const ProjectCard = ({
</span>
));

const handleClick = () => {
setIsBookmarked(!isBookmarked);

// If the project is already bookmarked, remove it from the list
if (isBookmarked) {
let bookMarkProjects = JSON.parse(
localStorage.getItem('bookMarkProjects')
);

bookMarkProjects = bookMarkProjects.filter(
(project) => project !== projectLink
);
localStorage.setItem(
'bookMarkProjects',
JSON.stringify(bookMarkProjects)
);
getBookMarkProjects(); // Update the bookmark list
return;
}

// If the project is not bookmarked, add it to the list
if (!isBookmarked) {
let bookMarkProjects = JSON.parse(
localStorage.getItem('bookMarkProjects')
);
if (bookMarkProjects === null) {
bookMarkProjects = [projectLink];
} else {
bookMarkProjects.push(projectLink);
}
localStorage.setItem(
'bookMarkProjects',
JSON.stringify(bookMarkProjects)
);
getBookMarkProjects(); // Update the bookmark list
return;
}
};

return (
<div className="flex self-auto flex-col h-full w-96 border rounded-lg shadow bg-gray-800 border-gray-700">
<div className="flex self-auto flex-col h-full w-96 max-w-full border rounded-lg shadow bg-gray-800 border-gray-700 relative">
<div
className="absolute text-2xl right-2 top-2 text-yellow-400 cursor-pointer"
onClick={handleClick}
>
{isBookmarked ? <BsFillBookmarkCheckFill /> : <BsBookmark />}
</div>
<a href={projectLink}>
<img
rel="preload"
Expand Down Expand Up @@ -99,4 +150,6 @@ ProjectCard.propTypes = {
name: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
tags: PropTypes.arrayOf(PropTypes.string),
bookMarkProjects: PropTypes.arrayOf(PropTypes.string),
getBookMarkProjects: PropTypes.func,
};
91 changes: 89 additions & 2 deletions web/src/pages/Issues/ProjectList.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,98 @@
// eslint-disable-next-line no-unused-vars
import React from "react";
import React, { useEffect, useState } from 'react';
import projectList from "./ListOfOrgs/listOfOrgs";
import ProjectCard from "./ListOfOrgs/ProjectCard";
import { ScaleLoader } from 'react-spinners';
import { BsBookmark, BsFillBookmarkCheckFill } from 'react-icons/bs';
import LanguageDropDown from './LanguageDropDown';

const ProjectList = () => {
const [selectedLanguage, setSelectedLanguage] = useState('All');
const [languages, setLanguages] = useState([]);
const [bookMarkProjects, setBookMarkProjects] = useState();
const [showBookMark, setShowBookMark] = useState(false);

// Filter projects by language or bookmark
function filterProject(project) {
// If the user wants to see all projects
if (selectedLanguage === 'All' && !showBookMark) {
return true;
}

// If the user wants to see only bookmarked projects
if (selectedLanguage === 'All' && showBookMark) {
return bookMarkProjects.includes(project.projectLink);
}

// If the user wants to see only bookmark projects of a specific language
if (showBookMark) {
return (
project.tags.includes(selectedLanguage) &&
bookMarkProjects.includes(project.projectLink)
);
}

// If the user wants to see only projects of a specific language
return project.tags.includes(selectedLanguage);
}

// Get all the languages/tags from the project list
const getLanguages = () => {
projectList.map((project) => {
project.tags.map((tag) => {
if (!languages.includes(tag)) {
languages.push(tag);
}
});
});
setLanguages(languages);
};

const getBookMarkProjects = () => {
const bookMarkProject = localStorage.getItem('bookMarkProjects');
if (bookMarkProject) {
const array = JSON.parse(bookMarkProject);
setBookMarkProjects(array);
} else {
setBookMarkProjects([]);
}
};

useEffect(() => {
getLanguages();
getBookMarkProjects();
}, []);

return (
<div className="mx-auto min-h-screen max-w-screen-2xl p-4 md:p-8 2xl:p-10">
<div className="w-full my-4 p-4 flex items-center flex-wrap gap-4">
<LanguageDropDown
languages={languages}
selectedLanguage={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
/>
<div
onClick={() => setShowBookMark(!showBookMark)}
className={`${showBookMark ? 'border-yellow-400' : 'border-gray-600'}
text-white flex items-center gap-2 border-2 px-2 py-1 rounded-md cursor-pointer hover:border-yellow-400 duration-300`}
>
{showBookMark ? (
<BsFillBookmarkCheckFill className="text-yellow-400" />
) : (
<BsBookmark />
)}
<span className="opacity-60 text-sm">Bookmark: </span>
<span>{bookMarkProjects?.length}</span>
</div>
</div>
<div className="flex w-full items-center justify-center">
{<ScaleLoader loading={!bookMarkProjects} color="white" />}
</div>
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 md:gap-4 xl:grid-cols-3 2xl:gap-7.5 bg-gradient-to-r from-gray-700 via-gray-900 to-black bg-animate place-items-center">
{projectList.map((project, key) => {
{bookMarkProjects && projectList.map((project, key) => {
if (!filterProject(project)) {
return null;
}
return (
<ProjectCard
key={key}
Expand All @@ -16,6 +101,8 @@ const ProjectList = () => {
projectLink={project.projectLink}
description={project.description}
tags={project.tags}
bookMarkProjects={bookMarkProjects}
getBookMarkProjects={getBookMarkProjects}
/>
);
})}
Expand Down

0 comments on commit bf80339

Please sign in to comment.