Skip to content

Commit

Permalink
refactor: ♻️ Refactor useFilteredApps to have a better functional imp…
Browse files Browse the repository at this point in the history
…lementation

Replaced the iterative implementation of the useFilteredApps hook with a functional one using underscores.js's compose function.
  • Loading branch information
rique223 committed Sep 4, 2023
1 parent 42644a6 commit 4f2f252
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 64 deletions.
24 changes: 21 additions & 3 deletions apps/meteor/client/views/marketplace/AppsPage/AppsPageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,34 @@ const AppsPageContent = (): ReactElement => {
}
}, [context, marketplaceApps, installedApps, privateApps]);

const findSort = () => {
const possibleSort = sortFilterStructure.items.find(({ checked }) => checked);

return possibleSort ? possibleSort.id : 'mru';
};

const findPurchaseType = () => {
const possiblePurchaseType = freePaidFilterStructure.items.find(({ checked }) => checked);

return possiblePurchaseType ? possiblePurchaseType.id : 'all';
};

const findStatus = () => {
const possibleStatus = statusFilterStructure.items.find(({ checked }) => checked);

return possibleStatus ? possibleStatus.id : 'all';
};

const [categories, selectedCategories, categoryTagList, onSelected] = useCategories();
const appsResult = useFilteredApps({
appsData: getAppsData(),
text,
current,
itemsPerPage,
categories: useMemo(() => selectedCategories.map(({ label }) => label), [selectedCategories]),
purchaseType: useMemo(() => freePaidFilterStructure.items.find(({ checked }) => checked)?.id, [freePaidFilterStructure]),
sortingMethod: useMemo(() => sortFilterStructure.items.find(({ checked }) => checked)?.id, [sortFilterStructure]),
status: useMemo(() => statusFilterStructure.items.find(({ checked }) => checked)?.id, [statusFilterStructure]),
purchaseType: useMemo(findPurchaseType, [freePaidFilterStructure]),
sortingMethod: useMemo(findSort, [sortFilterStructure]),
status: useMemo(findStatus, [statusFilterStructure]),
context,
});

Expand Down
106 changes: 45 additions & 61 deletions apps/meteor/client/views/marketplace/hooks/useFilteredApps.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { PaginatedResult } from '@rocket.chat/rest-typings';
import type { ContextType } from 'react';
import { useMemo } from 'react';
import { compose } from 'underscore';

