import {getCardComponentData} from "../cards"; import {CardRenderer, CardRendererContext} from "../CardRenderers"; import {ComponentMeta} from "../ComponentsMeta"; import {__, CouponsPlus} from "../../globals"; import {useTreeNodeTestable} from "../TreeHooks"; import {AmountValidatorOptions} from "./filterinterfaces"; import {FieldType} from "../fields"; import {usingTestableOptions} from "./CardHelpers"; import {amountValidatorTierFields, equals, TierType} from "../tiers"; import {number} from "motion"; import classNames from "classnames"; import {RowOptions} from "./Fields/RowOptions"; import {NumberProps} from "../fields/Number"; import React from "react"; export enum QuantityType { Any = 'any', Limit = 'limit', } export type QuantityOptions = AmountValidatorOptions & { type: QuantityType } const type = CouponsPlus?.components?.filters?.NumberOfItems?.type || 'NumberOfItems' export const QuantityMeta: ComponentMeta = { id: type, type: 'filters', supportsTiers: true, tierFields: amountValidatorTierFields(), tierType: TierType.Numeric, configurable: context => context !== 'tier-base', supportsCustomTitleForSuggestedScopes: (suggestedScope) => true, description: ({suggestedScope}) => { if (suggestedScope === 'bogo') { return __('These are the number of items the customer must buy for the bogo offer to apply.'); } }, icon({className}) { return }, fieldsMap: (componentRuntimeData, scope, suggestedScope) => [ [ /* edit: this is no longer going to be needed and if you've found this please delete it {id: 'type', renderType: FieldType.Tab} */ ], [ new RowOptions({ type: 'featured', colWidth: 'auto' }), { id: 'quantity', renderType: FieldType.Number, fieldProps: { border: false, labels: { input: { inputLeftOutside: suggestedScope === 'bogo' && scope === 'tree-node'? {__('Buy')} : undefined } } } as Partial } ] ], fieldsNotes: ({options}, scope) => [ scope.startsWith('tier') && __('Tier: The cheapest items will be selected from the filtered items.') ].filter(note => !!note), } export const QuantityRenderer: CardRenderer = { type, icon({className}) { return }, prefix: false, example: scope => scope === 'tier-base' ? __('2 -> 10% OFF, 3 -> 13% OFF, etc.') : __('Buy 1, Get 1 Free, 10% off Max. 5 items, etc.'), AboveComputedValue: usingTestableOptions(({quantity: {type} = {}} = {}, {context}) => { if ((['tier-base', 'tier-subchild'] as CardRendererContext[]).includes(context)) { return false } switch (type) { case "equals": case "range": return __('Quantity') case "minimum": return __('Minimum') case "maximum": return __('Maximum') } }), ComputedValue: usingTestableOptions(({quantity: {amount, type, range} = {}} = {}, {context}) => { if (context === 'tier-base') { return getCardComponentData('filter', QuantityMeta.id).name } let value: string | number = '' switch (type) { case "equals": case "minimum": case "maximum": value = amount! break case "range": value = `${range?.minimum} - ${range?.maxmimum}` break } if (context === 'tier-subchild') { return {value} {type === 'minimum' && } {type === 'maximum' && {__('max.')}} } return value }), canRenderInSelectedSidebarPopup: (options: QuantityOptions, currentFilterId: string): boolean => { // if its type is 'any' then it should not be shown in the sidebar popup return options?.type !== QuantityType.Any; }, canShowAsAvailableWhileBeingAmongstSelected: (options: QuantityOptions, currentFilterId): boolean => { const anyQuantity = options?.type === QuantityType.Any; const currentlySelectedFilterIsNotQuantity = currentFilterId !== QuantityMeta.id; return anyQuantity && currentlySelectedFilterIsNotQuantity; }, }