diff --git a/client/app/components/cards-list/CardsList.jsx b/client/app/components/cards-list/CardsList.jsx deleted file mode 100644 index 39a9747fad..0000000000 --- a/client/app/components/cards-list/CardsList.jsx +++ /dev/null @@ -1,84 +0,0 @@ -import Input from "antd/lib/input"; -import { includes, isEmpty } from "lodash"; -import PropTypes from "prop-types"; -import React from "react"; -import Link from "@/components/Link"; -import EmptyState from "@/components/items-list/components/EmptyState"; - -import "./CardsList.less"; - -const { Search } = Input; - -export default class CardsList extends React.Component { - static propTypes = { - items: PropTypes.arrayOf( - PropTypes.shape({ - title: PropTypes.string.isRequired, - imgSrc: PropTypes.string.isRequired, - onClick: PropTypes.func, - href: PropTypes.string, - }) - ), - showSearch: PropTypes.bool, - }; - - static defaultProps = { - items: [], - showSearch: false, - }; - - state = { - searchText: "", - }; - - constructor(props) { - super(props); - this.items = []; - - let itemId = 1; - props.items.forEach(item => { - this.items.push({ id: itemId, ...item }); - itemId += 1; - }); - } - - // eslint-disable-next-line class-methods-use-this - renderListItem(item) { - return ( - - {item.title} -

{item.title}

- - ); - } - - render() { - const { showSearch } = this.props; - const { searchText } = this.state; - - const filteredItems = this.items.filter( - item => isEmpty(searchText) || includes(item.title.toLowerCase(), searchText.toLowerCase()) - ); - - return ( -
- {showSearch && ( -
-
- this.setState({ searchText: e.target.value })} autoFocus /> -
-
- )} - {isEmpty(filteredItems) ? ( - - ) : ( -
-
- {filteredItems.map(item => this.renderListItem(item))} -
-
- )} -
- ); - } -} diff --git a/client/app/components/cards-list/CardsList.tsx b/client/app/components/cards-list/CardsList.tsx new file mode 100644 index 0000000000..d3b305892b --- /dev/null +++ b/client/app/components/cards-list/CardsList.tsx @@ -0,0 +1,80 @@ +import { includes, isEmpty } from "lodash"; +import PropTypes from "prop-types"; +import React, { useState } from "react"; +import Input from "antd/lib/input"; +import Link from "@/components/Link"; +import EmptyState from "@/components/items-list/components/EmptyState"; + +import "./CardsList.less"; + +export interface CardsListItem { + title: string; + imgSrc: string; + onClick?: () => void; + href?: string; +} + +export interface CardsListProps { + items?: CardsListItem[]; + showSearch?: boolean; +} + +interface ListItemProps { + item: CardsListItem; + keySuffix: string; +} + +function ListItem({ item, keySuffix }: ListItemProps) { + return ( + + {item.title} +

{item.title}

+ + ); +} + +export default function CardsList({ items = [], showSearch = false }: CardsListProps) { + const [searchText, setSearchText] = useState(""); + const filteredItems = items.filter( + item => isEmpty(searchText) || includes(item.title.toLowerCase(), searchText.toLowerCase()) + ); + + return ( +
+ {showSearch && ( +
+
+ ) => setSearchText(e.target.value)} + autoFocus + /> +
+
+ )} + {isEmpty(filteredItems) ? ( + + ) : ( +
+
+ {filteredItems.map((item: CardsListItem, index: number) => ( + + ))} +
+
+ )} +
+ ); +} + +CardsList.propTypes = { + items: PropTypes.arrayOf( + PropTypes.shape({ + title: PropTypes.string.isRequired, + imgSrc: PropTypes.string.isRequired, + onClick: PropTypes.func, + href: PropTypes.string, + }) + ), + showSearch: PropTypes.bool, +};