import { useState, useCallback, useEffect } from "react";
import {
TextField,
ResourceList,
ResourceItem,
Thumbnail,
Card,
Button,
Stack,
Text,
Icon,
} from "@shopify/polaris";
import { SearchMinor } from "@shopify/polaris-icons";
/**
* Searchable, paginated product list. Checking a product adds it to the group;
* selected ids are controlled by the parent.
*/
export function ProductMultiSelect({ selectedIds, onToggle }) {
const [query, setQuery] = useState("");
const [products, setProducts] = useState([]);
const [pageInfo, setPageInfo] = useState({});
const [loading, setLoading] = useState(false);
const load = useCallback(async (q, after) => {
setLoading(true);
try {
const params = new URLSearchParams();
if (q) params.set("q", q);
if (after) params.set("after", after);
const res = await fetch(`/api/products?${params.toString()}`);
const data = await res.json();
setProducts((prev) =>
after ? [...prev, ...data.products] : data.products
);
setPageInfo(data.pageInfo || {});
} finally {
setLoading(false);
}
}, []);
useEffect(() => {
const t = setTimeout(() => load(query), 250);
return () => clearTimeout(t);
}, [query, load]);
return (
<Card>
<Card.Section>
<TextField
label="Search products"
labelHidden
prefix={<Icon source={SearchMinor} />}
value={query}
onChange={setQuery}
placeholder="Search products to add…"
autoComplete="off"
/>
</Card.Section>
<ResourceList
resourceName={{ singular: "product", plural: "products" }}
items={products}
loading={loading}
renderItem={(p) => {
const checked = selectedIds.includes(p.id);
return (
<ResourceItem
id={p.id}
media={
<Thumbnail size="small" source={p.image || ""} alt={p.title} />
}
onClick={() => onToggle(p)}
>
<Stack alignment="center">
<Stack.Item fill>
<Text variant="bodyMd" as="span">
{p.title}
</Text>
</Stack.Item>
<Button
size="slim"
primary={!checked}
pressed={checked}
onClick={(e) => {
e.stopPropagation();
onToggle(p);
}}
>
{checked ? "Added" : "Add"}
</Button>
</Stack>
</ResourceItem>
);
}}
/>
{pageInfo.hasNextPage && (
<Card.Section>
<Button
fullWidth
loading={loading}
onClick={() => load(query, pageInfo.endCursor)}
>
Load more
</Button>
</Card.Section>
)}
</Card>
);
}