import { AgnosticAddress, AgnosticLocale, AgnosticStore, UseStoreGetters } from '@vue-storefront/core'; import { Store, Channel, Address } from '@vue-storefront/commercetools-api'; import { StoresData } from '../types'; import { FilterCriteriaRecord, Localized, filterArrayByCriteriaRecord } from '../helpers/internals'; export interface StoreFilterCriteria { store?: FilterCriteriaRecord; channel?: FilterCriteriaRecord } type StoreChannelSetKeys = 'distributionChannels' | 'supplyChannels'; function mapToAddress(address: Address): AgnosticAddress { return { addressLine1: `${address?.country ?? ''} ${address?.city ?? ''} ${address?.postalCode ?? ''}`.trim(), addressLine2: `${address?.streetName ?? ''} ${address?.streetNumber ?? ''}`.trim(), _address: address ?? null }; } function mapToLocale (localized: T): AgnosticLocale { return { code: localized.locale, /** * TODO * CT GraphQL "LocalizedString" type does not provide locale label value. * The default value is empty string to match the "AgnosticLocale" type. * Maybe AgnosticLocale["label"] property should be optional? */ label: '' }; } function mapToLocales(localized: Localized[]): AgnosticLocale[] { return localized?.map(mapToLocale) ?? null; } function mapStoreAndChannelToAgnosticStore (store: Store) { return function (channel?: Channel): AgnosticStore { return { name: `${store?.name ?? ''}${channel?.name ? ` - ${channel?.name}` : ''}`.trim(), id: `${store?.id ?? ''}${channel?.id ? `/${channel?.id}` : ''}`.trim(), description: channel?.description ?? '', geoLocation: channel?.geoLocation ?? null, locales: (mapToLocales(channel?.descriptionAllLocales) ?? store.languages) ?? [], address: mapToAddress(channel?.address), key: `${store?.key ?? ''}${channel?.id ? `/${channel?.id}` : ''}`.trim(), _storeID: store?.id ?? null, _channelID: channel?.id ?? null }; }; } function mapChannelSet (store: Store, channels: Channel[]): AgnosticStore[] { return channels?.map(mapStoreAndChannelToAgnosticStore(store)) ?? []; } function mapChannelSetByKey (store: Store, key: StoreChannelSetKeys, criteria?: FilterCriteriaRecord): AgnosticStore[] { return mapChannelSet( store, filterArrayByCriteriaRecord( store?.[key], criteria ) ); } function gainAgnosticStoreItems (criteria?: FilterCriteriaRecord) { return function (acc: AgnosticStore[], store: Store): AgnosticStore[] { const mappedStores = [ ...mapChannelSetByKey(store, 'distributionChannels', criteria), ...mapChannelSetByKey(store, 'supplyChannels', criteria) ]; return [ ...acc, ...(!mappedStores.length && !criteria ? [mapStoreAndChannelToAgnosticStore(store)()] : mappedStores) ]; }; } function getItems (stores: StoresData, criteria: StoreFilterCriteria = {}): AgnosticStore[] { return filterArrayByCriteriaRecord( stores?.results, criteria?.store) ?.reduce(gainAgnosticStoreItems(criteria.channel), []) ?? []; } function getSelected (stores: StoresData): AgnosticStore | undefined { return getItems(stores, { store: { key: (stores?._selectedStore ?? '') }})[0]; } const storeGetters: UseStoreGetters = { getItems, getSelected }; export default storeGetters;