Skip to content
This repository has been archived by the owner on Dec 8, 2023. It is now read-only.

Commit

Permalink
feat: move filtered quickstarts to hook
Browse files Browse the repository at this point in the history
  • Loading branch information
josephgregoryii committed Jul 12, 2022
1 parent 5060c4a commit dc1ca46
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 92 deletions.
136 changes: 136 additions & 0 deletions src/hooks/useFilteredQuickstarts.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import React, { useEffect, useState, useRef } from 'react';
import CATEGORIES from '@data/instant-observability-categories';
import useSearchAndCategory from '@hooks/useSearchAndCategory';

/**
* Callback function for alphabetical sort.
* @param {Object} quickstart node
* @param {Object} quickstart node
*/
const alphaSort = (a, b) => a.title.localeCompare(b.title);

/**
* Curried function for filtering by keyword
* @param {Array} array of quickstarts
* @param {(Function) => Array} Callback function that filters quickstart array
*/
const filterQuickstarts = (quickstarts) => (keyword) =>
quickstarts.filter((product) => product.keywords.includes(keyword));

/**
* Custom hook to get filtered quickstarts
* @param {Array} array of quickstarts
*/
const useFilteredQuickstarts = (quickstarts, search, category) => {
const filterQuickstartsByKeyword = filterQuickstarts(quickstarts);
const featuredQuickstarts = filterQuickstartsByKeyword('featured');
const mostPopularQuickstarts = filterQuickstartsByKeyword('most popular');
const alphaSortedQuickstarts = quickstarts.sort(alphaSort);

const [sortedQuickstarts, setSortedQuickstarts] = useState(
alphaSortedQuickstarts
);

const [filteredQuickstarts, setFilteredQuickstarts] = useState(
sortedQuickstarts
);
const [categoriesWithCount, setCategoriesWithCount] = useState(
sortedQuickstarts
);

useEffect(() => {
/**
* Determines if one string is a substring of the other, case insensitive
* @param {String} substring the substring to test against
* @returns {(Function) => Boolean} Callback function that determines if the argument has the substring
*/
const stringIncludes = (substring) => (fullstring) =>
fullstring.toLowerCase().includes(substring.toLowerCase());

/**
* Filters a quickstart based on a provided search term.
* @param {String} search Search term.
* @returns {(Function) => Boolean} Callback function to be used by filter.
*/
const filterBySearch = (search) => ({
title,
summary,
description,
keywords,
}) => {
if (!search) {
return true;
}

const searchIncludes = stringIncludes(search);
return (
searchIncludes(title) ||
searchIncludes(summary) ||
searchIncludes(description) ||
keywords.some(searchIncludes)
);
};

/**
* Filters a quickstart based on a category.
* @param {String} category The category type (e.g. 'featured').
* @returns {(Function) => Boolean} Callback function to be used by filter.
*/
const filterByCategory = (category) => {
const { associatedKeywords = [] } =
CATEGORIES.find(({ value }) => value === category) || {};

return (quickstart) =>
!category ||
(quickstart.keywords &&
quickstart.keywords.find((k) => associatedKeywords.includes(k)));
};

setFilteredQuickstarts(
sortedQuickstarts
.filter(filterBySearch(search))
.filter(filterByCategory(category))
);

setCategoriesWithCount(() =>
CATEGORIES.map((cat) => ({
...cat,
count: sortedQuickstarts
.filter(filterBySearch(search))
.filter(filterByCategory(cat.value)).length,
}))
);

// shifts the codestream quickstart to the front
// if it is included in the filtered quickstarts
const shiftCodestream = () => {
// Hard-code for moving codestream object to front of sortedQuickstarts array
// hardcoded codestream uuid
const codestreamIndex = sortedQuickstarts.findIndex(
({ id }) => id === '29bd9a4a-1c19-4219-9694-0942f6411ce7'
);
if (codestreamIndex > -1) {
const codestreamObject = sortedQuickstarts[codestreamIndex];
setSortedQuickstarts((sq) => [
codestreamObject,
...sq.slice(0, codestreamIndex),
...sq.slice(codestreamIndex + 1),
]);
}
};

if ((!category && !search) || (category === 'featured' && !search)) {
shiftCodestream();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [search, category]);

return {
featuredQuickstarts,
filteredQuickstarts,
mostPopularQuickstarts,
categoriesWithCount,
};
};

export default useFilteredQuickstarts;
102 changes: 10 additions & 92 deletions src/pages/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import React, { useEffect, useState } from 'react';

import CATEGORIES from '@data/instant-observability-categories';
import useSearchAndCategory from '@hooks/useSearchAndCategory';
import useFilteredQuickstarts from '@hooks/useFilteredQuickstarts';
import IOBanner from '@components/IOBanner';
import IOSeo from '@components/IOSeo';
import Overlay from '@components/Overlay';
Expand All @@ -26,53 +27,6 @@ const DOUBLE_COLUMN_BREAKPOINT = '1180px';
const SINGLE_COLUMN_BREAKPOINT = '900px';
const COLUMN_BREAKPOINT = '1131px';

/**
* Determines if one string is a substring of the other, case insensitive
* @param {String} substring the substring to test against
* @returns {(Function) => Boolean} Callback function that determines if the argument has the substring
*/
const stringIncludes = (substring) => (fullstring) =>
fullstring.toLowerCase().includes(substring.toLowerCase());

/**
* Filters a quickstart based on a provided search term.
* @param {String} search Search term.
* @returns {(Function) => Boolean} Callback function to be used by filter.
*/
const filterBySearch = (search) => ({
title,
summary,
description,
keywords,
}) => {
if (!search) {
return true;
}

const searchIncludes = stringIncludes(search);
return (
searchIncludes(title) ||
searchIncludes(summary) ||
searchIncludes(description) ||
keywords.some(searchIncludes)
);
};

/**
* Filters a quickstart based on a category.
* @param {String} category The category type (e.g. 'featured').
* @returns {(Function) => Boolean} Callback function to be used by filter.
*/
const filterByCategory = (category) => {
const { associatedKeywords = [] } =
CATEGORIES.find(({ value }) => value === category) || {};

return (quickstart) =>
!category ||
(quickstart.keywords &&
quickstart.keywords.find((k) => associatedKeywords.includes(k)));
};

const QuickstartsPage = ({ data, location }) => {
const {
search,
Expand All @@ -81,6 +35,12 @@ const QuickstartsPage = ({ data, location }) => {
handleParam,
clearParam,
} = useSearchAndCategory(location);
const {
featuredQuickstarts,
filteredQuickstarts,
mostPopularQuickstarts,
categoriesWithCount,
} = useFilteredQuickstarts(data.allQuickstarts.nodes, search, category);

const [isCategoriesOverlayOpen, setIsCategoriesOverlayOpen] = useState(false);
// variable to check if the page load completed
Expand All @@ -95,48 +55,6 @@ const QuickstartsPage = ({ data, location }) => {
setIsCategoriesOverlayOpen(false);
};

const quickstarts = data.allQuickstarts.nodes;

const featuredQuickStarts = quickstarts?.filter((product) =>
product.keywords.includes('featured')
);

const mostPopularQuickStarts = quickstarts?.filter((product) =>
product.keywords.includes('most popular')
);

const alphaSort = quickstarts.sort((a, b) => a.title.localeCompare(b.title));
// let sortedQuickstarts = sortFeaturedQuickstarts(alphaSort);
let sortedQuickstarts = alphaSort;

// Hard-code for moving codestream object to front of sortedQuickstarts array - CM
if ((!category && !search) || (category === 'featured' && !search)) {
// uuid is codestream id specifically - CM
const codestreamIndex = sortedQuickstarts.findIndex(
({ id }) => id === '29bd9a4a-1c19-4219-9694-0942f6411ce7'
);

if (codestreamIndex > -1) {
const codestreamObject = sortedQuickstarts[codestreamIndex];
sortedQuickstarts = [
codestreamObject,
...sortedQuickstarts.slice(0, codestreamIndex),
...sortedQuickstarts.slice(codestreamIndex + 1),
];
}
}

const filteredQuickstarts = sortedQuickstarts
.filter(filterBySearch(search))
.filter(filterByCategory(category));

const categoriesWithCount = CATEGORIES.map((cat) => ({
...cat,
count: quickstarts
.filter(filterBySearch(search))
.filter(filterByCategory(cat.value)).length,
}));

/**
* Finds display name for selected category.
* @returns {String} Display name for results found.
Expand Down Expand Up @@ -531,7 +449,7 @@ const QuickstartsPage = ({ data, location }) => {

{!category && !search && (
<>
{mostPopularQuickStarts.length > 0 && (
{mostPopularQuickstarts.length > 0 && (
<>
<div
css={css`
Expand Down Expand Up @@ -569,7 +487,7 @@ const QuickstartsPage = ({ data, location }) => {
`}
>
<SuperTiles />
{mostPopularQuickStarts.map((pack) => (
{mostPopularQuickstarts.map((pack) => (
<QuickstartTile
key={pack.id}
featured={false}
Expand Down Expand Up @@ -614,7 +532,7 @@ const QuickstartsPage = ({ data, location }) => {
{!loadComplete && <Spinner />}
{loadComplete && (
<Slider {...settings}>
{featuredQuickStarts.map((pack) => (
{featuredQuickstarts.map((pack) => (
<QuickstartTile
key={pack.id}
featured={false}
Expand Down

0 comments on commit dc1ca46

Please sign in to comment.