Add load more to category and collection selection

This commit is contained in:
dominik-zeglen 2020-10-26 12:20:52 +01:00
parent 96d8aa101c
commit fb0a503b91
5 changed files with 183 additions and 80 deletions

View file

@ -17,7 +17,10 @@ import ResponsiveTable from "@saleor/components/ResponsiveTable";
import useSearchQuery from "@saleor/hooks/useSearchQuery";
import { buttonMessages } from "@saleor/intl";
import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories";
import useScrollableDialogStyle from "@saleor/styles/useScrollableDialogStyle";
import { FetchMoreProps } from "@saleor/types";
import React from "react";
import InfiniteScroll from "react-infinite-scroller";
import { FormattedMessage, useIntl } from "react-intl";
import Checkbox from "../Checkbox";
@ -37,9 +40,6 @@ const useStyles = makeStyles(
checkboxCell: {
paddingLeft: 0
},
overflow: {
overflowY: "visible"
},
wideCell: {
width: "100%"
}
@ -47,7 +47,7 @@ const useStyles = makeStyles(
{ name: "AssignCategoryDialog" }
);
interface AssignCategoriesDialogProps {
interface AssignCategoriesDialogProps extends FetchMoreProps {
categories: SearchCategories_search_edges_node[];
confirmButtonState: ConfirmButtonTransitionState;
open: boolean;
@ -80,25 +80,31 @@ const AssignCategoriesDialog: React.FC<AssignCategoriesDialogProps> = props => {
open,
loading,
categories: categories,
hasMore,
onClose,
onFetch,
onFetchMore,
onSubmit
} = props;
const classes = useStyles(props);
const scrollableDialogClasses = useScrollableDialogStyle({});
const intl = useIntl();
const [query, onQueryChange] = useSearchQuery(onFetch);
const [selectedCategories, setSelectedCategories] = React.useState<
SearchCategories_search_edges_node[]
>([]);
const container = React.useRef<HTMLDivElement>();
const handleSubmit = () => onSubmit(selectedCategories);
const containerHeight = container.current?.scrollHeight - 130;
return (
<Dialog
classes={{ paper: scrollableDialogClasses.dialog }}
open={open}
onClose={onClose}
classes={{ paper: classes.overflow }}
fullWidth
maxWidth="sm"
>
@ -108,7 +114,10 @@ const AssignCategoriesDialog: React.FC<AssignCategoriesDialogProps> = props => {
description="dialog header"
/>
</DialogTitle>
<DialogContent className={classes.overflow}>
<DialogContent
className={scrollableDialogClasses.content}
ref={container}
>
<TextField
name="query"
value={query}
@ -126,40 +135,59 @@ const AssignCategoriesDialog: React.FC<AssignCategoriesDialogProps> = props => {
}}
/>
<FormSpacer />
<ResponsiveTable>
<TableBody>
{categories &&
categories.map(category => {
const isSelected = !!selectedCategories.find(
selectedCategories => selectedCategories.id === category.id
);
<div
className={scrollableDialogClasses.scrollArea}
style={{ height: containerHeight }}
>
<InfiniteScroll
pageStart={0}
loadMore={onFetchMore}
hasMore={hasMore}
useWindow={false}
loader={
<div className={scrollableDialogClasses.loadMoreLoaderContainer}>
<CircularProgress size={16} />
</div>
}
threshold={10}
>
<ResponsiveTable key="table">
<TableBody>
{categories &&
categories.map(category => {
const isSelected = !!selectedCategories.find(
selectedCategories =>
selectedCategories.id === category.id
);
return (
<TableRow key={category.id}>
<TableCell
padding="checkbox"
className={classes.checkboxCell}
>
<Checkbox
checked={isSelected}
onChange={() =>
handleCategoryAssign(
category,
isSelected,
selectedCategories,
setSelectedCategories
)
}
/>
</TableCell>
<TableCell className={classes.wideCell}>
{category.name}
</TableCell>
</TableRow>
);
})}
</TableBody>
</ResponsiveTable>
return (
<TableRow key={category.id}>
<TableCell
padding="checkbox"
className={classes.checkboxCell}
>
<Checkbox
checked={isSelected}
onChange={() =>
handleCategoryAssign(
category,
isSelected,
selectedCategories,
setSelectedCategories
)
}
/>
</TableCell>
<TableCell className={classes.wideCell}>
{category.name}
</TableCell>
</TableRow>
);
})}
</TableBody>
</ResponsiveTable>
</InfiniteScroll>
</div>
</DialogContent>
<DialogActions>
<Button onClick={onClose}>

View file

@ -13,7 +13,10 @@ import ResponsiveTable from "@saleor/components/ResponsiveTable";
import useSearchQuery from "@saleor/hooks/useSearchQuery";
import { buttonMessages } from "@saleor/intl";
import { SearchCollections_search_edges_node } from "@saleor/searches/types/SearchCollections";
import useScrollableDialogStyle from "@saleor/styles/useScrollableDialogStyle";
import { FetchMoreProps } from "@saleor/types";
import React from "react";
import InfiniteScroll from "react-infinite-scroller";
import { FormattedMessage, useIntl } from "react-intl";
import Checkbox from "../Checkbox";
@ -37,9 +40,6 @@ const useStyles = makeStyles(
checkboxCell: {
paddingLeft: 0
},
overflow: {
overflowY: "visible"
},
wideCell: {
width: "100%"
}
@ -47,7 +47,7 @@ const useStyles = makeStyles(
{ name: "AssignCollectionDialog" }
);
interface AssignCollectionDialogProps {
interface AssignCollectionDialogProps extends FetchMoreProps {
collections: SearchCollections_search_edges_node[];
confirmButtonState: ConfirmButtonTransitionState;
open: boolean;
@ -77,28 +77,34 @@ function handleCollectionAssign(
const AssignCollectionDialog: React.FC<AssignCollectionDialogProps> = props => {
const {
confirmButtonState,
hasMore,
open,
loading,
collections,
onClose,
onFetch,
onFetchMore,
onSubmit
} = props;
const classes = useStyles(props);
const scrollableDialogClasses = useScrollableDialogStyle({});
const intl = useIntl();
const [query, onQueryChange] = useSearchQuery(onFetch);
const [selectedCollections, setSelectedCollections] = React.useState<
SearchCollections_search_edges_node[]
>([]);
const container = React.useRef<HTMLDivElement>();
const handleSubmit = () => onSubmit(selectedCollections);
const containerHeight = container.current?.scrollHeight - 130;
return (
<Dialog
onClose={onClose}
open={open}
classes={{ paper: classes.overflow }}
classes={{ paper: scrollableDialogClasses.dialog }}
fullWidth
maxWidth="sm"
>
@ -108,7 +114,7 @@ const AssignCollectionDialog: React.FC<AssignCollectionDialogProps> = props => {
description="dialog header"
/>
</DialogTitle>
<DialogContent className={classes.overflow}>
<DialogContent className={scrollableDialogClasses.content}>
<TextField
name="query"
value={query}
@ -126,40 +132,59 @@ const AssignCollectionDialog: React.FC<AssignCollectionDialogProps> = props => {
}}
/>
<FormSpacer />
<ResponsiveTable>
<TableBody>
{collections &&
collections.map(collection => {
const isSelected = !!selectedCollections.find(
selectedCollection => selectedCollection.id === collection.id
);
<div
className={scrollableDialogClasses.scrollArea}
style={{ height: containerHeight }}
>
<InfiniteScroll
pageStart={0}
loadMore={onFetchMore}
hasMore={hasMore}
useWindow={false}
loader={
<div className={scrollableDialogClasses.loadMoreLoaderContainer}>
<CircularProgress size={16} />
</div>
}
threshold={10}
>
<ResponsiveTable>
<TableBody>
{collections &&
collections.map(collection => {
const isSelected = !!selectedCollections.find(
selectedCollection =>
selectedCollection.id === collection.id
);
return (
<TableRow key={collection.id}>
<TableCell
padding="checkbox"
className={classes.checkboxCell}
>
<Checkbox
checked={isSelected}
onChange={() =>
handleCollectionAssign(
collection,
isSelected,
selectedCollections,
setSelectedCollections
)
}
/>
</TableCell>
<TableCell className={classes.wideCell}>
{collection.name}
</TableCell>
</TableRow>
);
})}
</TableBody>
</ResponsiveTable>
return (
<TableRow key={collection.id}>
<TableCell
padding="checkbox"
className={classes.checkboxCell}
>
<Checkbox
checked={isSelected}
onChange={() =>
handleCollectionAssign(
collection,
isSelected,
selectedCollections,
setSelectedCollections
)
}
/>
</TableCell>
<TableCell className={classes.wideCell}>
{collection.name}
</TableCell>
</TableRow>
);
})}
</TableBody>
</ResponsiveTable>
</InfiniteScroll>
</div>
</DialogContent>
<DialogActions>
<Button onClick={onClose}>

View file

@ -68,14 +68,14 @@ export const SaleDetails: React.FC<SaleDetailsProps> = ({ id, params }) => {
);
const intl = useIntl();
const {
// loadMore: loadMoreCategories,
loadMore: loadMoreCategories,
search: searchCategories,
result: searchCategoriesOpts
} = useCategorySearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const {
// loadMore: loadMoreCollections,
loadMore: loadMoreCollections,
search: searchCollections,
result: searchCollectionsOpts
} = useCollectionSearch({
@ -367,8 +367,13 @@ export const SaleDetails: React.FC<SaleDetailsProps> = ({ id, params }) => {
)
)}
confirmButtonState={saleCataloguesAddOpts.status}
hasMore={
searchCategoriesOpts.data?.search.pageInfo
.hasNextPage
}
open={params.action === "assign-category"}
onFetch={searchCategories}
onFetchMore={loadMoreCategories}
loading={searchCategoriesOpts.loading}
onClose={closeModal}
onSubmit={categories =>
@ -394,8 +399,13 @@ export const SaleDetails: React.FC<SaleDetailsProps> = ({ id, params }) => {
)
)}
confirmButtonState={saleCataloguesAddOpts.status}
hasMore={
searchCollectionsOpts.data?.search.pageInfo
.hasNextPage
}
open={params.action === "assign-collection"}
onFetch={searchCollections}
onFetchMore={loadMoreCollections}
loading={searchCollectionsOpts.loading}
onClose={closeModal}
onSubmit={collections =>

View file

@ -70,12 +70,14 @@ export const VoucherDetails: React.FC<VoucherDetailsProps> = ({
);
const intl = useIntl();
const {
loadMore: loadMoreCategories,
search: searchCategories,
result: searchCategoriesOpts
} = useCategorySearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const {
loadMore: loadMoreCollections,
search: searchCollections,
result: searchCollectionsOpts
} = useCollectionSearch({
@ -411,8 +413,13 @@ export const VoucherDetails: React.FC<VoucherDetailsProps> = ({
confirmButtonState={
voucherCataloguesAddOpts.status
}
hasMore={
searchCategoriesOpts.data?.search.pageInfo
.hasNextPage
}
open={params.action === "assign-category"}
onFetch={searchCategories}
onFetchMore={loadMoreCategories}
loading={searchCategoriesOpts.loading}
onClose={closeModal}
onSubmit={categories =>
@ -440,8 +447,13 @@ export const VoucherDetails: React.FC<VoucherDetailsProps> = ({
confirmButtonState={
voucherCataloguesAddOpts.status
}
hasMore={
searchCollectionsOpts.data?.search.pageInfo
.hasNextPage
}
open={params.action === "assign-collection"}
onFetch={searchCollections}
onFetchMore={loadMoreCollections}
loading={searchCollectionsOpts.loading}
onClose={closeModal}
onSubmit={collections =>

View file

@ -0,0 +1,28 @@
import makeStyles from "@material-ui/core/styles/makeStyles";
const useScrollableDialogStyle = makeStyles(
theme => ({
content: {
overflowY: "hidden"
},
dialog: {
height: "calc(100% - 64px)",
maxHeight: 700
},
loadMoreLoaderContainer: {
alignItems: "center",
display: "flex",
height: theme.spacing(3),
justifyContent: "center",
marginTop: theme.spacing(3)
},
scrollArea: {
overflowY: "scroll"
}
}),
{
name: "ScrollableDialog"
}
);
export default useScrollableDialogStyle;