import { isEmpty } from "lodash" import { useAdminProducts } from "medusa-react" import qs from "qs" import React, { useEffect, useState } from "react" import { useLocation } from "react-router-dom" import { usePagination, useTable } from "react-table" import { useTranslation } from "react-i18next" import ProductsFilter from "../../../domain/products/filter-dropdown" import { useAnalytics } from "../../../providers/analytics-provider" import { useFeatureFlag } from "../../../providers/feature-flag-provider" import Table from "../../molecules/table" import TableContainer from "../../organisms/table-container" import ProductOverview from "./overview" import useProductActions from "./use-product-actions" import useProductTableColumn from "./use-product-column" import { useProductFilters } from "./use-product-filters" const DEFAULT_PAGE_SIZE = 15 const DEFAULT_PAGE_SIZE_TILE_VIEW = 18 const defaultQueryProps = { fields: "id,title,thumbnail,status,handle,collection_id", expand: "variants,options,variants.prices,variants.options,collection,tags,type,images", is_giftcard: false, } const ProductTable = () => { const location = useLocation() const { t } = useTranslation() const { isFeatureEnabled } = useFeatureFlag() const { trackNumberOfProducts } = useAnalytics() let hiddenColumns = ["sales_channel"] if (isFeatureEnabled("sales_channels")) { defaultQueryProps.expand = "variants,options,variants.prices,variants.options,collection,tags,type,images,sales_channels" hiddenColumns = [] } const { removeTab, setTab, saveTab, availableTabs: filterTabs, activeFilterTab, reset, paginate, setFilters, setLimit, filters, setQuery: setFreeText, queryObject, representationObject, } = useProductFilters(location.search, defaultQueryProps) const offs = parseInt(queryObject.offset) || 0 const limit = parseInt(queryObject.limit) const [query, setQuery] = useState(queryObject.query) const [numPages, setNumPages] = useState(0) const clearFilters = () => { reset() setQuery("") } const { products, isLoading, count } = useAdminProducts( { ...queryObject, }, { keepPreviousData: true, onSuccess: ({ count }) => trackNumberOfProducts({ count }), } ) useEffect(() => { if (typeof count !== "undefined") { const controlledPageCount = Math.ceil(count / limit) setNumPages(controlledPageCount) } }, [count]) const updateUrlFromFilter = (obj = {}) => { const stringified = qs.stringify(obj) window.history.replaceState(`/a/products`, "", `${`?${stringified}`}`) } const refreshWithFilters = () => { const filterObj = representationObject if (isEmpty(filterObj)) { updateUrlFromFilter({ offset: 0, limit: DEFAULT_PAGE_SIZE }) } else { updateUrlFromFilter(filterObj) } } useEffect(() => { refreshWithFilters() }, [representationObject]) const setTileView = () => { setLimit(DEFAULT_PAGE_SIZE_TILE_VIEW) setShowList(false) } const setListView = () => { setLimit(DEFAULT_PAGE_SIZE) setShowList(true) } const [showList, setShowList] = React.useState(true) const [columns] = useProductTableColumn({ setTileView, setListView, showList, }) const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow, gotoPage, canPreviousPage, canNextPage, pageCount, nextPage, previousPage, // Get the state from the instance state: { pageIndex }, } = useTable( { columns, data: products || [], manualPagination: true, initialState: { pageIndex: Math.floor(offs / limit), pageSize: limit, hiddenColumns, }, pageCount: numPages, autoResetPage: false, }, usePagination ) // Debounced search useEffect(() => { const delayDebounceFn = setTimeout(() => { if (query) { setFreeText(query) gotoPage(0) } else { if (typeof query !== "undefined") { // if we delete query string, we reset the table view reset() } } }, 400) return () => clearTimeout(delayDebounceFn) }, [query]) const handleNext = () => { if (canNextPage) { paginate(1) nextPage() } } const handlePrev = () => { if (canPreviousPage) { paginate(-1) previousPage() } } return ( } enableSearch searchValue={query} handleSearch={setQuery} {...getTableProps()} > {showList ? ( <> {headerGroups?.map((headerGroup) => ( {headerGroup.headers.map((col) => ( {col.render("Header")} ))} ))} {rows.map((row) => { prepareRow(row) return })} ) : ( )}
) } const ProductRow = ({ row, ...rest }) => { const product = row.original const { getActions } = useProductActions(product) return ( {row.cells.map((cell, index) => { return ( {cell.render("Cell", { index })} ) })} ) } export default ProductTable