Skip to content

Commit 32b0e32

Browse files
committed
Add StaticListPageComponent and ToolsProvider context
1 parent 61c1615 commit 32b0e32

3 files changed

Lines changed: 439 additions & 0 deletions

File tree

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { FC, useState, useEffect } from 'react';
2+
import { Button, Dropdown, PanelHeader } from '@components/elements';
3+
import { Panel } from '@components/layout';
4+
import { MobileFilters, ToolCard, ToolsSidebar } from '@components/tools';
5+
import { useTools, type SortOption } from 'context/ToolsProvider';
6+
import { type ArticlePreview } from 'utils/types';
7+
import { FilterOption } from '../ToolsSidebar/FilterCard/FilterCard';
8+
import { LanguageFilterOption } from '../ToolsSidebar/FilterCard/LanguageFilterCard';
9+
import styles from '../ListPageComponent/ListPageComponent.module.css';
10+
11+
const DEFAULT_PAGE_SIZE = 50;
12+
13+
export interface StaticListComponentProps {
14+
languages: LanguageFilterOption[];
15+
others: FilterOption[];
16+
articles: ArticlePreview[];
17+
}
18+
19+
const StaticListComponent: FC<StaticListComponentProps> = ({
20+
languages,
21+
others,
22+
articles,
23+
}) => {
24+
const heading = `Static Analysis Tools`;
25+
const { tools, search, clearFilters, setSorting, totalCount } = useTools();
26+
27+
// Simple client-side pagination with "Load More"
28+
const [displayCount, setDisplayCount] = useState(DEFAULT_PAGE_SIZE);
29+
30+
// Reset display count when filters change
31+
const searchKey = JSON.stringify(search);
32+
useEffect(() => {
33+
setDisplayCount(DEFAULT_PAGE_SIZE);
34+
}, [searchKey]);
35+
36+
const displayedTools = tools.slice(0, displayCount);
37+
const hasMore = displayCount < totalCount;
38+
39+
const loadMore = () => {
40+
setDisplayCount((prev) => prev + DEFAULT_PAGE_SIZE);
41+
};
42+
43+
const changeSort = (e: React.ChangeEvent<HTMLSelectElement>) => {
44+
const sorting = e.target.value as SortOption;
45+
setSorting(sorting);
46+
};
47+
48+
const resetSearch = () => {
49+
clearFilters();
50+
};
51+
52+
// Show clear filter button if there are any filters applied
53+
const shouldShowClearFilterButton =
54+
Object.keys(search).filter((key) => key !== 'sorting').length > 0;
55+
56+
return (
57+
<>
58+
<ToolsSidebar
59+
languages={languages}
60+
others={others}
61+
articles={articles}
62+
/>
63+
<Panel>
64+
<PanelHeader level={3} text={heading}>
65+
<span className={styles.resultsCount}>
66+
{totalCount} tools
67+
</span>
68+
{shouldShowClearFilterButton ? (
69+
<Button
70+
className={styles.clearButton}
71+
onClick={resetSearch}
72+
theme="primary">
73+
Clear All Filters
74+
</Button>
75+
) : null}
76+
<Dropdown
77+
className="mobileHidden"
78+
changeSort={changeSort}
79+
/>
80+
<MobileFilters languages={languages} others={others} />
81+
</PanelHeader>
82+
{displayedTools.map((tool, index) => (
83+
<ToolCard key={`tool-${tool.id}-${index}`} tool={tool} />
84+
))}
85+
{hasMore && (
86+
<div className={styles.loadMoreContainer}>
87+
<Button onClick={loadMore} theme="secondary">
88+
Load More ({totalCount - displayCount} remaining)
89+
</Button>
90+
</div>
91+
)}
92+
</Panel>
93+
</>
94+
);
95+
};
96+
97+
export default StaticListComponent;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as StaticListPageComponent } from './StaticListPageComponent';

0 commit comments

Comments
 (0)