mirror of
https://github.com/vercel/commerce.git
synced 2025-05-15 05:56:59 +00:00
feat(poc): fix type errors in transform, add simple sitemap
This commit is contained in:
parent
9c89c36008
commit
1cdb5d3343
@ -1,4 +1,4 @@
|
|||||||
import { getCollections, getPages, getProducts } from 'lib/shopify';
|
import { getProductSeoUrls } from 'lib/shopware';
|
||||||
import { MetadataRoute } from 'next';
|
import { MetadataRoute } from 'next';
|
||||||
|
|
||||||
const baseUrl = process.env.NEXT_PUBLIC_VERCEL_URL
|
const baseUrl = process.env.NEXT_PUBLIC_VERCEL_URL
|
||||||
@ -11,29 +11,16 @@ export default async function sitemap(): Promise<Promise<Promise<MetadataRoute.S
|
|||||||
lastModified: new Date().toISOString()
|
lastModified: new Date().toISOString()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const collectionsPromise = getCollections().then((collections) =>
|
// @ToDo: Get categories and get cms pages
|
||||||
collections.map((collection) => ({
|
const productsPromise = getProductSeoUrls().then((products) =>
|
||||||
url: `${baseUrl}${collection.path}`,
|
|
||||||
lastModified: collection.updatedAt
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
|
|
||||||
const productsPromise = getProducts({}).then((products) =>
|
|
||||||
products.map((product) => ({
|
products.map((product) => ({
|
||||||
url: `${baseUrl}/product/${product.handle}`,
|
url: `${baseUrl}/product/${product.path}`,
|
||||||
lastModified: product.updatedAt
|
lastModified: product.updatedAt
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
const pagesPromise = getPages().then((pages) =>
|
|
||||||
pages.map((page) => ({
|
|
||||||
url: `${baseUrl}/${page.handle}`,
|
|
||||||
lastModified: page.updatedAt
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
|
|
||||||
const fetchedRoutes = (
|
const fetchedRoutes = (
|
||||||
await Promise.all([collectionsPromise, productsPromise, pagesPromise])
|
await Promise.all([productsPromise])
|
||||||
).flat();
|
).flat();
|
||||||
|
|
||||||
return [...routesMap, ...fetchedRoutes];
|
return [...routesMap, ...fetchedRoutes];
|
||||||
|
@ -1,17 +1,73 @@
|
|||||||
import { operations, operationPaths, components } from '@shopware/api-client/api-types';
|
import { operations, operationPaths, components } from '@shopware/api-client/api-types';
|
||||||
|
|
||||||
|
type schemas = components['schemas'];
|
||||||
type operationsWithoutOriginal = Omit<
|
type operationsWithoutOriginal = Omit<
|
||||||
operations,
|
operations,
|
||||||
'readProduct' | 'searchPage' | 'readProductListing'
|
| 'readCategory'
|
||||||
|
| 'readCategoryList'
|
||||||
|
| 'readNavigation'
|
||||||
|
| 'readProduct'
|
||||||
|
| 'readProductCrossSellings'
|
||||||
|
| 'readProductListing'
|
||||||
|
| 'searchPage'
|
||||||
>;
|
>;
|
||||||
export type extendedPaths = 'readProduct post /product' | operationPaths;
|
export type extendedPaths =
|
||||||
|
| 'readCategory post /category/{navigationId}?slots'
|
||||||
|
| 'readCategoryList post /category'
|
||||||
|
| 'readNavigation post /navigation/{activeId}/{rootId} sw-include-seo-urls'
|
||||||
|
| 'readProduct post /product'
|
||||||
|
| 'readProductCrossSellings post /product/{productId}/cross-selling'
|
||||||
|
| 'readProductListing post /product-listing/{categoryId}'
|
||||||
|
| 'searchPage post /search'
|
||||||
|
| operationPaths;
|
||||||
export type extendedOperations = operationsWithoutOriginal & {
|
export type extendedOperations = operationsWithoutOriginal & {
|
||||||
|
readCategory: extendedReadCategory;
|
||||||
|
readCategoryList: extendedReadCategoryList;
|
||||||
|
readNavigation: extendedReadNavigation;
|
||||||
readProduct: extendedReadProduct;
|
readProduct: extendedReadProduct;
|
||||||
searchPage: extendedSearchPage;
|
readProductCrossSellings: extendedReadProductCrossSellings;
|
||||||
readProductListing: extendedReadProductListing;
|
readProductListing: extendedReadProductListing;
|
||||||
|
searchPage: extendedSearchPage;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ExtendedCriteria = Omit<components['schemas']['Criteria'], 'filter'> & {
|
export type ExtendedCmsBlock = Omit<schemas['CmsBlock'], 'slots'> & {
|
||||||
|
slots?: schemas['CmsSlot'][];
|
||||||
|
};
|
||||||
|
export type ExtendedCmsSection = Omit<schemas['CmsSection'], 'blocks'> & {
|
||||||
|
blocks?: ExtendedCmsBlock[];
|
||||||
|
};
|
||||||
|
export type ExtendedCmsPage = Omit<schemas['CmsPage'], 'sections'> & {
|
||||||
|
sections?: ExtendedCmsSection[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ExtendedProduct = Omit<
|
||||||
|
schemas['Product'],
|
||||||
|
'children' | 'seoUrls' | 'options' | 'media'
|
||||||
|
> & {
|
||||||
|
children?: ExtendedProduct[];
|
||||||
|
seoUrls?: schemas['SeoUrl'][];
|
||||||
|
options?: schemas['PropertyGroupOption'][];
|
||||||
|
media?: schemas['ProductMedia'][];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ExtendedProductListingResult = Omit<schemas['ProductListingResult'], 'elements'> & {
|
||||||
|
elements?: ExtendedProduct[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ExtendedCrossSellingElementCollection = Omit<
|
||||||
|
schemas['CrossSellingElementCollection'],
|
||||||
|
'products'
|
||||||
|
> & {
|
||||||
|
products?: ExtendedProduct[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ExtendedCategory = Omit<schemas['Category'], 'children' | 'seoUrls' | 'cmsPage'> & {
|
||||||
|
children?: ExtendedCategory[];
|
||||||
|
seoUrls?: schemas['SeoUrl'][];
|
||||||
|
cmsPage?: ExtendedCmsPage;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ExtendedCriteria = Omit<schemas['Criteria'], 'filter'> & {
|
||||||
filter?: {
|
filter?: {
|
||||||
field: string;
|
field: string;
|
||||||
type: string;
|
type: string;
|
||||||
@ -30,8 +86,25 @@ type extendedReadProduct = {
|
|||||||
200: {
|
200: {
|
||||||
content: {
|
content: {
|
||||||
'application/json': {
|
'application/json': {
|
||||||
elements?: components['schemas']['Product'][];
|
elements?: ExtendedProduct[];
|
||||||
} & components['schemas']['EntitySearchResult'];
|
} & schemas['EntitySearchResult'];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type extendedReadProductCrossSellings = {
|
||||||
|
parameters: {
|
||||||
|
path: {
|
||||||
|
/** Product ID */
|
||||||
|
productId: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
responses: {
|
||||||
|
/** Found cross sellings */
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': ExtendedCrossSellingElementCollection
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -106,14 +179,93 @@ type extendedSearchPage = {
|
|||||||
/** Using the search parameter, the server performs a text search on all records based on their data model and weighting as defined in the entity definition using the SearchRanking flag. */
|
/** Using the search parameter, the server performs a text search on all records based on their data model and weighting as defined in the entity definition using the SearchRanking flag. */
|
||||||
search: string;
|
search: string;
|
||||||
} & ExtendedProductCriteria &
|
} & ExtendedProductCriteria &
|
||||||
components['schemas']['ProductListingFlags'];
|
schemas['ProductListingFlags'];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
responses: {
|
responses: {
|
||||||
/** Returns a product listing containing all products and additional fields to display a listing. */
|
/** Returns a product listing containing all products and additional fields to display a listing. */
|
||||||
200: {
|
200: {
|
||||||
content: {
|
content: {
|
||||||
'application/json': components['schemas']['ProductListingResult'];
|
'application/json': ExtendedProductListingResult;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type extendedReadNavigation = {
|
||||||
|
parameters: {
|
||||||
|
header?: {
|
||||||
|
/** Instructs Shopware to try and resolve SEO URLs for the given navigation item */
|
||||||
|
'sw-include-seo-urls'?: boolean;
|
||||||
|
};
|
||||||
|
path: {
|
||||||
|
/** Identifier of the active category in the navigation tree (if not used, just set to the same as rootId). */
|
||||||
|
activeId: string;
|
||||||
|
/** Identifier of the root category for your desired navigation tree. You can use it to fetch sub-trees of your navigation tree. */
|
||||||
|
rootId: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
requestBody: {
|
||||||
|
content: {
|
||||||
|
'application/json': ExtendedCriteria & {
|
||||||
|
/** Return the categories as a tree or as a flat list. */
|
||||||
|
buildTree?: unknown;
|
||||||
|
/** Determines the depth of fetched navigation levels. */
|
||||||
|
depth?: unknown;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
responses: {
|
||||||
|
/** All available navigations */
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': ExtendedCategory[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type extendedReadCategory = {
|
||||||
|
parameters: {
|
||||||
|
query?: {
|
||||||
|
/** Resolves only the given slot identifiers. The identifiers have to be seperated by a '|' character */
|
||||||
|
slots?: string;
|
||||||
|
};
|
||||||
|
path: {
|
||||||
|
/** Identifier of the category to be fetched */
|
||||||
|
navigationId: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
requestBody?: {
|
||||||
|
content: {
|
||||||
|
'application/json': ExtendedCriteria &
|
||||||
|
Omit<schemas['ProductListingCriteria'], 'filter'> &
|
||||||
|
ExtendedCriteria;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
responses: {
|
||||||
|
/** The loaded category with cms page */
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': ExtendedCategory;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type extendedReadCategoryList = {
|
||||||
|
requestBody?: {
|
||||||
|
content: {
|
||||||
|
'application/json': ExtendedCriteria;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
responses: {
|
||||||
|
/** Entity search result containing categories. */
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
elements?: ExtendedCategory[];
|
||||||
|
} & components['schemas']['EntitySearchResult'];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -128,14 +280,14 @@ type extendedReadProductListing = {
|
|||||||
};
|
};
|
||||||
requestBody?: {
|
requestBody?: {
|
||||||
content: {
|
content: {
|
||||||
'application/json': ExtendedProductCriteria & components['schemas']['ProductListingFlags'];
|
'application/json': ExtendedProductCriteria & schemas['ProductListingFlags'];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
responses: {
|
responses: {
|
||||||
/** Returns a product listing containing all products and additional fields to display a listing. */
|
/** Returns a product listing containing all products and additional fields to display a listing. */
|
||||||
200: {
|
200: {
|
||||||
content: {
|
content: {
|
||||||
'application/json': components['schemas']['ProductListingResult'];
|
'application/json': ExtendedProductListingResult;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
import { createAPIClient, RequestReturnType } from '@shopware/api-client';
|
import { createAPIClient, RequestReturnType } from '@shopware/api-client';
|
||||||
import { operations } from '@shopware/api-client/api-types';
|
import { operations } from '@shopware/api-client/api-types';
|
||||||
import { extendedPaths, extendedOperations } from './api-extended';
|
|
||||||
import {
|
import {
|
||||||
ApiSchemas,
|
ExtendedCategory,
|
||||||
|
ExtendedCriteria,
|
||||||
|
ExtendedCrossSellingElementCollection,
|
||||||
|
ExtendedProductListingResult,
|
||||||
|
extendedOperations,
|
||||||
|
extendedPaths
|
||||||
|
} from './api-extended';
|
||||||
|
import {
|
||||||
CategoryListingResultSW,
|
CategoryListingResultSW,
|
||||||
ProductListingCriteria,
|
ProductListingCriteria,
|
||||||
|
RouteNames,
|
||||||
SeoURLResultSW,
|
SeoURLResultSW,
|
||||||
StoreNavigationTypeSW
|
StoreNavigationTypeSW
|
||||||
} from './types';
|
} from './types';
|
||||||
@ -27,7 +34,7 @@ export type ApiReturnType<OPERATION_NAME extends keyof operations> = RequestRetu
|
|||||||
export async function requestNavigation(
|
export async function requestNavigation(
|
||||||
type: StoreNavigationTypeSW,
|
type: StoreNavigationTypeSW,
|
||||||
depth: number
|
depth: number
|
||||||
): Promise<ApiSchemas['NavigationRouteResponse']> {
|
): Promise<ExtendedCategory[]> {
|
||||||
return await apiInstance.invoke(
|
return await apiInstance.invoke(
|
||||||
'readNavigation post /navigation/{activeId}/{rootId} sw-include-seo-urls',
|
'readNavigation post /navigation/{activeId}/{rootId} sw-include-seo-urls',
|
||||||
{
|
{
|
||||||
@ -41,7 +48,7 @@ export async function requestNavigation(
|
|||||||
export async function requestCategory(
|
export async function requestCategory(
|
||||||
categoryId: string,
|
categoryId: string,
|
||||||
criteria?: Partial<ProductListingCriteria>
|
criteria?: Partial<ProductListingCriteria>
|
||||||
): Promise<ApiSchemas['Category']> {
|
): Promise<ExtendedCategory> {
|
||||||
return await apiInstance.invoke('readCategory post /category/{navigationId}?slots', {
|
return await apiInstance.invoke('readCategory post /category/{navigationId}?slots', {
|
||||||
navigationId: categoryId,
|
navigationId: categoryId,
|
||||||
criteria
|
criteria
|
||||||
@ -49,21 +56,21 @@ export async function requestCategory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function requestCategoryList(
|
export async function requestCategoryList(
|
||||||
criteria: Partial<ApiSchemas['Criteria']>
|
criteria: Partial<ExtendedCriteria>
|
||||||
): Promise<CategoryListingResultSW> {
|
): Promise<CategoryListingResultSW> {
|
||||||
return await apiInstance.invoke('readCategoryList post /category', criteria);
|
return await apiInstance.invoke('readCategoryList post /category', criteria);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function requestProductsCollection(
|
export async function requestProductsCollection(
|
||||||
criteria: Partial<ProductListingCriteria>
|
criteria: Partial<ProductListingCriteria>
|
||||||
): Promise<ApiSchemas['ProductListingResult']> {
|
): Promise<ExtendedProductListingResult> {
|
||||||
return await apiInstance.invoke('readProduct post /product', criteria);
|
return await apiInstance.invoke('readProduct post /product', criteria);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function requestCategoryProductsCollection(
|
export async function requestCategoryProductsCollection(
|
||||||
categoryId: string,
|
categoryId: string,
|
||||||
criteria: Partial<ProductListingCriteria>
|
criteria: Partial<ProductListingCriteria>
|
||||||
): Promise<ApiSchemas['ProductListingResult']> {
|
): Promise<ExtendedProductListingResult> {
|
||||||
return await apiInstance.invoke('readProductListing post /product-listing/{categoryId}', {
|
return await apiInstance.invoke('readProductListing post /product-listing/{categoryId}', {
|
||||||
...criteria,
|
...criteria,
|
||||||
categoryId: categoryId
|
categoryId: categoryId
|
||||||
@ -72,17 +79,35 @@ export async function requestCategoryProductsCollection(
|
|||||||
|
|
||||||
export async function requestSearchCollectionProducts(
|
export async function requestSearchCollectionProducts(
|
||||||
criteria?: Partial<ProductListingCriteria>
|
criteria?: Partial<ProductListingCriteria>
|
||||||
): Promise<ApiSchemas['ProductListingResult']> {
|
): Promise<ExtendedProductListingResult> {
|
||||||
return await apiInstance.invoke('searchPage post /search', {
|
return await apiInstance.invoke('searchPage post /search', {
|
||||||
search: encodeURIComponent(criteria?.query || ''),
|
search: encodeURIComponent(criteria?.query || ''),
|
||||||
...criteria
|
...criteria
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function requestSeoUrl(handle: string): Promise<SeoURLResultSW> {
|
export async function requestSeoUrls(routeName: RouteNames, page: number = 1, limit: number = 100) {
|
||||||
return await apiInstance.invoke('readSeoUrl post /seo-url', {
|
return await apiInstance.invoke('readSeoUrl post /seo-url', {
|
||||||
page: 1,
|
page: page,
|
||||||
limit: 1,
|
limit: limit,
|
||||||
|
filter: [
|
||||||
|
{
|
||||||
|
type: 'equals',
|
||||||
|
field: 'routeName',
|
||||||
|
value: routeName
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function requestSeoUrl(
|
||||||
|
handle: string,
|
||||||
|
page: number = 1,
|
||||||
|
limit: number = 1
|
||||||
|
): Promise<SeoURLResultSW> {
|
||||||
|
return await apiInstance.invoke('readSeoUrl post /seo-url', {
|
||||||
|
page: page,
|
||||||
|
limit: limit,
|
||||||
filter: [
|
filter: [
|
||||||
{
|
{
|
||||||
type: 'multi',
|
type: 'multi',
|
||||||
@ -108,7 +133,7 @@ export async function requestSeoUrl(handle: string): Promise<SeoURLResultSW> {
|
|||||||
export async function requestCrossSell(
|
export async function requestCrossSell(
|
||||||
productId: string,
|
productId: string,
|
||||||
criteria?: Partial<ProductListingCriteria>
|
criteria?: Partial<ProductListingCriteria>
|
||||||
): Promise<ApiSchemas['CrossSellingElementCollection']> {
|
): Promise<ExtendedCrossSellingElementCollection> {
|
||||||
return await apiInstance.invoke(
|
return await apiInstance.invoke(
|
||||||
'readProductCrossSellings post /product/{productId}/cross-selling',
|
'readProductCrossSellings post /product/{productId}/cross-selling',
|
||||||
{
|
{
|
||||||
|
@ -24,7 +24,8 @@ import {
|
|||||||
requestNavigation,
|
requestNavigation,
|
||||||
requestProductsCollection,
|
requestProductsCollection,
|
||||||
requestSearchCollectionProducts,
|
requestSearchCollectionProducts,
|
||||||
requestSeoUrl
|
requestSeoUrl,
|
||||||
|
requestSeoUrls
|
||||||
} from './api';
|
} from './api';
|
||||||
import {
|
import {
|
||||||
transformCollection,
|
transformCollection,
|
||||||
@ -35,6 +36,7 @@ import {
|
|||||||
transformProducts,
|
transformProducts,
|
||||||
transformStaticCollection
|
transformStaticCollection
|
||||||
} from './transform';
|
} from './transform';
|
||||||
|
import { ExtendedCategory, ExtendedProduct, ExtendedProductListingResult } from './api-extended';
|
||||||
|
|
||||||
export async function getMenu(params?: {
|
export async function getMenu(params?: {
|
||||||
type?: StoreNavigationTypeSW;
|
type?: StoreNavigationTypeSW;
|
||||||
@ -66,11 +68,9 @@ export async function getFirstSeoUrlElement(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getFirstProduct(
|
export async function getFirstProduct(productId: string): Promise<ExtendedProduct | undefined> {
|
||||||
productId: string
|
|
||||||
): Promise<ApiSchemas['Product'] | undefined> {
|
|
||||||
const productCriteria = getDefaultProductCriteria(productId);
|
const productCriteria = getDefaultProductCriteria(productId);
|
||||||
const res: ApiSchemas['ProductListingResult'] = await requestProductsCollection(productCriteria);
|
const res: ExtendedProductListingResult = await requestProductsCollection(productCriteria);
|
||||||
if (res.elements && res.elements.length > 0 && res.elements[0]) {
|
if (res.elements && res.elements.length > 0 && res.elements[0]) {
|
||||||
return res.elements[0];
|
return res.elements[0];
|
||||||
}
|
}
|
||||||
@ -142,7 +142,7 @@ export async function getCollectionProducts(params?: {
|
|||||||
export async function getCategory(
|
export async function getCategory(
|
||||||
seoUrl: ApiSchemas['SeoUrl'],
|
seoUrl: ApiSchemas['SeoUrl'],
|
||||||
cms: boolean = false
|
cms: boolean = false
|
||||||
): Promise<ApiSchemas['Category']> {
|
): Promise<ExtendedCategory> {
|
||||||
const criteria = cms ? getDefaultCategoryWithCmsCriteria() : getDefaultCategoryCriteria();
|
const criteria = cms ? getDefaultCategoryWithCmsCriteria() : getDefaultCategoryCriteria();
|
||||||
const resCategory = await requestCategory(seoUrl.foreignKey, criteria);
|
const resCategory = await requestCategory(seoUrl.foreignKey, criteria);
|
||||||
|
|
||||||
@ -165,8 +165,21 @@ export async function getCollection(handle: string | []) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getProductSeoUrls() {
|
||||||
|
const productSeoUrls: { path: string; updatedAt: string }[] = [];
|
||||||
|
const res = await requestSeoUrls('frontend.detail.page');
|
||||||
|
|
||||||
|
if (res.elements && res.elements.length > 0) {
|
||||||
|
res.elements.map((item) =>
|
||||||
|
productSeoUrls.push({ path: item.seoPathInfo, updatedAt: item.updatedAt ?? item.createdAt })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return productSeoUrls;
|
||||||
|
}
|
||||||
|
|
||||||
export async function getProduct(handle: string | []): Promise<Product | undefined> {
|
export async function getProduct(handle: string | []): Promise<Product | undefined> {
|
||||||
let productSW: ApiSchemas['Product'] | undefined;
|
let productSW: ExtendedProduct | undefined;
|
||||||
let productId: string | undefined;
|
let productId: string | undefined;
|
||||||
const productHandle = transformHandle(handle);
|
const productHandle = transformHandle(handle);
|
||||||
|
|
||||||
@ -189,11 +202,12 @@ export async function getProduct(handle: string | []): Promise<Product | undefin
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getProductRecommendations(productId: string): Promise<Product[]> {
|
export async function getProductRecommendations(productId: string): Promise<Product[]> {
|
||||||
let products: ApiSchemas['ProductListingResult'] = {};
|
let products: ExtendedProductListingResult = {};
|
||||||
|
|
||||||
const res = await requestCrossSell(productId, getDefaultCrossSellingCriteria());
|
const res = await requestCrossSell(productId, getDefaultCrossSellingCriteria());
|
||||||
// @ToDo: Make this more dynamic to merge multiple Cross-Sellings, at the moment we only get the first one
|
// @ToDo: Make this more dynamic to merge multiple Cross-Sellings, at the moment we only get the first one
|
||||||
if (res && res[0] && res[0].products) {
|
if (res && res[0] && res[0].products) {
|
||||||
|
// @ts-ignore (@ToDo: fix this wrong type ...)
|
||||||
products.elements = res[0].products;
|
products.elements = res[0].products;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,9 +8,15 @@ import {
|
|||||||
ProductOption,
|
ProductOption,
|
||||||
ProductVariant
|
ProductVariant
|
||||||
} from './types';
|
} from './types';
|
||||||
|
import {
|
||||||
|
ExtendedCategory,
|
||||||
|
ExtendedCmsPage,
|
||||||
|
ExtendedProduct,
|
||||||
|
ExtendedProductListingResult
|
||||||
|
} from './api-extended';
|
||||||
import { ListItem } from 'components/layout/search/filter';
|
import { ListItem } from 'components/layout/search/filter';
|
||||||
|
|
||||||
export function transformMenu(res: ApiSchemas['NavigationRouteResponse'], type: string) {
|
export function transformMenu(res: ExtendedCategory[], type: string) {
|
||||||
let menu: Menu[] = [];
|
let menu: Menu[] = [];
|
||||||
|
|
||||||
res.map((item) => menu.push(transformMenuItem(item, type)));
|
res.map((item) => menu.push(transformMenuItem(item, type)));
|
||||||
@ -18,7 +24,7 @@ export function transformMenu(res: ApiSchemas['NavigationRouteResponse'], type:
|
|||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
function transformMenuItem(item: ApiSchemas['Category'], type: string): Menu {
|
function transformMenuItem(item: ExtendedCategory, type: string): Menu {
|
||||||
// @ToDo: currently only footer-navigation is used for cms pages, this need to be more dynamic (shoud depending on the item)
|
// @ToDo: currently only footer-navigation is used for cms pages, this need to be more dynamic (shoud depending on the item)
|
||||||
return {
|
return {
|
||||||
id: item.id ?? '',
|
id: item.id ?? '',
|
||||||
@ -36,11 +42,11 @@ function transformMenuItem(item: ApiSchemas['Category'], type: string): Menu {
|
|||||||
|
|
||||||
export function transformPage(
|
export function transformPage(
|
||||||
seoUrlElement: ApiSchemas['SeoUrl'],
|
seoUrlElement: ApiSchemas['SeoUrl'],
|
||||||
category: ApiSchemas['Category']
|
category: ExtendedCategory
|
||||||
): Page {
|
): Page {
|
||||||
let plainHtmlContent;
|
let plainHtmlContent;
|
||||||
if (category.cmsPage) {
|
if (category.cmsPage) {
|
||||||
const cmsPage: ApiSchemas['CmsPage'] = category.cmsPage;
|
const cmsPage: ExtendedCmsPage = category.cmsPage;
|
||||||
plainHtmlContent = transformToPlainHtmlContent(cmsPage);
|
plainHtmlContent = transformToPlainHtmlContent(cmsPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +68,7 @@ export function transformPage(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function transformToPlainHtmlContent(cmsPage: ApiSchemas['CmsPage']): string {
|
export function transformToPlainHtmlContent(cmsPage: ExtendedCmsPage): string {
|
||||||
let plainHtmlContent = '';
|
let plainHtmlContent = '';
|
||||||
|
|
||||||
cmsPage.sections?.map((section) => {
|
cmsPage.sections?.map((section) => {
|
||||||
@ -84,7 +90,7 @@ export function transformToPlainHtmlContent(cmsPage: ApiSchemas['CmsPage']): str
|
|||||||
|
|
||||||
export function transformCollection(
|
export function transformCollection(
|
||||||
seoUrlElement: ApiSchemas['SeoUrl'],
|
seoUrlElement: ApiSchemas['SeoUrl'],
|
||||||
resCategory: ApiSchemas['Category']
|
resCategory: ExtendedCategory
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
handle: seoUrlElement.seoPathInfo,
|
handle: seoUrlElement.seoPathInfo,
|
||||||
@ -137,7 +143,7 @@ export function transformStaticCollectionToList(collection: Collection[]): ListI
|
|||||||
return listItem;
|
return listItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function transformProducts(res: ApiSchemas['ProductListingResult']): Product[] {
|
export function transformProducts(res: ExtendedProductListingResult): Product[] {
|
||||||
let products: Product[] = [];
|
let products: Product[] = [];
|
||||||
|
|
||||||
if (res.elements && res.elements.length > 0) {
|
if (res.elements && res.elements.length > 0) {
|
||||||
@ -147,7 +153,7 @@ export function transformProducts(res: ApiSchemas['ProductListingResult']): Prod
|
|||||||
return products;
|
return products;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function transformProduct(item: ApiSchemas['Product']): Product {
|
export function transformProduct(item: ExtendedProduct): Product {
|
||||||
const productOptions = transformOptions(item);
|
const productOptions = transformOptions(item);
|
||||||
const productVariants = transformVariants(item);
|
const productVariants = transformVariants(item);
|
||||||
|
|
||||||
@ -202,7 +208,7 @@ export function transformProduct(item: ApiSchemas['Product']): Product {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function transformOptions(parent: ApiSchemas['Product']): ProductOption[] {
|
function transformOptions(parent: ExtendedProduct): ProductOption[] {
|
||||||
// we only transform options for parents with children, ignore child products with options
|
// we only transform options for parents with children, ignore child products with options
|
||||||
let productOptions: ProductOption[] = [];
|
let productOptions: ProductOption[] = [];
|
||||||
if (parent.children && parent.parentId === null && parent.children.length > 0) {
|
if (parent.children && parent.parentId === null && parent.children.length > 0) {
|
||||||
@ -231,7 +237,7 @@ function transformOptions(parent: ApiSchemas['Product']): ProductOption[] {
|
|||||||
return productOptions;
|
return productOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
function transformVariants(parent: ApiSchemas['Product']): ProductVariant[] {
|
function transformVariants(parent: ExtendedProduct): ProductVariant[] {
|
||||||
let productVariants: ProductVariant[] = [];
|
let productVariants: ProductVariant[] = [];
|
||||||
if (parent.children && parent.parentId === null && parent.children.length > 0) {
|
if (parent.children && parent.parentId === null && parent.children.length > 0) {
|
||||||
parent.children.map((child) => {
|
parent.children.map((child) => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { components } from '@shopware/api-client/api-types';
|
import { components } from '@shopware/api-client/api-types';
|
||||||
import { ExtendedCriteria } from './api-extended';
|
import { ExtendedCriteria, ExtendedCategory, ExtendedCmsPage } from './api-extended';
|
||||||
|
|
||||||
/** Shopware Types */
|
/** Shopware Types */
|
||||||
|
|
||||||
@ -10,10 +10,11 @@ export type ProductListingCriteria = {
|
|||||||
query: string;
|
query: string;
|
||||||
} & Omit<ApiSchemas['ProductListingCriteria'], 'filter'> &
|
} & Omit<ApiSchemas['ProductListingCriteria'], 'filter'> &
|
||||||
ExtendedCriteria;
|
ExtendedCriteria;
|
||||||
|
export type RouteNames = 'frontend.navigation.page' | 'frontend.detail.page' | 'frontend.account.customer-group-registration.page' | 'frontend.landing.page'
|
||||||
|
|
||||||
/** Return Types */
|
/** Return Types */
|
||||||
export type CategoryListingResultSW = {
|
export type CategoryListingResultSW = {
|
||||||
elements?: ApiSchemas['Category'][];
|
elements?: ExtendedCategory[];
|
||||||
} & ApiSchemas['EntitySearchResult'];
|
} & ApiSchemas['EntitySearchResult'];
|
||||||
export type SeoURLResultSW = {
|
export type SeoURLResultSW = {
|
||||||
elements?: ApiSchemas['SeoUrl'][];
|
elements?: ApiSchemas['SeoUrl'][];
|
||||||
@ -33,7 +34,7 @@ export type Page = {
|
|||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
routeName?: string;
|
routeName?: string;
|
||||||
foreignKey?: string;
|
foreignKey?: string;
|
||||||
originalCmsPage?: ApiSchemas['CmsPage'];
|
originalCmsPage?: ExtendedCmsPage;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ProductOption = {
|
export type ProductOption = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user