Skip to content

Commit

Permalink
Allow passing pageOffSet as props to IS productListingPage (#61)
Browse files Browse the repository at this point in the history
* add verify

* remove format
  • Loading branch information
RafaelCassiano30011 authored Sep 19, 2023
1 parent cfa2e18 commit ee6ab02
Showing 1 changed file with 80 additions and 114 deletions.
194 changes: 80 additions & 114 deletions vtex/loaders/intelligentSearch/productListingPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,13 @@ import type { ProductListingPage } from "../../../commerce/types.ts";
import { parseRange } from "../../../commerce/utils/filters.ts";
import sendEvent from "../../actions/analytics/sendEvent.ts";
import { AppContext } from "../../mod.ts";
import {
toPath,
withDefaultFacets,
withDefaultParams,
} from "../../utils/intelligentSearch.ts";
import {
pageTypesFromPathname,
pageTypesToBreadcrumbList,
pageTypesToSeo,
} from "../../utils/legacy.ts";
import {
getSegment,
setSegment,
withSegmentCookie,
} from "../../utils/segment.ts";
import { toPath, withDefaultFacets, withDefaultParams } from "../../utils/intelligentSearch.ts";
import { pageTypesFromPathname, pageTypesToBreadcrumbList, pageTypesToSeo } from "../../utils/legacy.ts";
import { getSegment, setSegment, withSegmentCookie } from "../../utils/segment.ts";
import { withIsSimilarTo } from "../../utils/similars.ts";
import { slugify } from "../../utils/slugify.ts";
import {
filtersFromURL,
mergeFacets,
toFilter,
toProduct,
} from "../../utils/transform.ts";
import type {
Facet,
Fuzzy,
PageType,
RangeFacet,
SelectedFacet,
Sort,
} from "../../utils/types.ts";
import { filtersFromURL, mergeFacets, toFilter, toProduct } from "../../utils/transform.ts";
import type { Facet, Fuzzy, PageType, RangeFacet, SelectedFacet, Sort } from "../../utils/types.ts";

/** this type is more friendly user to fuzzy type that is 0, 1 or auto. */
export type LabelledFuzzy = "automatic" | "disabled" | "enabled";
Expand Down Expand Up @@ -64,9 +40,7 @@ const LEGACY_TO_IS: Record<string, Sort> = {
OrderByBestDiscountDESC: "discount:desc",
};

const mapLabelledFuzzyToFuzzy = (
labelledFuzzy?: LabelledFuzzy,
): Fuzzy | undefined => {
const mapLabelledFuzzyToFuzzy = (labelledFuzzy?: LabelledFuzzy): Fuzzy | undefined => {
switch (labelledFuzzy) {
case "automatic":
return "auto";
Expand Down Expand Up @@ -125,40 +99,33 @@ export interface Props {
}

// TODO (mcandeia) investigating bugs related to returning the same set of products but different queries.
const _singleFlightKey = (
props: Props,
{ request }: { request: Request },
) => {
const _singleFlightKey = (props: Props, { request }: { request: Request }) => {
const url = new URL(request.url);
const { query, count, sort, page, selectedFacets, fuzzy } = searchArgsOf(
props,
url,
);
return `${query}${count}${sort}${page}${fuzzy}${
selectedFacets.map((f) => `${f.key}${f.value}`).sort().join("")
}`;
const { query, count, sort, page, selectedFacets, fuzzy } = searchArgsOf(props, url);
return `${query}${count}${sort}${page}${fuzzy}${selectedFacets
.map((f) => `${f.key}${f.value}`)
.sort()
.join("")}`;
};

const searchArgsOf = (props: Props, url: URL) => {
const hideUnavailableItems = props.hideUnavailableItems;
const count = props.count ?? 12;
const query = props.query ?? url.searchParams.get("q") ?? "";
const currentPageoffset = props.pageOffset ?? 1;
const page = Math.min(
url.searchParams.get("page")
? Number(url.searchParams.get("page")) - currentPageoffset
: 0,
VTEX_MAX_PAGES - currentPageoffset,
);
const sort = url.searchParams.get("sort") as Sort ??
LEGACY_TO_IS[url.searchParams.get("O") ?? ""] ?? props.sort ??
const page =
props.pageOffset ??
Math.min(
url.searchParams.get("page") ? Number(url.searchParams.get("page")) - currentPageoffset : 0,
VTEX_MAX_PAGES - currentPageoffset
);
const sort =
(url.searchParams.get("sort") as Sort) ??
LEGACY_TO_IS[url.searchParams.get("O") ?? ""] ??
props.sort ??
sortOptions[0].value;
const selectedFacets = mergeFacets(
props.selectedFacets ?? [],
filtersFromURL(url),
);
const fuzzy = mapLabelledFuzzyToFuzzy(props.fuzzy) ??
url.searchParams.get("fuzzy") as Fuzzy;
const selectedFacets = mergeFacets(props.selectedFacets ?? [], filtersFromURL(url));
const fuzzy = mapLabelledFuzzyToFuzzy(props.fuzzy) ?? (url.searchParams.get("fuzzy") as Fuzzy);

return {
query,
Expand Down Expand Up @@ -198,10 +165,13 @@ const filtersFromPathname = (pages: PageType[]) =>
return;
}

return key && page.name && {
key,
value: slugify(page.name),
};
return (
key &&
page.name && {
key,
value: slugify(page.name),
}
);
})
.filter((facet): facet is { key: string; value: string } => Boolean(facet));

Expand Down Expand Up @@ -234,91 +204,87 @@ const selectPriceFacet = (facets: Facet[], selectedFacets: SelectedFacet[]) => {
* @title VTEX Integration - Intelligent Search
* @description Product Listing Page loader
*/
const loader = async (
props: Props,
req: Request,
ctx: AppContext,
): Promise<ProductListingPage | null> => {
const loader = async (props: Props, req: Request, ctx: AppContext): Promise<ProductListingPage | null> => {
const { vcs } = ctx;
const { url: baseUrl } = req;

const url = new URL(baseUrl);
const segment = getSegment(req);
const currentPageoffset = props.pageOffset ?? 1;
const {
selectedFacets: baseSelectedFacets,
page,
...args
} = searchArgsOf(props, url);
const { selectedFacets: baseSelectedFacets, page, ...args } = searchArgsOf(props, url);
const pageTypesPromise = pageTypesFromPathname(url.pathname, ctx);
const selectedFacets = baseSelectedFacets.length === 0
? filtersFromPathname(await pageTypesPromise)
: baseSelectedFacets;
const selectedFacets =
baseSelectedFacets.length === 0 ? filtersFromPathname(await pageTypesPromise) : baseSelectedFacets;

const selected = withDefaultFacets(selectedFacets, ctx);
const fselected = selected.filter((f) => f.key !== "price");
const params = withDefaultParams({ ...args, page });
// search products on VTEX. Feel free to change any of these parameters
const [productsResult, facetsResult] = await Promise.all([
vcs["GET /api/io/_v/api/intelligent-search/product_search/*facets"]({
...params,
facets: toPath(selected),
}, {
deco: { cache: "stale-while-revalidate" },
headers: withSegmentCookie(segment),
}).then((res) => res.json()),
vcs["GET /api/io/_v/api/intelligent-search/facets/*facets"]({
...params,
facets: toPath(fselected),
}, {
deco: { cache: "stale-while-revalidate" },
headers: withSegmentCookie(segment),
}).then((res) => res.json()),
vcs["GET /api/io/_v/api/intelligent-search/product_search/*facets"](
{
...params,
facets: toPath(selected),
},
{
deco: { cache: "stale-while-revalidate" },
headers: withSegmentCookie(segment),
}
).then((res) => res.json()),
vcs["GET /api/io/_v/api/intelligent-search/facets/*facets"](
{
...params,
facets: toPath(fselected),
},
{
deco: { cache: "stale-while-revalidate" },
headers: withSegmentCookie(segment),
}
).then((res) => res.json()),
]);

/** Intelligent search API analytics. Fire and forget 🔫 */
const fullTextTerm = params["query"];
if (fullTextTerm) {
sendEvent({ type: "session.ping" }, req, ctx).then(() =>
sendEvent(
{
type: "search.query",
text: fullTextTerm,
misspelled: productsResult.correction?.misspelled ?? false,
match: productsResult.recordsFiltered,
operator: productsResult.operator,
locale: "pt-BR", // config?.defaultLocale, // TODO
},
req,
ctx,
sendEvent({ type: "session.ping" }, req, ctx)
.then(() =>
sendEvent(
{
type: "search.query",
text: fullTextTerm,
misspelled: productsResult.correction?.misspelled ?? false,
match: productsResult.recordsFiltered,
operator: productsResult.operator,
locale: "pt-BR", // config?.defaultLocale, // TODO
},
req,
ctx
)
)
).catch(console.error);
.catch(console.error);
}

const { products: vtexProducts, pagination, recordsFiltered } =
productsResult;
const { products: vtexProducts, pagination, recordsFiltered } = productsResult;
const facets = selectPriceFacet(facetsResult.facets, selectedFacets);

// Transform VTEX product format into schema.org's compatible format
// If a property is missing from the final `products` array you can add
// it in here
const products = await Promise.all(
vtexProducts.map((p) =>
toProduct(p, p.items[0], 0, {
baseUrl: baseUrl,
priceCurrency: "BRL", // config!.defaultPriceCurrency, // TODO
})
).map((product) =>
props.similars ? withIsSimilarTo(req, ctx, product) : product
),
vtexProducts
.map((p) =>
toProduct(p, p.items[0], 0, {
baseUrl: baseUrl,
priceCurrency: "BRL", // config!.defaultPriceCurrency, // TODO
})
)
.map((product) => (props.similars ? withIsSimilarTo(req, ctx, product) : product))
);

const paramsToPersist = new URLSearchParams();
args.query && paramsToPersist.set("q", args.query);
args.sort && paramsToPersist.set("sort", args.sort);
const filters = facets.filter((f) => !f.hidden).map(
toFilter(selectedFacets, paramsToPersist),
);
const filters = facets.filter((f) => !f.hidden).map(toFilter(selectedFacets, paramsToPersist));
const pageTypes = await pageTypesPromise;
const itemListElement = pageTypesToBreadcrumbList(pageTypes, baseUrl);

Expand Down

0 comments on commit ee6ab02

Please sign in to comment.