Implement filtering repositories by name and account (#18)

* Filter repositories according to title

* Add style to project repo card

* Filter repositories through title and user

* Update project repository card for user

---------

Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
Nabarun Gogoi 2023-12-21 11:59:17 +05:30 committed by GitHub
parent 6590b8f6f5
commit 5c762f3583
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 114 additions and 42 deletions

View File

@ -1,26 +1,32 @@
[ [
{ {
"title": "Project-101", "title": "project-101",
"updatedTime": "2023-05-15T08:30:00" "updatedAt": "2023-12-21T08:30:00",
"user": "bob"
}, },
{ {
"title": "Project-102", "title": "project-102",
"updatedTime": "2023-05-15T08:30:00" "updatedAt": "2023-12-21T08:30:00",
"user": "alice"
}, },
{ {
"title": "Project-103", "title": "project-103",
"updatedTime": "2023-12-11T04:20:00" "updatedAt": "2023-12-21T04:20:00",
"user": "charlie"
}, },
{ {
"title": "Project-104", "title": "project-104",
"updatedTime": "2023-12-11T04:27:00" "updatedAt": "2023-12-21T04:27:00",
"user": "alice"
}, },
{ {
"title": "Project-105", "title": "project-105",
"updatedTime": "2023-12-11T04:41:00" "updatedAt": "2023-12-21T04:41:00",
"user": "ivan"
}, },
{ {
"title": "Project-106", "title": "project-106",
"updatedTime": "2023-12-11T04:32:00" "updatedAt": "2023-12-21T04:32:00",
"user": "david"
} }
] ]

View File

@ -1,10 +1,13 @@
import React from 'react'; import React from 'react';
import { IconButton } from '@material-tailwind/react';
import { relativeTime } from '../../../utils/time'; import { relativeTime } from '../../../utils/time';
interface RepositoryDetails { interface RepositoryDetails {
title: string; title: string;
updatedTime: string; updatedAt: string;
user: string;
} }
interface ProjectRepoCardProps { interface ProjectRepoCardProps {
@ -13,11 +16,16 @@ interface ProjectRepoCardProps {
const ProjectRepoCard: React.FC<ProjectRepoCardProps> = ({ repository }) => { const ProjectRepoCard: React.FC<ProjectRepoCardProps> = ({ repository }) => {
return ( return (
<div className="flex text-gray-500 text-xs bg-gray-100 m-2"> <div className="group flex items-center gap-4 text-gray-500 text-xs hover:bg-gray-100 m-2">
<div>^</div> <div>^</div>
<div className="grow"> <div className="grow">
<p>{repository.title}</p> <p className="text-black">
<p>{relativeTime(repository.updatedTime)}</p> {repository.user}/{repository.title}
</p>
<p>{relativeTime(repository.updatedAt)}</p>
</div>
<div className="hidden group-hover:block">
<IconButton size="sm">{'>'}</IconButton>
</div> </div>
</div> </div>
); );

View File

@ -1,34 +1,87 @@
import React from 'react'; import React, { useCallback, useMemo, useState } from 'react';
import { Button, Typography, Option, Select } from '@material-tailwind/react';
import SearchBar from '../../SearchBar'; import SearchBar from '../../SearchBar';
import ProjectRepoCard from './ProjectRepoCard'; import ProjectRepoCard from './ProjectRepoCard';
import repositoryDetails from '../../../assets/repositories.json'; import repositoryDetails from '../../../assets/repositories.json';
import Dropdown from '../../Dropdown';
const ACCOUNT_OPTIONS = [ const DEFAULT_SEARCHED_REPO = '';
{ value: 'alice', label: 'Alice' }, const DEFAULT_SELECTED_USER = 'All accounts';
{ value: 'bob', label: 'Bob' },
{ value: 'charlie', label: 'Charlie' },
];
const RepositoryList = () => { const RepositoryList = () => {
const [searchedRepo, setSearchedRepo] = useState(DEFAULT_SEARCHED_REPO);
const [selectedUser, setSelectedUser] = useState(DEFAULT_SELECTED_USER);
const filteredRepos = useMemo(() => {
return repositoryDetails.filter((repo) => {
const titleMatch =
!searchedRepo ||
repo.title.toLowerCase().includes(searchedRepo.toLowerCase());
const userMatch =
selectedUser === DEFAULT_SELECTED_USER || selectedUser === repo.user;
return titleMatch && userMatch;
});
}, [searchedRepo, selectedUser]);
const handleResetFilters = useCallback(() => {
setSearchedRepo(DEFAULT_SEARCHED_REPO);
setSelectedUser(DEFAULT_SELECTED_USER);
}, []);
const users = useMemo(() => {
return [
DEFAULT_SELECTED_USER,
...Array.from(new Set(repositoryDetails.map((repo) => repo.user))),
];
}, []);
return ( return (
<div className="p-4"> <div className="p-4">
<div className="flex"> <div className="flex gap-2">
<div className="basis-1/3"> <div className="basis-1/3">
<Dropdown <Select
placeholder="All accounts" value={selectedUser}
options={ACCOUNT_OPTIONS} onChange={(value) => setSelectedUser(value!)}
onChange={() => {}} >
/> {users.map((user, key) => (
<Option
className={user === selectedUser ? 'hidden' : ''}
key={key}
value={user}
>
^ {user}
</Option>
))}
</Select>
</div> </div>
<div className="basis-2/3"> <div className="basis-2/3">
<SearchBar onChange={() => {}} placeholder="Search for repository" /> <SearchBar
value={searchedRepo}
onChange={(event) => setSearchedRepo(event.target.value)}
placeholder="Search for repository"
/>
</div> </div>
</div> </div>
{repositoryDetails.map((repo, key) => { {Boolean(filteredRepos.length) ? (
filteredRepos.map((repo, key) => {
return <ProjectRepoCard repository={repo} key={key} />; return <ProjectRepoCard repository={repo} key={key} />;
})} })
) : (
<div className="mt-4 p-6 flex items-center justify-center">
<div className="text-center">
<Typography>No repository found</Typography>
<Button
className="rounded-full mt-5"
color="white"
size="sm"
onClick={handleResetFilters}
>
^ Reset filters
</Button>
</div>
</div>
)}
</div> </div>
); );
}; };

View File

@ -1,5 +1,7 @@
import React from 'react'; import React from 'react';
import { IconButton } from '@material-tailwind/react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
interface TemplateDetails { interface TemplateDetails {
@ -12,15 +14,19 @@ interface TemplateCardProps {
const TemplateCard: React.FC<TemplateCardProps> = ({ framework }) => { const TemplateCard: React.FC<TemplateCardProps> = ({ framework }) => {
return ( return (
<div className="group bg-gray-200 text-gray-500 text-xs border-gray-200 rounded-lg shadow p-4 flex items-center justify-between"> <Link to={'/projects/create/template'}>
<div> <div className="h-14 group bg-gray-200 text-gray-500 text-xs border-gray-200 rounded-lg shadow p-4 flex items-center justify-between">
<div className="grow">
{framework.icon} {framework.icon}
{framework.framework} {framework.framework}
</div> </div>
<Link to={'/projects/create/template'}> <div>
<button className="hidden group-hover:block">{'>'}</button> <IconButton size="sm" className="hidden group-hover:block">
</Link> {'>'}
</IconButton>
</div> </div>
</div>
</Link>
); );
}; };

View File

@ -57,7 +57,6 @@ const FilterForm = ({ value, onChange }: FilterFormProps) => {
<Select <Select
value={selectedStatus} value={selectedStatus}
onChange={(value) => setSelectedStatus(value!)} onChange={(value) => setSelectedStatus(value!)}
label="Select Version"
> >
{Object.values(StatusOptions).map((status) => ( {Object.values(StatusOptions).map((status) => (
<Option <Option