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",
"updatedTime": "2023-05-15T08:30:00"
"title": "project-101",
"updatedAt": "2023-12-21T08:30:00",
"user": "bob"
},
{
"title": "Project-102",
"updatedTime": "2023-05-15T08:30:00"
"title": "project-102",
"updatedAt": "2023-12-21T08:30:00",
"user": "alice"
},
{
"title": "Project-103",
"updatedTime": "2023-12-11T04:20:00"
"title": "project-103",
"updatedAt": "2023-12-21T04:20:00",
"user": "charlie"
},
{
"title": "Project-104",
"updatedTime": "2023-12-11T04:27:00"
"title": "project-104",
"updatedAt": "2023-12-21T04:27:00",
"user": "alice"
},
{
"title": "Project-105",
"updatedTime": "2023-12-11T04:41:00"
"title": "project-105",
"updatedAt": "2023-12-21T04:41:00",
"user": "ivan"
},
{
"title": "Project-106",
"updatedTime": "2023-12-11T04:32:00"
"title": "project-106",
"updatedAt": "2023-12-21T04:32:00",
"user": "david"
}
]

View File

@ -1,10 +1,13 @@
import React from 'react';
import { IconButton } from '@material-tailwind/react';
import { relativeTime } from '../../../utils/time';
interface RepositoryDetails {
title: string;
updatedTime: string;
updatedAt: string;
user: string;
}
interface ProjectRepoCardProps {
@ -13,11 +16,16 @@ interface ProjectRepoCardProps {
const ProjectRepoCard: React.FC<ProjectRepoCardProps> = ({ repository }) => {
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 className="grow">
<p>{repository.title}</p>
<p>{relativeTime(repository.updatedTime)}</p>
<p className="text-black">
{repository.user}/{repository.title}
</p>
<p>{relativeTime(repository.updatedAt)}</p>
</div>
<div className="hidden group-hover:block">
<IconButton size="sm">{'>'}</IconButton>
</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 ProjectRepoCard from './ProjectRepoCard';
import repositoryDetails from '../../../assets/repositories.json';
import Dropdown from '../../Dropdown';
const ACCOUNT_OPTIONS = [
{ value: 'alice', label: 'Alice' },
{ value: 'bob', label: 'Bob' },
{ value: 'charlie', label: 'Charlie' },
];
const DEFAULT_SEARCHED_REPO = '';
const DEFAULT_SELECTED_USER = 'All accounts';
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 (
<div className="p-4">
<div className="flex">
<div className="flex gap-2">
<div className="basis-1/3">
<Dropdown
placeholder="All accounts"
options={ACCOUNT_OPTIONS}
onChange={() => {}}
/>
<Select
value={selectedUser}
onChange={(value) => setSelectedUser(value!)}
>
{users.map((user, key) => (
<Option
className={user === selectedUser ? 'hidden' : ''}
key={key}
value={user}
>
^ {user}
</Option>
))}
</Select>
</div>
<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>
{repositoryDetails.map((repo, key) => {
return <ProjectRepoCard repository={repo} key={key} />;
})}
{Boolean(filteredRepos.length) ? (
filteredRepos.map((repo, 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>
);
};

View File

@ -1,5 +1,7 @@
import React from 'react';
import { IconButton } from '@material-tailwind/react';
import { Link } from 'react-router-dom';
interface TemplateDetails {
@ -12,15 +14,19 @@ interface TemplateCardProps {
const TemplateCard: React.FC<TemplateCardProps> = ({ framework }) => {
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">
<div>
{framework.icon}
{framework.framework}
<Link to={'/projects/create/template'}>
<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.framework}
</div>
<div>
<IconButton size="sm" className="hidden group-hover:block">
{'>'}
</IconButton>
</div>
</div>
<Link to={'/projects/create/template'}>
<button className="hidden group-hover:block">{'>'}</button>
</Link>
</div>
</Link>
);
};

View File

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