import type { AppsContext } from '../../../contexts/AppsContext';
import type { AsyncState } from '../../../lib/asyncState';
Expand Down Expand Up @@ -33,11 +34,11 @@ export const useFilteredApps = ({
text: string;
current: number;
itemsPerPage: number;
categories?: string[];
purchaseType?: string;
categories: string[];
purchaseType: string;
isEnterpriseOnly?: boolean;
sortingMethod?: string;
status?: string;
sortingMethod: string;
status: string;
context?: string;
}): AsyncState<
{ items: App[] } & { shouldShowSearchText: boolean } & PaginatedResult & { allApps: App[] } & { totalAppsLength: number }
Expand All @@ -49,70 +50,53 @@ export const useFilteredApps = ({

const { apps } = appsData.value;

let filtered: App[] = apps;
let shouldShowSearchText = true;

const sortingMethods: Record<string, () => App[]> = {
urf: () =>
filtered.sort(
(firstApp, secondApp) => (secondApp?.appRequestStats?.totalUnseen || 0) - (firstApp?.appRequestStats?.totalUnseen || 0),
),
url: () =>
filtered.sort(
(firstApp, secondApp) => (firstApp?.appRequestStats?.totalUnseen || 0) - (secondApp?.appRequestStats?.totalUnseen || 0),
),
az: () => filtered.sort((firstApp, secondApp) => sortAppsByAlphabeticalOrInverseOrder(firstApp.name, secondApp.name)),
za: () => filtered.sort((firstApp, secondApp) => sortAppsByAlphabeticalOrInverseOrder(secondApp.name, firstApp.name)),
mru: () =>
filtered.sort((firstApp, secondApp) => sortAppsByClosestOrFarthestModificationDate(firstApp.modifiedAt, secondApp.modifiedAt)),
lru: () =>
filtered.sort((firstApp, secondApp) => sortAppsByClosestOrFarthestModificationDate(secondApp.modifiedAt, firstApp.modifiedAt)),
let shouldShowSearchText = false;
const fallback = (apps: App[]) => apps;

const sortingMethods: Record<string, (apps: App[]) => App[]> = {
urf: (apps: App[]) =>
apps.sort((firstApp, secondApp) => (secondApp?.appRequestStats?.totalUnseen || 0) - (firstApp?.appRequestStats?.totalUnseen || 0)),
url: (apps: App[]) =>
apps.sort((firstApp, secondApp) => (firstApp?.appRequestStats?.totalUnseen || 0) - (secondApp?.appRequestStats?.totalUnseen || 0)),
az: (apps: App[]) => apps.sort((firstApp, secondApp) => sortAppsByAlphabeticalOrInverseOrder(firstApp.name, secondApp.name)),
za: (apps: App[]) => apps.sort((firstApp, secondApp) => sortAppsByAlphabeticalOrInverseOrder(secondApp.name, firstApp.name)),
mru: (apps: App[]) =>
apps.sort((firstApp, secondApp) => sortAppsByClosestOrFarthestModificationDate(firstApp.modifiedAt, secondApp.modifiedAt)),
lru: (apps: App[]) =>
apps.sort((firstApp, secondApp) => sortAppsByClosestOrFarthestModificationDate(secondApp.modifiedAt, firstApp.modifiedAt)),
};

if (context && context === 'enterprise') {
filtered = apps.filter(({ categories }) => categories.includes('Enterprise'));
}

if (sortingMethod) {
filtered = sortingMethods[sortingMethod]();
}

const filterByPurchaseType: Record<string, () => App[]> = {
paid: () => filtered.filter(filterAppsByPaid),
enterprise: () => filtered.filter(filterAppsByEnterprise),
free: () => filtered.filter(filterAppsByFree),
const filterByPurchaseType: Record<string, (apps: App[]) => App[]> = {
all: fallback,
paid: (apps: App[]) => apps.filter(filterAppsByPaid),
enterprise: (apps: App[]) => apps.filter(filterAppsByEnterprise),
free: (apps: App[]) => apps.filter(filterAppsByFree),
};

if (purchaseType && purchaseType !== 'all') {
filtered = filterByPurchaseType[purchaseType]();

if (!filtered.length) shouldShowSearchText = false;
}

if (status && status !== 'all') {
filtered = status === 'enabled' ? filtered.filter(filterAppsByEnabled) : filtered.filter(filterAppsByDisabled);

if (!filtered.length) shouldShowSearchText = false;
}

if (Boolean(categories.length) && Boolean(text)) {
filtered = filtered.filter((app) => filterAppsByCategories(app, categories)).filter(({ name }) => filterAppsByText(name, text));
shouldShowSearchText = true;
}
const filterByStatus: Record<string, (apps: App[]) => App[]> = {
all: fallback,
enabled: (apps: App[]) => apps.filter(filterAppsByEnabled),
disabled: (apps: App[]) => apps.filter(filterAppsByDisabled),
};

if (Boolean(categories.length) && !text) {
filtered = filtered.filter((app) => filterAppsByCategories(app, categories));
shouldShowSearchText = false;
}
const filterByContext: Record<string, (apps: App[]) => App[]> = {
explore: fallback,
installed: fallback,
private: fallback,
enterprise: (apps: App[]) => apps.filter(({ categories }) => categories.includes('Enterprise')),
requested: (apps: App[]) => apps.filter(({ appRequestStats, installed }) => Boolean(appRequestStats) && !installed),
};

if (!categories.length && Boolean(text)) {
filtered = filtered.filter(({ name }) => filterAppsByText(name, text));
shouldShowSearchText = true;
}
const filtered = compose(
context ? filterByContext[context] : fallback,
filterByPurchaseType[purchaseType],
filterByStatus[status],
categories.length ? (apps: App[]) => apps.filter((app) => filterAppsByCategories(app, categories)) : fallback,
text ? (apps: App[]) => apps.filter(({ name }) => filterAppsByText(name, text)) : fallback,
sortingMethods[sortingMethod],
)(apps);

if (context && context === 'requested') {
filtered = apps.filter(({ appRequestStats, installed }) => Boolean(appRequestStats) && !installed);
}
if (text) shouldShowSearchText = true;

const total = filtered.length;
const offset = current > total ? 0 : current;
Expand Down

0 comments on commit 4f2f252

Please sign in to comment.