Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(RSS-ECOMM-5_96): update requests #355

Merged
merged 5 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion src/shared/API/discount/DiscountApi.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import type { ClientResponse, DiscountCodePagedQueryResponse } from '@commercetools/platform-sdk';
import type {
ClientResponse,
DiscountCodePagedQueryResponse,
ProductDiscountPagedQueryResponse,
} from '@commercetools/platform-sdk';

import getApiClient, { type ApiClient } from '../sdk/client.ts';

Expand All @@ -13,6 +17,11 @@ export class DiscountApi {
const data = await this.client.apiRoot().discountCodes().get().execute();
return data;
}

public async getDiscounts(): Promise<ClientResponse<ProductDiscountPagedQueryResponse>> {
const data = await this.client.apiRoot().productDiscounts().get().execute();
return data;
}
}

const createDiscountApi = (): DiscountApi => new DiscountApi();
Expand Down
40 changes: 38 additions & 2 deletions src/shared/API/discount/model/DiscountModel.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
import type { Coupon } from '@/shared/types/cart.ts';
import type { ClientResponse, DiscountCode, DiscountCodePagedQueryResponse } from '@commercetools/platform-sdk';
import type { Category } from '@/shared/types/product.ts';
import type {
ClientResponse,
DiscountCode,
DiscountCodePagedQueryResponse,
ProductDiscountPagedQueryResponse,
} from '@commercetools/platform-sdk';

import { showErrorMessage } from '@/shared/utils/userMessage.ts';

import { isClientResponse, isDiscountCodePagedQueryResponse } from '../../types/validation.ts';
import getProductModel from '../../product/model/ProductModel.ts';
import {
isClientResponse,
isDiscountCodePagedQueryResponse,
isProductDiscountPagedQueryResponse,
} from '../../types/validation.ts';
import getDiscountApi, { type DiscountApi } from '../DiscountApi.ts';

export class DiscountModel {
Expand All @@ -23,6 +34,25 @@ export class DiscountModel {
};
}

private getCategorySaleFromData(
data: ClientResponse<ProductDiscountPagedQueryResponse>,
categories: Category[],
): Category[] {
const result: Category[] = [];
if (isClientResponse(data) && isProductDiscountPagedQueryResponse(data.body)) {
const allReferences = data.body.results.flatMap((result) => result.references);
allReferences.forEach((rule) => {
if (rule.typeId === 'category') {
const categorySale = categories.find((category) => category.id === rule.id);
if (categorySale) {
result.push(categorySale);
}
}
});
}
return result;
}

