Add global search and filtering enhancements

This commit is contained in:
Mondo Diaz
2025-12-12 12:12:46 -06:00
parent 7d80bef39a
commit 096887d4da
11 changed files with 910 additions and 10 deletions

View File

@@ -5,6 +5,7 @@ import { listProjects, createProject } from '../api';
import { Badge } from '../components/Badge';
import { SearchInput } from '../components/SearchInput';
import { SortDropdown, SortOption } from '../components/SortDropdown';
import { FilterDropdown, FilterOption } from '../components/FilterDropdown';
import { FilterChip, FilterChipGroup } from '../components/FilterChip';
import { Pagination } from '../components/Pagination';
import './Home.css';
@@ -15,6 +16,12 @@ const SORT_OPTIONS: SortOption[] = [
{ value: 'updated_at', label: 'Updated' },
];
const VISIBILITY_OPTIONS: FilterOption[] = [
{ value: '', label: 'All Projects' },
{ value: 'public', label: 'Public Only' },
{ value: 'private', label: 'Private Only' },
];
function Home() {
const [searchParams, setSearchParams] = useSearchParams();
@@ -30,6 +37,7 @@ function Home() {
const search = searchParams.get('search') || '';
const sort = searchParams.get('sort') || 'name';
const order = (searchParams.get('order') || 'asc') as 'asc' | 'desc';
const visibility = searchParams.get('visibility') || '';
const updateParams = useCallback(
(updates: Record<string, string | undefined>) => {
@@ -49,7 +57,13 @@ function Home() {
const loadProjects = useCallback(async () => {
try {
setLoading(true);
const data = await listProjects({ page, search, sort, order });
const data = await listProjects({
page,
search,
sort,
order,
visibility: visibility as 'public' | 'private' | undefined || undefined,
});
setProjectsData(data);
setError(null);
} catch (err) {
@@ -57,7 +71,7 @@ function Home() {
} finally {
setLoading(false);
}
}, [page, search, sort, order]);
}, [page, search, sort, order, visibility]);
useEffect(() => {
loadProjects();
@@ -86,6 +100,10 @@ function Home() {
updateParams({ sort: newSort, order: newOrder, page: '1' });
};
const handleVisibilityChange = (value: string) => {
updateParams({ visibility: value, page: '1' });
};
const handlePageChange = (newPage: number) => {
updateParams({ page: String(newPage) });
};
@@ -94,7 +112,7 @@ function Home() {
setSearchParams({});
};
const hasActiveFilters = search !== '';
const hasActiveFilters = search !== '' || visibility !== '';
const projects = projectsData?.items || [];
const pagination = projectsData?.pagination;
@@ -160,12 +178,25 @@ function Home() {
placeholder="Search projects..."
className="list-controls__search"
/>
<FilterDropdown
label="Visibility"
options={VISIBILITY_OPTIONS}
value={visibility}
onChange={handleVisibilityChange}
/>
<SortDropdown options={SORT_OPTIONS} value={sort} order={order} onChange={handleSortChange} />
</div>
{hasActiveFilters && (
<FilterChipGroup onClearAll={clearFilters}>
{search && <FilterChip label="Search" value={search} onRemove={() => handleSearchChange('')} />}
{visibility && (
<FilterChip
label="Visibility"
value={visibility === 'public' ? 'Public' : 'Private'}
onRemove={() => handleVisibilityChange('')}
/>
)}
</FilterChipGroup>
)}