import type { ProductOptionValues } from '@commerce/types/product' import type { JsonApiDocument, JsonApiResponse, } from '@spree/storefront-api-v2-sdk/types/interfaces/JsonApi' import { jsonApi } from '@spree/storefront-api-v2-sdk' import type { RelationType } from '@spree/storefront-api-v2-sdk/types/interfaces/Relationships' import SpreeResponseContentError from '../errors/SpreeResponseContentError' import type { OptionTypeAttr, ExpandedProductOption } from '../types' import sortOptionsByPosition from '../utils/sort-option-types' const isColorProductOption = (productOption: ExpandedProductOption) => { return productOption.displayName === 'Color' } const expandOptions = ( spreeSuccessResponse: JsonApiResponse, spreeOptionValue: JsonApiDocument, accumulatedOptions: ExpandedProductOption[] ): ExpandedProductOption[] => { const spreeOptionTypeIdentifier = spreeOptionValue.relationships.option_type .data as RelationType const existingOptionIndex = accumulatedOptions.findIndex( (option) => option.id == spreeOptionTypeIdentifier.id ) let option: ExpandedProductOption if (existingOptionIndex === -1) { const spreeOptionType = jsonApi.findDocument( spreeSuccessResponse, spreeOptionTypeIdentifier ) if (!spreeOptionType) { throw new SpreeResponseContentError( `Option type with id ${spreeOptionTypeIdentifier.id} not found.` ) } option = { __typename: 'MultipleChoiceOption', id: spreeOptionType.id, displayName: spreeOptionType.attributes.presentation, position: spreeOptionType.attributes.position, values: [], } } else { const existingOption = accumulatedOptions[existingOptionIndex] option = existingOption } let optionValue: ProductOptionValues const label = isColorProductOption(option) ? spreeOptionValue.attributes.name : spreeOptionValue.attributes.presentation const productOptionValueExists = option.values.some( (optionValue: ProductOptionValues) => optionValue.label === label ) if (!productOptionValueExists) { if (isColorProductOption(option)) { optionValue = { label, hexColors: [spreeOptionValue.attributes.presentation], } } else { optionValue = { label, } } if (existingOptionIndex === -1) { return [ ...accumulatedOptions, { ...option, values: [optionValue], }, ] } const expandedOptionValues = [...option.values, optionValue] const expandedOptions = [...accumulatedOptions] expandedOptions[existingOptionIndex] = { ...option, values: expandedOptionValues, } const sortedOptions = sortOptionsByPosition(expandedOptions) return sortedOptions } return accumulatedOptions } export default expandOptions