diff --git a/.changeset/soft-buses-roll.md b/.changeset/soft-buses-roll.md new file mode 100644 index 000000000..8196d2742 --- /dev/null +++ b/.changeset/soft-buses-roll.md @@ -0,0 +1,5 @@ +--- +"saleor-dashboard": minor +--- + +Introduce datagrid on voucher list view diff --git a/locale/defaultMessages.json b/locale/defaultMessages.json index c660c51cf..81a082aeb 100644 --- a/locale/defaultMessages.json +++ b/locale/defaultMessages.json @@ -997,9 +997,6 @@ "50lR2F": { "string": "- used by Payment Plugins" }, - "51HE+Q": { - "string": "No sales found" - }, "54KYgS": { "context": "months after label", "string": "months after issue" @@ -2921,9 +2918,6 @@ "context": "window title", "string": "Create category" }, - "IruP2T": { - "string": "Search Voucher" - }, "IwEQvz": { "context": "success activate alert message", "string": "Successfully activated gift {count,plural,one{card} other{cards}}" @@ -5551,6 +5545,9 @@ "context": "product type", "string": "Product Type" }, + "bPshhv": { + "string": "Search vouchers..." + }, "bRJD/v": { "context": "button", "string": "Create permission group" @@ -6925,6 +6922,9 @@ "context": "section header", "string": "Eligible Variants" }, + "lfXze9": { + "string": "Delete vouchers" + }, "li1BBk": { "context": "export items as csv file", "string": "Plain CSV file" @@ -7394,9 +7394,9 @@ "context": "status", "string": "Deactivated" }, - "pNrF72": { + "pOUOnw": { "context": "tab name", - "string": "All Vouchers" + "string": "All vouchers" }, "pPef6L": { "context": "order payment", diff --git a/src/config.ts b/src/config.ts index f91ff5a95..87495e8b9 100644 --- a/src/config.ts +++ b/src/config.ts @@ -127,6 +127,7 @@ export const defaultListSettings: AppListViewSettings = { }, [ListViews.VOUCHER_LIST]: { rowNumber: PAGINATE_BY, + columns: ["code", "min-spent", "start-date", "end-date", "value", "limit"], }, [ListViews.WAREHOUSE_LIST]: { rowNumber: PAGINATE_BY, diff --git a/src/discounts/components/SaleListDatagrid/messages.ts b/src/discounts/components/SaleListDatagrid/messages.ts index 0d7f6567e..e71b1715c 100644 --- a/src/discounts/components/SaleListDatagrid/messages.ts +++ b/src/discounts/components/SaleListDatagrid/messages.ts @@ -25,7 +25,7 @@ export const columnsMessages = defineMessages({ export const messages = defineMessages({ empty: { - id: "51HE+Q", - defaultMessage: "No sales found", + id: "U2mOqA", + defaultMessage: "No vouchers found", }, }); diff --git a/src/discounts/components/VoucherListDatagrid/VoucherListDatagrid.tsx b/src/discounts/components/VoucherListDatagrid/VoucherListDatagrid.tsx new file mode 100644 index 000000000..50e239fe8 --- /dev/null +++ b/src/discounts/components/VoucherListDatagrid/VoucherListDatagrid.tsx @@ -0,0 +1,176 @@ +import { ColumnPicker } from "@dashboard/components/Datagrid/ColumnPicker/ColumnPicker"; +import { useColumns } from "@dashboard/components/Datagrid/ColumnPicker/useColumns"; +import Datagrid from "@dashboard/components/Datagrid/Datagrid"; +import { + DatagridChangeStateContext, + useDatagridChangeState, +} from "@dashboard/components/Datagrid/hooks/useDatagridChange"; +import { TablePaginationWithContext } from "@dashboard/components/TablePagination"; +import { commonTooltipMessages } from "@dashboard/components/TooltipTableCellHeader/messages"; +import { VoucherListUrlSortField, voucherUrl } from "@dashboard/discounts/urls"; +import { canBeSorted } from "@dashboard/discounts/views/VoucherList/sort"; +import { VoucherFragment } from "@dashboard/graphql"; +import useLocale from "@dashboard/hooks/useLocale"; +import useNavigator from "@dashboard/hooks/useNavigator"; +import { ChannelProps, ListProps, SortPage } from "@dashboard/types"; +import { Item } from "@glideapps/glide-data-grid"; +import { Box } from "@saleor/macaw-ui/next"; +import React, { useCallback, useMemo } from "react"; +import { useIntl } from "react-intl"; + +import { + createGetCellContent, + vouchersListStaticColumnsAdapter, +} from "./datagrid"; +import { messages } from "./messages"; + +interface VoucherListDatagridProps + extends ListProps, + SortPage, + ChannelProps { + vouchers: VoucherFragment[]; + onSelectVouchersIds: ( + rowsIndex: number[], + clearSelection: () => void, + ) => void; +} + +export const VoucherListDatagrid = ({ + vouchers, + settings, + sort, + selectedChannelId, + disabled, + filterDependency, + onSort, + onSelectVouchersIds, + onUpdateListSettings, +}: VoucherListDatagridProps) => { + const datagridState = useDatagridChangeState(); + const navigate = useNavigator(); + const { locale } = useLocale(); + const intl = useIntl(); + + const vouchersListStaticColumns = useMemo( + () => vouchersListStaticColumnsAdapter(intl, sort), + [intl, sort], + ); + + const onColumnChange = useCallback( + (picked: string[]) => { + if (onUpdateListSettings) { + onUpdateListSettings("columns", picked.filter(Boolean)); + } + }, + [onUpdateListSettings], + ); + + const { + handlers, + visibleColumns, + recentlyAddedColumn, + staticColumns, + selectedColumns, + } = useColumns({ + selectedColumns: settings?.columns ?? [], + staticColumns: vouchersListStaticColumns, + onSave: onColumnChange, + }); + + const getCellContent = useCallback( + createGetCellContent({ + vouchers, + columns: visibleColumns, + locale, + selectedChannelId, + }), + [vouchers, selectedChannelId, locale, visibleColumns], + ); + + const handleRowClick = useCallback( + ([_, row]: Item) => { + const rowData: VoucherFragment = vouchers[row]; + + if (rowData) { + navigate(voucherUrl(rowData.id)); + } + }, + [vouchers], + ); + + const handleRowAnchor = useCallback( + ([, row]: Item) => voucherUrl(vouchers[row].id), + [vouchers], + ); + + const handleGetColumnTooltipContent = useCallback( + (col: number): string => { + const columnName = visibleColumns[col].id as VoucherListUrlSortField; + + if (canBeSorted(columnName, !!selectedChannelId)) { + return ""; + } + + // Sortable but requrie selected channel + return intl.formatMessage(commonTooltipMessages.noFilterSelected, { + filterName: filterDependency?.label ?? "", + }); + }, + [filterDependency, intl, selectedChannelId, visibleColumns], + ); + + const handleHeaderClick = useCallback( + (col: number) => { + const columnName = visibleColumns[col].id as VoucherListUrlSortField; + + if (canBeSorted(columnName, !!selectedChannelId)) { + onSort(columnName); + } + }, + [visibleColumns, onSort], + ); + + return ( + + col > 0} + rows={vouchers?.length ?? 0} + availableColumns={visibleColumns} + emptyText={intl.formatMessage(messages.empty)} + onRowSelectionChange={onSelectVouchersIds} + getCellContent={getCellContent} + getCellError={() => false} + selectionActions={() => null} + menuItems={() => []} + onRowClick={handleRowClick} + onHeaderClicked={handleHeaderClick} + rowAnchor={handleRowAnchor} + getColumnTooltipContent={handleGetColumnTooltipContent} + recentlyAddedColumn={recentlyAddedColumn} + renderColumnPicker={() => ( + + )} + /> + + + + + + ); +}; diff --git a/src/discounts/components/VoucherListDatagrid/datagrid.ts b/src/discounts/components/VoucherListDatagrid/datagrid.ts new file mode 100644 index 000000000..51a0d7d85 --- /dev/null +++ b/src/discounts/components/VoucherListDatagrid/datagrid.ts @@ -0,0 +1,143 @@ +import { PLACEHOLDER } from "@dashboard/components/Datagrid/const"; +import { + moneyCell, + readonlyTextCell, +} from "@dashboard/components/Datagrid/customCells/cells"; +import { AvailableColumn } from "@dashboard/components/Datagrid/types"; +import { Locale } from "@dashboard/components/Locale"; +import { VoucherListUrlSortField } from "@dashboard/discounts/urls"; +import { VoucherFragment } from "@dashboard/graphql"; +import { Sort } from "@dashboard/types"; +import { getColumnSortDirectionIcon } from "@dashboard/utils/columns/getColumnSortDirectionIcon"; +import { GridCell, Item } from "@glideapps/glide-data-grid"; +import moment from "moment"; +import { IntlShape } from "react-intl"; + +import { columnsMessages } from "./messages"; + +export const vouchersListStaticColumnsAdapter = ( + intl: IntlShape, + sort: Sort, +) => + [ + { + id: "code", + title: intl.formatMessage(columnsMessages.code), + width: 350, + }, + { + id: "min-spent", + title: intl.formatMessage(columnsMessages.minSpent), + width: 200, + }, + { + id: "start-date", + title: intl.formatMessage(columnsMessages.starts), + width: 200, + }, + { + id: "end-date", + title: intl.formatMessage(columnsMessages.ends), + width: 200, + }, + { + id: "value", + title: intl.formatMessage(columnsMessages.value), + width: 200, + }, + { + id: "limit", + title: intl.formatMessage(columnsMessages.uses), + width: 200, + }, + ].map(column => ({ + ...column, + icon: getColumnSortDirectionIcon(sort, column.id), + })); + +export const createGetCellContent = + ({ + vouchers, + columns, + locale, + selectedChannelId, + }: { + vouchers: VoucherFragment[]; + columns: AvailableColumn[]; + locale: Locale; + selectedChannelId?: string; + }) => + ([column, row]: Item): GridCell => { + const rowData: VoucherFragment | undefined = vouchers[row]; + const columnId = columns[column]?.id; + + if (!columnId || !rowData) { + return readonlyTextCell(""); + } + + const channel = rowData?.channelListings?.find( + lisiting => lisiting.channel.id === selectedChannelId, + ); + const hasChannelsLoaded = rowData?.channelListings?.length; + + switch (columnId) { + case "code": + return readonlyTextCell(rowData?.code ?? PLACEHOLDER); + case "min-spent": + return rowData?.code && hasChannelsLoaded + ? moneyCell( + channel?.minSpent?.amount ?? "", + channel?.minSpent?.currency ?? "", + { + readonly: true, + }, + ) + : readonlyTextCell(PLACEHOLDER); + case "start-date": + return readonlyTextCell( + rowData.startDate + ? moment(rowData.startDate).locale(locale).format("lll") + : PLACEHOLDER, + ); + case "end-date": + return readonlyTextCell( + rowData.endDate + ? moment(rowData.endDate).locale(locale).format("lll") + : PLACEHOLDER, + ); + + case "value": + return getVoucherValueCell(rowData, channel); + + case "limit": + return readonlyTextCell( + rowData.usageLimit === null + ? PLACEHOLDER + : rowData.usageLimit.toString(), + ); + + default: + return readonlyTextCell(""); + } + }; + +function getVoucherValueCell( + voucher: VoucherFragment, + channel: NonNullable[number] | undefined, +) { + const hasChannelsLoaded = voucher?.channelListings?.length; + + if (!hasChannelsLoaded) { + return readonlyTextCell(PLACEHOLDER); + } + + if (voucher?.discountValueType === "FIXED") { + return moneyCell(channel?.discountValue ?? "", channel?.currency ?? "", { + readonly: true, + }); + } + + return moneyCell(channel?.discountValue ?? "", "%", { + readonly: true, + }); +} diff --git a/src/discounts/components/VoucherListDatagrid/index.ts b/src/discounts/components/VoucherListDatagrid/index.ts new file mode 100644 index 000000000..f47fbaa04 --- /dev/null +++ b/src/discounts/components/VoucherListDatagrid/index.ts @@ -0,0 +1 @@ +export * from "./VoucherListDatagrid"; diff --git a/src/discounts/components/VoucherListDatagrid/messages.ts b/src/discounts/components/VoucherListDatagrid/messages.ts new file mode 100644 index 000000000..bf594a333 --- /dev/null +++ b/src/discounts/components/VoucherListDatagrid/messages.ts @@ -0,0 +1,41 @@ +import { defineMessages } from "react-intl"; + +export const columnsMessages = defineMessages({ + code: { + id: "JsPIOX", + defaultMessage: "Code", + description: "voucher code", + }, + minSpent: { + id: "tuYPlG", + defaultMessage: "Min. Spent", + description: "minimum amount of spent money to activate voucher", + }, + starts: { + id: "5u7b3V", + defaultMessage: "Starts", + description: "voucher is active from date", + }, + ends: { + id: "b6L9n7", + defaultMessage: "Ends", + description: "voucher is active until date", + }, + value: { + id: "JV+EiM", + defaultMessage: "Value", + description: "voucher value", + }, + uses: { + id: "yHwvLL", + defaultMessage: "Uses", + description: "voucher uses", + }, +}); + +export const messages = defineMessages({ + empty: { + id: "U2mOqA", + defaultMessage: "No vouchers found", + }, +}); diff --git a/src/discounts/components/VoucherListPage/VoucherListPage.stories.tsx b/src/discounts/components/VoucherListPage/VoucherListPage.stories.tsx index a4b857b0f..effd7ca8f 100644 --- a/src/discounts/components/VoucherListPage/VoucherListPage.stories.tsx +++ b/src/discounts/components/VoucherListPage/VoucherListPage.stories.tsx @@ -2,12 +2,11 @@ import { voucherList } from "@dashboard/discounts/fixtures"; import { VoucherListUrlSortField } from "@dashboard/discounts/urls"; import { - filterPageProps, + filterPresetsProps, listActionsProps, pageListProps, searchPageProps, sortPageProps, - tabPageProps, } from "@dashboard/fixtures"; import { DiscountStatusEnum, VoucherDiscountType } from "@dashboard/graphql"; import { Meta, StoryObj } from "@storybook/react"; @@ -20,8 +19,11 @@ const props: VoucherListPageProps = { ...pageListProps.default, ...searchPageProps, ...sortPageProps, - ...tabPageProps, - ...filterPageProps, + ...filterPresetsProps, + onSelectVouchersIds: () => undefined, + selectedVouchersIds: [], + onVoucherDelete: () => undefined, + onFilterChange: () => undefined, filterOpts: { channel: { active: false, @@ -62,6 +64,10 @@ const props: VoucherListPageProps = { sort: VoucherListUrlSortField.code, }, vouchers: voucherList, + settings: { + rowNumber: 20, + columns: ["code", "min-spent", "start-date", "end-date", "value", "limit"], + }, }; const meta: Meta = { @@ -85,6 +91,7 @@ export const Loading: Story = { args: { ...props, vouchers: undefined, + disabled: true, }, parameters: { chromatic: { diffThreshold: 0.85 }, diff --git a/src/discounts/components/VoucherListPage/VoucherListPage.tsx b/src/discounts/components/VoucherListPage/VoucherListPage.tsx index a87733662..451a4606a 100644 --- a/src/discounts/components/VoucherListPage/VoucherListPage.tsx +++ b/src/discounts/components/VoucherListPage/VoucherListPage.tsx @@ -1,28 +1,29 @@ // @ts-strict-ignore +import { ListFilters } from "@dashboard/components/AppLayout/ListFilters"; import { TopNav } from "@dashboard/components/AppLayout/TopNav"; -import { Button } from "@dashboard/components/Button"; +import { BulkDeleteButton } from "@dashboard/components/BulkDeleteButton"; import { getByName } from "@dashboard/components/Filter/utils"; -import FilterBar from "@dashboard/components/FilterBar"; +import { FilterPresetsSelect } from "@dashboard/components/FilterPresetsSelect"; import { ListPageLayout } from "@dashboard/components/Layouts"; import { voucherAddUrl, VoucherListUrlSortField, } from "@dashboard/discounts/urls"; import { VoucherFragment } from "@dashboard/graphql"; +import useNavigator from "@dashboard/hooks/useNavigator"; import { sectionNames } from "@dashboard/intl"; import { ChannelProps, - FilterPageProps, - ListActions, + FilterPagePropsWithPresets, PageListProps, SortPage, - TabPageProps, } from "@dashboard/types"; import { Card } from "@material-ui/core"; -import React from "react"; +import { Box, Button, ChevronRightIcon } from "@saleor/macaw-ui/next"; +import React, { useState } from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import VoucherList from "../VoucherList"; +import { VoucherListDatagrid } from "../VoucherListDatagrid"; import { createFilterStructure, VoucherFilterKeys, @@ -31,69 +32,119 @@ import { export interface VoucherListPageProps extends PageListProps, - ListActions, - FilterPageProps, + FilterPagePropsWithPresets, SortPage, - TabPageProps, ChannelProps { vouchers: VoucherFragment[]; + selectedVouchersIds: string[]; + onVoucherDelete: () => void; + onSelectVouchersIds: (rows: number[], clearSelection: () => void) => void; } const VoucherListPage: React.FC = ({ - currentTab, filterOpts, initialSearch, - onAll, onFilterChange, onSearchChange, - onTabChange, - onTabDelete, - onTabSave, - tabs, + hasPresetsChanged, + onFilterPresetChange, + onFilterPresetDelete, + onFilterPresetPresetSave, + onFilterPresetUpdate, + onFilterPresetsAll, + filterPresets, + selectedFilterPreset, + onVoucherDelete, + selectedVouchersIds, + currencySymbol, ...listProps }) => { const intl = useIntl(); + const navigate = useNavigator(); const structure = createFilterStructure(intl, filterOpts); + const [isFilterPresetOpen, setFilterPresetOpen] = useState(false); const filterDependency = structure.find(getByName("channel")); return ( - - + + + + + + + + + + + - + currencySymbol={currencySymbol} initialSearch={initialSearch} - searchPlaceholder={intl.formatMessage({ - id: "IruP2T", - defaultMessage: "Search Voucher", - })} - tabs={tabs} - onAll={onAll} onFilterChange={onFilterChange} onSearchChange={onSearchChange} - onTabChange={onTabChange} - onTabDelete={onTabDelete} - onTabSave={onTabSave} + filterStructure={structure} + searchPlaceholder={intl.formatMessage({ + id: "bPshhv", + defaultMessage: "Search vouchers...", + })} + actions={ + + {selectedVouchersIds.length > 0 && ( + + + + )} + + } + /> + + - ); diff --git a/src/discounts/views/VoucherList/VoucherList.tsx b/src/discounts/views/VoucherList/VoucherList.tsx index de03dac92..2b277293a 100644 --- a/src/discounts/views/VoucherList/VoucherList.tsx +++ b/src/discounts/views/VoucherList/VoucherList.tsx @@ -2,15 +2,13 @@ import ActionDialog from "@dashboard/components/ActionDialog"; import useAppChannel from "@dashboard/components/AppLayout/AppChannelContext"; import DeleteFilterTabDialog from "@dashboard/components/DeleteFilterTabDialog"; -import SaveFilterTabDialog, { - SaveFilterTabDialogFormData, -} from "@dashboard/components/SaveFilterTabDialog"; +import SaveFilterTabDialog from "@dashboard/components/SaveFilterTabDialog"; import { WindowTitle } from "@dashboard/components/WindowTitle"; import { useVoucherBulkDeleteMutation, useVoucherListQuery, } from "@dashboard/graphql"; -import useBulkActions from "@dashboard/hooks/useBulkActions"; +import { useFilterPresets } from "@dashboard/hooks/useFilterPresets"; import useListSettings from "@dashboard/hooks/useListSettings"; import useNavigator from "@dashboard/hooks/useNavigator"; import useNotifier from "@dashboard/hooks/useNotifier"; @@ -19,8 +17,8 @@ import usePaginator, { createPaginationState, PaginatorContext, } from "@dashboard/hooks/usePaginator"; +import { useRowSelection } from "@dashboard/hooks/useRowSelection"; import { commonMessages, sectionNames } from "@dashboard/intl"; -import { maybe } from "@dashboard/misc"; import { ListViews } from "@dashboard/types"; import createDialogActionHandlers from "@dashboard/utils/handlers/dialogActionHandlers"; import createFilterHandlers from "@dashboard/utils/handlers/filterHandlers"; @@ -28,8 +26,8 @@ import createSortHandler from "@dashboard/utils/handlers/sortHandler"; import { mapEdgesToItems, mapNodeToChoice } from "@dashboard/utils/maps"; import { getSortParams } from "@dashboard/utils/sort"; import { DialogContentText } from "@material-ui/core"; -import { DeleteIcon, IconButton } from "@saleor/macaw-ui"; -import React, { useEffect } from "react"; +import isEqual from "lodash/isEqual"; +import React, { useCallback, useEffect } from "react"; import { FormattedMessage, useIntl } from "react-intl"; import VoucherListPage from "../../components/VoucherListPage"; @@ -39,14 +37,10 @@ import { VoucherListUrlQueryParams, } from "../../urls"; import { - deleteFilterTab, - getActiveFilters, getFilterOpts, getFilterQueryParam, - getFiltersCurrentTab, - getFilterTabs, getFilterVariables, - saveFilterTab, + storageUtils, } from "./filters"; import { canBeSorted, DEFAULT_SORT_KEY, getSortQueryVariables } from "./sort"; @@ -57,9 +51,7 @@ interface VoucherListProps { export const VoucherList: React.FC = ({ params }) => { const navigate = useNavigator(); const notify = useNotifier(); - const { isSelected, listElements, reset, toggle, toggleAll } = useBulkActions( - params.ids, - ); + const { updateListSettings, settings } = useListSettings( ListViews.VOUCHER_LIST, ); @@ -96,17 +88,38 @@ export const VoucherList: React.FC = ({ params }) => { variables: queryVariables, }); - const tabs = getFilterTabs(); + const { + clearRowSelection, + selectedRowIds, + setSelectedRowIds, + setClearDatagridRowSelectionCallback, + } = useRowSelection(params); - const currentTab = getFiltersCurrentTab(params, tabs); + const { + hasPresetsChanged, + onPresetChange, + onPresetDelete, + onPresetSave, + onPresetUpdate, + selectedPreset, + presets, + getPresetNameToDelete, + setPresetIdToDelete, + } = useFilterPresets({ + getUrl: voucherListUrl, + params, + storageUtils, + reset: clearRowSelection, + }); const [changeFilters, resetFilters, handleSearchChange] = createFilterHandlers({ - cleanupFn: reset, + cleanupFn: clearRowSelection, createUrl: voucherListUrl, getFilterQueryParam, navigate, params, + keepActiveTab: true, }); useEffect(() => { @@ -120,29 +133,6 @@ export const VoucherList: React.FC = ({ params }) => { } }, [params]); - const handleTabChange = (tab: number) => { - reset(); - navigate( - voucherListUrl({ - activeTab: tab.toString(), - ...getFilterTabs()[tab - 1].data, - }), - ); - }; - - const handleTabDelete = () => { - deleteFilterTab(currentTab); - reset(); - navigate(voucherListUrl()); - }; - - const handleTabSave = (data: SaveFilterTabDialogFormData) => { - saveFilterTab(data.name, getActiveFilters(params)); - handleTabChange(tabs.length + 1); - }; - - const canOpenBulkActionDialog = maybe(() => params.ids.length > 0); - const paginationValues = usePaginator({ pageInfo: data?.vouchers?.pageInfo, paginationState, @@ -157,66 +147,85 @@ export const VoucherList: React.FC = ({ params }) => { status: "success", text: intl.formatMessage(commonMessages.savedChanges), }); - reset(); + clearRowSelection(); closeModal(); refetch(); } }, }); - const onVoucherBulkDelete = () => - voucherBulkDelete({ + const onVoucherBulkDelete = async () => { + await voucherBulkDelete({ variables: { - ids: params.ids, + ids: selectedRowIds, }, }); + clearRowSelection(); + }; const handleSort = createSortHandler(navigate, voucherListUrl, params); + const vouchers = mapEdgesToItems(data?.vouchers) ?? []; + + const handleSelectVouchersIds = useCallback( + (rows: number[], clearSelection: () => void) => { + if (!vouchers) { + return; + } + + const rowsIds = rows.map(row => vouchers[row]?.id); + const haveSaveValues = isEqual(rowsIds, selectedRowIds); + + if (!haveSaveValues) { + setSelectedRowIds(rowsIds); + } + + setClearDatagridRowSelectionCallback(clearSelection); + }, + [ + vouchers, + selectedRowIds, + setClearDatagridRowSelectionCallback, + setSelectedRowIds, + ], + ); + return ( changeFilters(filter)} - onAll={resetFilters} - onTabChange={handleTabChange} - onTabDelete={() => openModal("delete-search")} - onTabSave={() => openModal("save-search")} - tabs={tabs.map(tab => tab.name)} + onFilterPresetsAll={resetFilters} + onFilterPresetDelete={(id: number) => { + setPresetIdToDelete(id); + openModal("delete-search"); + }} + onFilterPresetPresetSave={() => openModal("save-search")} + onFilterPresetChange={onPresetChange} + onFilterPresetUpdate={onPresetUpdate} + hasPresetsChanged={hasPresetsChanged} + onVoucherDelete={() => openModal("remove")} + selectedFilterPreset={selectedPreset} + selectedVouchersIds={selectedRowIds} + currencySymbol={selectedChannel?.currencyCode} + filterPresets={presets.map(tab => tab.name)} settings={settings} - vouchers={mapEdgesToItems(data?.vouchers)} + vouchers={vouchers} disabled={loading} onUpdateListSettings={updateListSettings} onSort={handleSort} - isChecked={isSelected} - selected={listElements.length} sort={getSortParams(params)} - toggle={toggle} - toggleAll={toggleAll} - toolbar={ - - openModal("remove", { - ids: listElements, - }) - } - > - - - } selectedChannelId={selectedChannel?.id} /> 0} title={intl.formatMessage({ id: "Q0JJ4F", defaultMessage: "Delete Vouchers", @@ -224,32 +233,30 @@ export const VoucherList: React.FC = ({ params }) => { })} variant="delete" > - {canOpenBulkActionDialog && ( - - {params.ids.length}, - }} - /> - - )} + + {selectedRowIds.length}, + }} + /> + tabs[currentTab - 1].name, "...")} + onSubmit={onPresetDelete} + tabName={getPresetNameToDelete()} /> ); diff --git a/src/discounts/views/VoucherList/filters.ts b/src/discounts/views/VoucherList/filters.ts index 4bbf045dc..66a0d8987 100644 --- a/src/discounts/views/VoucherList/filters.ts +++ b/src/discounts/views/VoucherList/filters.ts @@ -151,8 +151,7 @@ export function getFilterQueryParam( } } -export const { deleteFilterTab, getFilterTabs, saveFilterTab } = - createFilterTabUtils(VOUCHER_FILTERS_KEY); +export const storageUtils = createFilterTabUtils(VOUCHER_FILTERS_KEY); export const { areFiltersApplied, getActiveFilters, getFiltersCurrentTab } = createFilterUtils({ diff --git a/src/hooks/useFilterPresets/useFilterPresets.ts b/src/hooks/useFilterPresets/useFilterPresets.ts index f573c4e41..a43c21276 100644 --- a/src/hooks/useFilterPresets/useFilterPresets.ts +++ b/src/hooks/useFilterPresets/useFilterPresets.ts @@ -18,6 +18,7 @@ export interface UseFilterPresets { onPresetDelete: () => void; onPresetSave: (data: SaveFilterTabDialogFormData) => void; onPresetUpdate: (tabName: string) => void; + getPresetNameToDelete: () => string; hasPresetsChanged: () => boolean; } @@ -122,9 +123,18 @@ export const useFilterPresets = < ); }; + const getPresetNameToDelete = (): string => { + const presetIndex = presetIdToDelete ? presetIdToDelete - 1 : 0; + const preset = presets?.[presetIndex]; + const tabName = preset?.name ?? "..."; + + return tabName; + }; + return { presetIdToDelete, setPresetIdToDelete, + getPresetNameToDelete, presets, selectedPreset, onPresetChange,