forked from cerc-io/snowballtools-base
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:
parent
6590b8f6f5
commit
5c762f3583
@ -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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user