import { ChannelSaleData, validateSalePrice } from "@dashboard/channels/utils"; import { TopNav } from "@dashboard/components/AppLayout/TopNav"; import CardSpacer from "@dashboard/components/CardSpacer"; import ChannelsAvailabilityCard from "@dashboard/components/ChannelsAvailabilityCard"; import Form from "@dashboard/components/Form"; import { DetailPageLayout } from "@dashboard/components/Layouts"; import Metadata, { MetadataFormData } from "@dashboard/components/Metadata"; import Savebar from "@dashboard/components/Savebar"; import { Tab, TabContainer } from "@dashboard/components/Tab"; import { createSaleChannelsChangeHandler, createSaleUpdateHandler, } from "@dashboard/discounts/handlers"; import { itemsQuantityMessages } from "@dashboard/discounts/translations"; import { saleListUrl } from "@dashboard/discounts/urls"; import { SALE_UPDATE_FORM_ID } from "@dashboard/discounts/views/SaleDetails/types"; import { DiscountErrorFragment, PermissionEnum, SaleDetailsFragment, SaleType as SaleTypeEnum, } from "@dashboard/graphql"; import { SubmitPromise } from "@dashboard/hooks/useForm"; import useNavigator from "@dashboard/hooks/useNavigator"; import { mapEdgesToItems, mapMetadataItemToInput } from "@dashboard/utils/maps"; import useMetadataChangeTrigger from "@dashboard/utils/metadata/useMetadataChangeTrigger"; import { ConfirmButtonTransitionState } from "@saleor/macaw-ui"; import { sprinkles } from "@saleor/macaw-ui/next"; import React from "react"; import { useIntl } from "react-intl"; import { splitDateTime } from "../../../misc"; import { ChannelProps, ListProps, TabListActions } from "../../../types"; import DiscountCategories from "../DiscountCategories"; import DiscountCollections from "../DiscountCollections"; import DiscountDates from "../DiscountDates"; import DiscountProducts from "../DiscountProducts"; import DiscountVariants from "../DiscountVariants"; import SaleInfo from "../SaleInfo"; import SaleSummary from "../SaleSummary"; import SaleType from "../SaleType"; import SaleValue from "../SaleValue"; export interface ChannelSaleFormData extends ChannelSaleData { percentageValue: string; fixedValue: string; } export interface SaleDetailsPageFormData extends MetadataFormData { channelListings: ChannelSaleFormData[]; endDate: string; endTime: string; hasEndDate: boolean; name: string; startDate: string; startTime: string; type: SaleTypeEnum; } export enum SaleDetailsPageTab { categories = "categories", collections = "collections", products = "products", variants = "variants", } export type SaleTabItemsCount = Partial>; export interface SaleDetailsPageProps extends Pick>, TabListActions< | "categoryListToolbar" | "collectionListToolbar" | "productListToolbar" | "variantListToolbar" >, ChannelProps { activeTab: SaleDetailsPageTab; tabItemsCount: SaleTabItemsCount; errors: DiscountErrorFragment[]; sale: SaleDetailsFragment; allChannelsCount: number; channelListings: ChannelSaleFormData[]; saveButtonBarState: ConfirmButtonTransitionState; onCategoryAssign: () => void; onCategoryUnassign: (id: string) => void; onCollectionAssign: () => void; onCollectionUnassign: (id: string) => void; onProductAssign: () => void; onProductUnassign: (id: string) => void; onVariantAssign: () => void; onVariantUnassign: (id: string) => void; onRemove: () => void; onSubmit: (data: SaleDetailsPageFormData) => SubmitPromise; onTabClick: (index: SaleDetailsPageTab) => void; onChannelsChange: (data: ChannelSaleFormData[]) => void; openChannelsModal: () => void; } const CategoriesTab = Tab(SaleDetailsPageTab.categories); const CollectionsTab = Tab(SaleDetailsPageTab.collections); const ProductsTab = Tab(SaleDetailsPageTab.products); const VariantsTab = Tab(SaleDetailsPageTab.variants); const SaleDetailsPage: React.FC = ({ activeTab, tabItemsCount = {}, allChannelsCount, channelListings = [], disabled, errors, onRemove, onSubmit, onTabClick, openChannelsModal, sale, saveButtonBarState, onCategoryAssign, onCategoryUnassign, onChannelsChange, onCollectionAssign, onCollectionUnassign, onProductAssign, onProductUnassign, onVariantAssign, onVariantUnassign, categoryListToolbar, collectionListToolbar, productListToolbar, variantListToolbar, isChecked, selected, selectedChannelId, toggle, toggleAll, }) => { const intl = useIntl(); const navigate = useNavigator(); const [localErrors, setLocalErrors] = React.useState( [], ); const { makeChangeHandler: makeMetadataChangeHandler } = useMetadataChangeTrigger(); const initialForm: SaleDetailsPageFormData = { channelListings, endDate: splitDateTime(sale?.endDate ?? "").date, endTime: splitDateTime(sale?.endDate ?? "").time, hasEndDate: !!sale?.endDate, name: sale?.name ?? "", startDate: splitDateTime(sale?.startDate ?? "").date, startTime: splitDateTime(sale?.startDate ?? "").time, type: sale?.type ?? SaleTypeEnum.FIXED, metadata: sale?.metadata.map(mapMetadataItemToInput), privateMetadata: sale?.privateMetadata.map(mapMetadataItemToInput), }; const checkIfSaveIsDisabled = (data: SaleDetailsPageFormData) => data.channelListings?.some(channel => validateSalePrice(data, channel)) || disabled; return (
{({ change, data, submit, triggerChange }) => { const handleChannelChange = createSaleChannelsChangeHandler( data.channelListings, onChannelsChange, triggerChange, data.type, ); const changeMetadata = makeMetadataChangeHandler(change); const handleSubmit = createSaleUpdateHandler(submit, setLocalErrors); const allErrors = [...localErrors, ...errors]; return ( {intl.formatMessage(itemsQuantityMessages.categories, { quantity: tabItemsCount.categories?.toString() || "…", })} {intl.formatMessage(itemsQuantityMessages.collections, { quantity: tabItemsCount.collections?.toString() || "…", })} {intl.formatMessage(itemsQuantityMessages.products, { quantity: tabItemsCount.products?.toString() || "…", })} {intl.formatMessage(itemsQuantityMessages.variants, { quantity: tabItemsCount.variants?.toString() || "…", })} {activeTab === SaleDetailsPageTab.categories ? ( ) : activeTab === SaleDetailsPageTab.collections ? ( ) : activeTab === SaleDetailsPageTab.products ? ( ) : ( )} ({ id: channel.id, name: channel.name, }))} disabled={disabled} openModal={openChannelsModal} /> navigate(saleListUrl())} onDelete={onRemove} onSubmit={() => handleSubmit(data)} state={saveButtonBarState} /> ); }}
); }; SaleDetailsPage.displayName = "SaleDetailsPage"; export default SaleDetailsPage;