noogle/website/components/basicList/basicList.tsx

135 lines
4.0 KiB
TypeScript
Raw Normal View History

import React, { useMemo, useState } from "react";
import { Box, List, ListItem, Stack, TablePagination } from "@mui/material";
import { BasicDataViewProps } from "../../types/basicDataView";
2022-11-26 12:36:08 +03:00
import { SearchInput } from "../searchInput";
2022-12-11 23:22:45 +03:00
2022-12-18 19:58:53 +03:00
import { Filter } from "../searchInput/searchInput";
import { usePageContext } from "../pageContext";
import { useMobile } from "../layout/layout";
import { EmptyRecordsPlaceholder } from "../emptyRecordsPlaceholder";
import { FunctionOfTheDay } from "../functionOfTheDay";
import { Query, SearchOptions } from "minisearch";
2022-11-26 12:36:08 +03:00
export type BasicListItem = {
item: React.ReactNode;
key: string;
};
export type BasicListProps = BasicDataViewProps & {
2022-12-03 19:48:36 +03:00
selected?: string | null;
search: (query: Query, options?: SearchOptions) => void;
2022-11-26 12:36:08 +03:00
};
type ViewMode = "explore" | "browse";
2022-11-26 12:36:08 +03:00
export function BasicList(props: BasicListProps) {
const { items, search } = props;
const { pageState, setPageStateVariable, resetQueries } = usePageContext();
const isMobile = useMobile();
const { page, itemsPerPage, filter, term, FOTD, data } = pageState;
const [mode, setMode] = useState<ViewMode>("explore");
const setPage = setPageStateVariable<number>("page");
const setTerm = setPageStateVariable<string>("term");
const setFilter = setPageStateVariable<Filter>("filter");
const setItemsPerPage = setPageStateVariable<number>("itemsPerPage");
2022-11-26 12:36:08 +03:00
const handleChangeRowsPerPage = (
event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
setItemsPerPage(parseInt(event.target.value, 10));
setPage(1);
};
2022-12-09 18:41:59 +03:00
const pageItems = useMemo(() => {
const startIdx = (page - 1) * itemsPerPage;
const endIdx = page * itemsPerPage;
return items.slice(startIdx, endIdx);
}, [page, items, itemsPerPage]);
2022-11-26 12:36:08 +03:00
const handlePageChange = (
event: React.MouseEvent<HTMLButtonElement> | null,
2022-11-26 12:36:08 +03:00
value: number
) => {
setPage(value + 1);
};
const handleClear = () => {
resetQueries();
2022-11-26 12:36:08 +03:00
};
const handleFilter = (filter: Filter | ((curr: Filter) => Filter)) => {
setFilter(filter);
2022-11-26 12:36:08 +03:00
setPage(1);
};
const handleSearch = (term: string) => {
setTerm(term);
search(term);
2022-11-26 12:36:08 +03:00
setPage(1);
};
2022-11-27 16:16:52 +03:00
const showFunctionOfTheDay =
mode === "explore" &&
filter.to === "any" &&
filter.from === "any" &&
term === "" &&
FOTD === true;
2022-11-26 12:36:08 +03:00
return (
<Stack>
<SearchInput
handleFilter={handleFilter}
handleClear={handleClear}
2022-11-26 12:36:08 +03:00
placeholder="search nix functions"
handleSearch={handleSearch}
2022-11-26 12:36:08 +03:00
/>
{showFunctionOfTheDay ? (
<FunctionOfTheDay
data={data}
handleClose={() => {
setMode("browse");
}}
/>
) : (
<List aria-label="basic-list" sx={{ pt: 0 }}>
{items.length ? (
pageItems.map(({ item, key }, idx) => (
<Box key={`${key}-${idx}`}>
<ListItem sx={{ px: 0 }} key={key} aria-label={`item-${key}`}>
{item}
</ListItem>
</Box>
))
) : (
<Box sx={{ mt: 3 }}>
<EmptyRecordsPlaceholder
CardProps={{
sx: { backgroundColor: "inherit" },
}}
title={"No search results found"}
subtitle={
"Maybe the function does not exist or is not documented."
}
/>
</Box>
)}
</List>
)}
{!showFunctionOfTheDay && (
<TablePagination
component={"div"}
sx={{ display: "flex", justifyContent: "center", mt: 1, mb: 10 }}
count={items.length}
color="primary"
page={page - 1}
onPageChange={handlePageChange}
rowsPerPage={itemsPerPage}
labelRowsPerPage={"per Page"}
rowsPerPageOptions={[10, 20, 50, 100]}
onRowsPerPageChange={handleChangeRowsPerPage}
showFirstButton={!isMobile}
showLastButton={!isMobile}
/>
)}
2022-11-26 12:36:08 +03:00
</Stack>
);
}