mirror of
https://github.com/vercel/commerce.git
synced 2025-05-15 05:56:59 +00:00
237 lines
7.4 KiB
TypeScript
237 lines
7.4 KiB
TypeScript
import {
|
|
ApiSchemas,
|
|
CategoryListingResultSW,
|
|
Collection,
|
|
Menu,
|
|
Product,
|
|
ProductOption,
|
|
ProductVariant
|
|
} from './types';
|
|
import { ListItem } from 'components/layout/search/filter';
|
|
|
|
export function transformMenu(res: ApiSchemas['NavigationRouteResponse']) {
|
|
let menu: Menu[] = [];
|
|
|
|
res.map((item) => menu.push(transformMenuItem(item)));
|
|
|
|
return menu;
|
|
}
|
|
|
|
function transformMenuItem(item: ApiSchemas['Category']): Menu {
|
|
return {
|
|
id: item.id ?? '',
|
|
title: item.name,
|
|
children: item.children?.map((item) => transformMenuItem(item)) ?? [],
|
|
path:
|
|
item.seoUrls && item.seoUrls.length > 0 && item.seoUrls[0] && item.seoUrls[0].seoPathInfo
|
|
? '/search/' + item.seoUrls[0].seoPathInfo
|
|
: '',
|
|
type: item.children && item.children.length > 0 ? 'headline' : 'link'
|
|
};
|
|
}
|
|
|
|
export function transformPage(
|
|
seoUrlElement: ApiSchemas['SeoUrl'],
|
|
resCategory: ApiSchemas['Category']
|
|
) {
|
|
return {
|
|
id: seoUrlElement.id ?? '',
|
|
title: resCategory.translated?.metaTitle ?? resCategory.name ?? '',
|
|
handle: seoUrlElement.seoPathInfo,
|
|
body: resCategory.description ?? '',
|
|
bodySummary: resCategory.translated?.metaDescription ?? resCategory.description ?? '',
|
|
seo: {
|
|
title: resCategory.translated?.metaTitle ?? resCategory.name ?? '',
|
|
description: resCategory.translated?.metaDescription ?? resCategory.description ?? ''
|
|
},
|
|
createdAt: seoUrlElement.createdAt ?? '',
|
|
updatedAt: seoUrlElement.updatedAt ?? '',
|
|
routeName: seoUrlElement.routeName,
|
|
foreignKey: seoUrlElement.foreignKey
|
|
};
|
|
}
|
|
|
|
export function transformCollection(
|
|
seoUrlElement: ApiSchemas['SeoUrl'],
|
|
resCategory: ApiSchemas['Category']
|
|
) {
|
|
return {
|
|
handle: seoUrlElement.seoPathInfo,
|
|
title: resCategory.translated?.metaTitle ?? resCategory.name ?? '',
|
|
description: resCategory.description ?? '',
|
|
seo: {
|
|
title: resCategory.translated?.metaTitle ?? resCategory.name ?? '',
|
|
description: resCategory.translated?.metaDescription ?? resCategory.description ?? ''
|
|
},
|
|
updatedAt: seoUrlElement.updatedAt ?? seoUrlElement.createdAt ?? ''
|
|
};
|
|
}
|
|
|
|
export function transformStaticCollection(resCategory: CategoryListingResultSW): Collection[] {
|
|
let collection: Collection[] = [];
|
|
|
|
if (resCategory.elements && resCategory.elements.length > 0) {
|
|
resCategory.elements.map((item) =>
|
|
collection.push({
|
|
handle:
|
|
item.seoUrls && item.seoUrls.length > 0 && item.seoUrls[0] && item.seoUrls[0].seoPathInfo
|
|
? item.seoUrls[0].seoPathInfo
|
|
: '',
|
|
title: item.translated?.metaTitle ?? item.name ?? '',
|
|
description: item.description ?? '',
|
|
seo: {
|
|
title: item.translated?.metaTitle ?? item.name ?? '',
|
|
description: item.translated?.metaDescription ?? item.description ?? ''
|
|
},
|
|
updatedAt: item.updatedAt ?? item.createdAt ?? ''
|
|
})
|
|
);
|
|
}
|
|
|
|
return collection;
|
|
}
|
|
|
|
export function transformStaticCollectionToList(collection: Collection[]): ListItem[] {
|
|
let listItem: ListItem[] = [];
|
|
|
|
if (collection && collection.length > 0) {
|
|
collection.map((item) =>
|
|
listItem.push({
|
|
title: item.title,
|
|
path: `/search/${item.handle}`
|
|
})
|
|
);
|
|
}
|
|
|
|
return listItem;
|
|
}
|
|
|
|
export function transformProducts(res: ApiSchemas['ProductListingResult']): Product[] {
|
|
let products: Product[] = [];
|
|
|
|
if (res.elements && res.elements.length > 0) {
|
|
res.elements.map((item) => products.push(transformProduct(item)));
|
|
}
|
|
|
|
return products;
|
|
}
|
|
|
|
export function transformProduct(item: ApiSchemas['Product']): Product {
|
|
const productOptions = transformOptions(item);
|
|
const productVariants = transformVariants(item);
|
|
|
|
return {
|
|
id: item.id ?? '',
|
|
path:
|
|
item.seoUrls && item.seoUrls.length > 0 && item.seoUrls[0] && item.seoUrls[0].seoPathInfo
|
|
? item.seoUrls[0].seoPathInfo
|
|
: '',
|
|
availableForSale: item.available ?? false,
|
|
title: item.translated ? item.translated.name ?? '' : item.name,
|
|
description: item.translated?.metaDescription
|
|
? item.translated.metaDescription ?? ''
|
|
: item.metaDescription ?? '',
|
|
descriptionHtml: item.translated?.description
|
|
? item.translated.description ?? ''
|
|
: item.description ?? '',
|
|
options: productOptions,
|
|
priceRange: {
|
|
maxVariantPrice: {
|
|
amount: item.calculatedPrice?.totalPrice ? String(item.calculatedPrice?.totalPrice) : '0',
|
|
currencyCode: 'EUR'
|
|
},
|
|
minVariantPrice: {
|
|
amount: item.calculatedCheapestPrice?.totalPrice
|
|
? String(item.calculatedPrice?.totalPrice)
|
|
: '0',
|
|
currencyCode: 'EUR'
|
|
}
|
|
},
|
|
variants: productVariants,
|
|
featuredImage: {
|
|
url: item.cover?.media?.url ?? '',
|
|
altText: item.cover?.media?.translated?.alt ?? '',
|
|
width: item.cover?.media?.metaData?.width ? Number(item.cover?.media?.metaData?.width) : 0,
|
|
height: item.cover?.media?.metaData?.width ? Number(item.cover?.media?.metaData?.height) : 0
|
|
},
|
|
images: item.media
|
|
? item.media.map((img) => ({
|
|
url: img.media?.url ?? '',
|
|
altText: img.media?.translated?.alt ?? '',
|
|
width: img.media?.metaData?.width ? Number(img.media?.metaData?.width) : 0,
|
|
height: img.media?.metaData?.width ? Number(img.media?.metaData?.height) : 0
|
|
}))
|
|
: [],
|
|
seo: {
|
|
title: item.translated?.metaTitle ?? item.translated?.name ?? item.name ?? '',
|
|
description: item.translated?.metaDescription ?? ''
|
|
},
|
|
tags: [''], // @ToDo: Add keywords or do we have tags?
|
|
updatedAt: item.updatedAt ?? ''
|
|
};
|
|
}
|
|
|
|
function transformOptions(parent: ApiSchemas['Product']): ProductOption[] {
|
|
// we only transform options for parents with children, ignore child products with options
|
|
let productOptions: ProductOption[] = [];
|
|
if (parent.children && parent.parentId === null && parent.children.length > 0) {
|
|
let group: { [key: string]: string[] } = {};
|
|
parent.children.map((child) => {
|
|
child.options?.map((option) => {
|
|
if (option && option.group) {
|
|
group[option.group.name] = group[option.group.name]
|
|
? [...new Set([...(group[option.group.name] as []), ...[option.name]])]
|
|
: [option.name];
|
|
}
|
|
});
|
|
});
|
|
|
|
if (parent.id) {
|
|
for (const [key, value] of Object.entries(group)) {
|
|
productOptions.push({
|
|
id: parent.id,
|
|
name: key,
|
|
values: value
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
return productOptions;
|
|
}
|
|
|
|
function transformVariants(parent: ApiSchemas['Product']): ProductVariant[] {
|
|
let productVariants: ProductVariant[] = [];
|
|
if (parent.children && parent.parentId === null && parent.children.length > 0) {
|
|
parent.children.map((child) => {
|
|
if (child.id) {
|
|
let selectedOptions: { name: string; value: string }[] = [];
|
|
child.options?.map((option) => {
|
|
if (option.group) {
|
|
selectedOptions.push({
|
|
name: option.group.name,
|
|
value: option.name
|
|
});
|
|
}
|
|
});
|
|
const currentVariant: ProductVariant = {
|
|
id: child.id,
|
|
title: child.name,
|
|
availableForSale: child.available ?? false,
|
|
selectedOptions: selectedOptions,
|
|
price: {
|
|
amount: child.calculatedPrice?.totalPrice
|
|
? String(child.calculatedPrice?.totalPrice)
|
|
: '0',
|
|
currencyCode: 'EUR'
|
|
}
|
|
};
|
|
|
|
productVariants.push(currentVariant);
|
|
}
|
|
});
|
|
}
|
|
|
|
return productVariants;
|
|
}
|