private getCouponsFromData(data: ClientResponse<DiscountCodePagedQueryResponse>): Coupon[] {
const coupons: Coupon[] = [];
if (isClientResponse(data) && isDiscountCodePagedQueryResponse(data.body)) {
Expand All @@ -42,6 +72,12 @@ export class DiscountModel {
public getAllCoupons(): Coupon[] {
return this.coupons;
}

public async getCategorySales(): Promise<Category[]> {
const data = await this.root.getDiscounts();
const categories = await getProductModel().getCategories();
return this.getCategorySaleFromData(data, categories);
}
}

const createDiscountModel = (): DiscountModel => new DiscountModel();
Expand Down
23 changes: 12 additions & 11 deletions src/shared/API/product/ProductApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import type {
ProductProjectionPagedSearchResponse,
} from '@commercetools/platform-sdk';

import { DEFAULT_PAGE, MAX_PRICE, MIN_PRICE, PRICE_FRACTIONS, PRODUCT_LIMIT } from '@/shared/constants/product.ts';
import { DEFAULT_PAGE, MAX_PRICE, MIN_PRICE, PRODUCT_LIMIT } from '@/shared/constants/product.ts';

import type { OptionsRequest, PriceRange } from '../types/type.ts';

import getApiClient, { type ApiClient } from '../sdk/client.ts';
import { type OptionsRequest } from '../types/type.ts';
import { getDefaultPriceRange } from './utils/filter.ts';
import makeSortRequest from './utils/sort.ts';

const Search = 'text';
const FACET_ADD = 1;
enum Facets {
category = 'categories.id counting products',
price = 'variants.price.centAmount',
Expand Down Expand Up @@ -63,25 +64,25 @@ export class ProductApi {
return data;
}

public async getProducts(options?: OptionsRequest): Promise<ClientResponse<ProductProjectionPagedSearchResponse>> {
public async getProducts(
options?: OptionsRequest,
productsPriceRange?: PriceRange,
): Promise<ClientResponse<ProductProjectionPagedSearchResponse>> {
const { filter, limit = PRODUCT_LIMIT, page = DEFAULT_PAGE, search, sort } = options || {};
const filterQuery = filter?.getFilter();
const priceRange = filter?.getPriceRange();
const min = Math.round((priceRange?.min ?? MIN_PRICE) * PRICE_FRACTIONS - FACET_ADD);
const max = Math.round((priceRange?.max ?? MAX_PRICE) * PRICE_FRACTIONS + FACET_ADD);
const filterQuery = filter?.getFilter(productsPriceRange);
const priceRange = filter ? filter.getPriceRange(productsPriceRange) : getDefaultPriceRange();
const fuzzyLevel = this.getFuzzyLevel(search?.value ? search?.value : '');

const data = await this.client
.apiRoot()
.productProjections()
.search()
.get({
queryArgs: {
facet: [Facets.category, Facets.size, `${Facets.price}:${QueryParams.range}(${min} to ${max})`],
facet: [Facets.category, Facets.size, priceRange],
limit,
markMatchingVariants: true,
offset: (page - 1) * PRODUCT_LIMIT,
...(search && { [`${Search}.${search.locale}`]: search.value }),
...(search && { [`${Search}.${search.locale}`]: `*${search.value}*` }),
...(search && { fuzzy: true }),
...(search?.value && { fuzzyLevel }),
...(sort && { sort: makeSortRequest(sort) }),
Expand Down
14 changes: 13 additions & 1 deletion src/shared/API/product/model/ProductModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ enum ProductConstant {
export class ProductModel {
private categories: Category[] = [];

private priceRange: PriceRange = {
max: 0,
min: 0,
};

private root: ProductApi;

constructor() {
Expand Down Expand Up @@ -268,6 +273,9 @@ export class ProductModel {
});
}
}
if (this.priceRange.min === 0 && this.priceRange.max === 0) {
this.priceRange = priceRange;
}
return priceRange;
}

Expand Down Expand Up @@ -395,7 +403,7 @@ export class ProductModel {

public async getProducts(options?: OptionsRequest): Promise<ProductWithCount> {
await getProductModel().getCategories();
const data = await this.root.getProducts(options);
const data = await this.root.getProducts(options, this.priceRange);
const products = this.getProductsFromData(data);
if (options?.sort) {
this.sortVariants(products, options?.sort);
Expand All @@ -413,6 +421,10 @@ export class ProductModel {
};
return result;
}

public getProductsPriceRange(): PriceRange {
return this.priceRange;
}
}

const createProductModel = (): ProductModel => new ProductModel();
Expand Down
24 changes: 16 additions & 8 deletions src/shared/API/product/utils/filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ export default class FilterProduct {
private newArrival = '';

private price: PriceRange = {
max: MAX_PRICE,
min: MIN_PRICE,
max: 0,
min: 0,
};

private sale = '';
Expand Down Expand Up @@ -55,7 +55,7 @@ export default class FilterProduct {
return this.getFilter();
}

public getFilter(): string[] {
public getFilter(productsPriceRange?: PriceRange): string[] {
const result = [];
if (this.id.length) {
result.push(`${FilterFields.ID}:${this.id.map((id) => `"${id}"`).join(',')}`);
Expand All @@ -70,17 +70,25 @@ export default class FilterProduct {
result.push(this.newArrival);
}
if (this.price) {
result.push(
`${FilterFields.PRICE}: range(${Math.round(this.price.min * PRICE_FRACTIONS)} to ${Math.round(this.price.max * PRICE_FRACTIONS)})`,
);
result.push(this.getPriceRange(productsPriceRange));
}
if (this.sale) {
result.push(this.sale);
}
return result;
}

public getPriceRange(): PriceRange {
return this.price;
public getPriceRange(productsPriceRange?: PriceRange): string {
const min = Math.round(this.price.min * PRICE_FRACTIONS);
const max =
this.price.max && productsPriceRange && this.price.max !== productsPriceRange.max
? Math.round(this.price.max * PRICE_FRACTIONS)
: MAX_PRICE;

return `${FilterFields.PRICE}: range(${min} to ${max})`;
}
}

export function getDefaultPriceRange(): string {
return `${FilterFields.PRICE}: range(${MIN_PRICE} to ${MAX_PRICE})`;
}
39 changes: 35 additions & 4 deletions src/shared/API/shopping-list/ShoppingListApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import type {
ShoppingListSetAnonymousIdAction,
} from '@commercetools/platform-sdk';

import { DEFAULT_PAGE, PRODUCT_LIMIT } from '@/shared/constants/product.ts';

import type { OptionsRequest } from '../types/type.ts';

import makeSortRequest from '../product/utils/sort.ts';
import getApiClient, { type ApiClient } from '../sdk/client.ts';

export class ShoppingListApi {
Expand Down Expand Up @@ -92,13 +97,39 @@ export class ShoppingListApi {
return data;
}

public async get(): Promise<ClientResponse<ShoppingListPagedQueryResponse>> {
const data = await this.client.apiRoot().me().shoppingLists().get().execute();
public async get(options?: OptionsRequest): Promise<ClientResponse<ShoppingListPagedQueryResponse>> {
const { limit = PRODUCT_LIMIT, page = DEFAULT_PAGE, sort } = options || {};
const data = await this.client
.apiRoot()
.me()
.shoppingLists()
.get({
queryArgs: {
limit,
offset: (page - 1) * PRODUCT_LIMIT,
...(sort && { sort: makeSortRequest(sort) }),
withTotal: true,
},
})
.execute();
return data;
}

public async getAnonymList(ID: string): Promise<ClientResponse<ShoppingListResponse>> {
const data = await this.client.apiRoot().shoppingLists().withId({ ID }).get().execute();
public async getAnonymList(ID: string, options?: OptionsRequest): Promise<ClientResponse<ShoppingListResponse>> {
const { limit = PRODUCT_LIMIT, page = DEFAULT_PAGE, sort } = options || {};
const data = await this.client
.apiRoot()
.shoppingLists()
.withId({ ID })
.get({
queryArgs: {
limit,
offset: (page - 1) * PRODUCT_LIMIT,
...(sort && { sort: makeSortRequest(sort) }),
withTotal: true,
},
})
.execute();
return data;
}

Expand Down
19 changes: 12 additions & 7 deletions src/shared/API/shopping-list/model/ShoppingListModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import getStore from '@/shared/Store/Store.ts';
import { setAnonymousId, setAnonymousShopListId } from '@/shared/Store/actions.ts';
import { showErrorMessage } from '@/shared/utils/userMessage.ts';

import type { OptionsRequest } from '../../types/type.ts';

import {
isClientResponse,
isErrorResponse,
Expand Down Expand Up @@ -66,8 +68,11 @@ export class ShoppingListModel {
};
}

private async getAnonymousShoppingList(anonymousShopListId: string): Promise<ShoppingList | null> {
const dataAnonymList = await this.root.getAnonymList(anonymousShopListId);
private async getAnonymousShoppingList(
anonymousShopListId: string,
options?: OptionsRequest,
): Promise<ShoppingList | null> {
const dataAnonymList = await this.root.getAnonymList(anonymousShopListId, options);
const anonymShoppingList = this.getShopListFromData(dataAnonymList);
if (anonymShoppingList.id && !dataAnonymList.body.customer?.id) {
this.shoppingList = anonymShoppingList;
Expand All @@ -94,8 +99,8 @@ export class ShoppingListModel {
return cart;
}

private async getUserShoppingLists(): Promise<ShoppingList> {
const data = await this.root.get();
private async getUserShoppingLists(options?: OptionsRequest): Promise<ShoppingList> {
const data = await this.root.get(options);
if (data.body.count === 0) {
const newShopList = await this.root.create();
this.shoppingList = this.getShopListFromData(newShopList);
Expand Down Expand Up @@ -183,14 +188,14 @@ export class ShoppingListModel {
return this.shoppingList;
}

public async getShoppingList(): Promise<ShoppingList> {
public async getShoppingList(options?: OptionsRequest): Promise<ShoppingList> {
if (!this.shoppingList) {
const { anonymousId, anonymousShopListId } = getStore().getState();
if (anonymousShopListId && anonymousId) {
this.shoppingList = await this.getAnonymousShoppingList(anonymousShopListId);
this.shoppingList = await this.getAnonymousShoppingList(anonymousShopListId, options);
}
if (!this.shoppingList) {
this.shoppingList = await this.getUserShoppingLists();
this.shoppingList = await this.getUserShoppingLists(options);
}
}
return this.shoppingList;
Expand Down
16 changes: 16 additions & 0 deletions src/shared/API/types/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type {
FacetTerm,
LocalizedString,
Product,
ProductDiscountPagedQueryResponse,
ProductPagedQueryResponse,
ProductProjection,
ProductProjectionPagedQueryResponse,
Expand Down Expand Up @@ -314,3 +315,18 @@ export function isDiscountCodePagedQueryResponse(data: unknown): data is Discoun
Array.isArray(data.results),
);
}

export function isProductDiscountPagedQueryResponse(data: unknown): data is ProductDiscountPagedQueryResponse {
return Boolean(
typeof data === 'object' &&
data &&
'count' in data &&
typeof data.count === 'number' &&
'limit' in data &&
typeof data.limit === 'number' &&
'total' in data &&
typeof data.total === 'number' &&
'results' in data &&
Array.isArray(data.results),
);
}
2 changes: 1 addition & 1 deletion src/shared/constants/product.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export const PRICE_FRACTIONS = 100;
export const PRODUCT_LIMIT = 9;
export const DEFAULT_PAGE = 1;
export const MIN_PRICE = 0;
export const MAX_PRICE = 1000000;
export const MAX_PRICE = '*';
export const CURRENCY = 'USD';

export const EMPTY_PRODUCT = {
Expand Down
5 changes: 3 additions & 2 deletions src/widgets/Catalog/model/CatalogModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,15 +169,16 @@ class CatalogModel {
if (currentSort) {
result = {
filter,

page: Number(params.page),
search: { locale: currentLanguage, value: params.searchValue },
search: params.searchValue ? { locale: currentLanguage, value: params.searchValue } : null,
sort: currentSort ?? null,
};
} else {
result = {
filter,
page: Number(params.page),
search: { locale: currentLanguage, value: params.searchValue },
search: params.searchValue ? { locale: currentLanguage, value: params.searchValue } : null,
};
}

Expand Down