Solstice web interface.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

67 lines
1.5 KiB

import {
ChangeEvent,
FC,
ReactElement,
ReactEventHandler,
useState,
} from "react";
interface ItemProps<Item> {
name: string;
data: Item;
}
interface ListProps<Item> {
title: string;
onRefresh: ReactEventHandler;
component: FC<ItemProps<Item>>;
map: { [key: string]: Item };
}
function SearchableList<Item>({
title,
onRefresh,
component,
map,
}: ListProps<Item>): ReactElement {
const [filter, setFilter] = useState<string>("");
const onChange = (event: ChangeEvent<HTMLInputElement>) => {
setFilter(event.target.value);
};
const children = [];
for (const name in map) {
if (name.includes(filter)) {
children.push(<li key={name}>{component({ name, data: map[name] })}</li>);
}
}
return (
<div className="flex flex-col px-3 h-full">
<div className="flex justify-between p-3">
<h1 className="pl-3 text-2xl font-bold text-yellow-800 text-center">
{title}
</h1>
<button onClick={onRefresh} className="button">
Refresh
</button>
</div>
<form className="flex gap-3 p-3">
<label htmlFor="filter" className="self-center">
Filter:
</label>
<input
name="filter"
type="text"
className="text-input flex-grow"
value={filter}
onChange={onChange}
/>
</form>
<ul className="flex-1 flex flex-col min-h-0 overflow-auto">{children}</ul>
</div>
);
}
export default SearchableList;