Skip to content

Commit

Permalink
feat: add dropdown, search box and register button
Browse files Browse the repository at this point in the history
  • Loading branch information
0xExp-po committed Sep 13, 2024
1 parent a719f09 commit 08a32f3
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 5 deletions.
23 changes: 23 additions & 0 deletions dapp/public/icons/search.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
75 changes: 70 additions & 5 deletions dapp/src/components/ProjectList.jsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,91 @@
import React, { useState, useEffect } from 'react';
import ProjectCard from './ProjectCard.jsx';
import { getDemoConfigData } from '../constants/demoConfigData.js';
import Dropdown from './utils/DropDown.jsx';
import { refreshLocalStorage, setProjectId } from '../service/StateService';

const ProjectList = () => {
const [projects, setProjects] = useState([]);
const [filteredProjects, setFilteredProjects] = useState([]);
const [searchTerm, setSearchTerm] = useState('');
const [category, setCategory] = useState('all');

const options = [
{ label: 'All', value: 'all' },
{ label: 'Web', value: 'web' },
{ label: 'Mobile', value: 'mobile' },
{ label: 'Desktop', value: 'desktop' },
];

useEffect(() => {
const fetchProjects = async () => {
// Simulating an async operation
await new Promise(resolve => setTimeout(resolve, 100));
const data = getDemoConfigData();
setProjects(data);
setFilteredProjects(data);
};

fetchProjects();
}, []);

useEffect(() => {
const filtered = projects.filter(project =>
project?.projectName.toLowerCase().includes(searchTerm.toLowerCase()) &&
(category === 'all')
);
setFilteredProjects(filtered);
}, [searchTerm, category, projects]);

const handleSearch = () => {
console.log('Search function activated');
};

const handleRegister = () => {
refreshLocalStorage();
setProjectId(searchTerm.toLowerCase());
window.location.href = '/register';
}

return (
<div className="project-list py-4 grid gap-4 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 justify-items-center">
{projects.map((project, index) => (
<ProjectCard key={index} config={project} />
))}
<div className="project-list-container">
<div className="filters flex items-center gap-2 sm:gap-4 mb-4">
<Dropdown options={options} onSelect={(e) => setCategory(e.target.value)} />
<div className="search-container relative">
<input
type="text"
placeholder="Search projects..."
className="w-36 sm:w-48 border rounded-2xl pl-3 sm:pl-4 pr-6 sm:pr-8 py-1"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
<div
className="absolute right-1 sm:right-2 top-1/2 transform -translate-y-1/2 rounded-full hover:bg-zinc-300 cursor-pointer flex justify-center items-center p-0.5 pl-[3px]"
onClick={handleSearch}
>
<img src='/icons/search.svg' width={20} height={20} className='icon-search'/>
</div>
</div>
{filteredProjects.length === 0 && (
<button
className="register-btn mr-2 px-2 sm:px-3 py-1 bg-black text-white text-base sm:text-lg rounded-lg"
onClick={handleRegister}
>
Register
</button>
)}
</div>

{filteredProjects.length > 0 ? (
<div className="project-list py-4 grid gap-4 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 justify-items-center">
{filteredProjects.map((project, index) => (
<ProjectCard key={index} config={project} />
))}
</div>
) : (
<div className="no-projects h-40 flex justify-center items-center text-center py-4">
<p className="px-3 py-1 text-base sm:text-lg font-semibold border-2 border-zinc-700 rounded-lg">No projects found</p>
</div>
)}
</div>
);
};
Expand Down
57 changes: 57 additions & 0 deletions dapp/src/components/utils/DropDown.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React, { useState } from 'react';

const Dropdown = ({ options, onSelect }) => {
const [isOpen, setIsOpen] = useState(false);
const [selectedOption, setSelectedOption] = useState(null);

const toggleDropdown = () => setIsOpen(!isOpen);

const handleOptionClick = (option) => {
setSelectedOption(option);
setIsOpen(false);
onSelect(option);
};

return (
<div className="relative inline-block w-24 sm:w-32">
<button
onClick={toggleDropdown}
className="w-full bg-lime text-sm sm:text-base text-black py-2 px-1 sm:px-3 rounded-lg flex justify-between items-center"
>
{selectedOption ? selectedOption.label : 'All'}
<svg
className={`w-4 h-4 ml-1 sm:ml-2 transition-transform duration-200 ${
isOpen ? 'rotate-180' : ''
}`}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M19 9l-7 7-7-7"
/>
</svg>
</button>

{isOpen && (
<ul className="absolute left-0 top-full w-full mt-2 bg-white border border-zinc-500 rounded-lg overflow-hidden shadow-lg z-10">
{options.map((option, index) => (
<li
key={index}
className="px-4 py-2 hover:bg-zinc-100 cursor-pointer"
onClick={() => handleOptionClick(option)}
>
{option.label}
</li>
))}
</ul>
)}
</div>
);
};

export default Dropdown;

0 comments on commit 08a32f3

Please sign in to comment.