From 79dff92e1e673b193bce70642976a75e4719fbae Mon Sep 17 00:00:00 2001 From: ttuovinen Date: Thu, 18 Apr 2024 09:02:50 +0300 Subject: [PATCH 1/3] Add double-click solo toggle to histogram legends --- src/finland/components/Histogram.tsx | 31 +++++++++++++++++++++---- src/stylesheets/finland_statistics.scss | 5 ++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/finland/components/Histogram.tsx b/src/finland/components/Histogram.tsx index fd8313a..3de79b9 100644 --- a/src/finland/components/Histogram.tsx +++ b/src/finland/components/Histogram.tsx @@ -1,5 +1,5 @@ import * as React from "react"; -import { useEffect, useMemo, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; import { LineChart, Line, @@ -33,6 +33,10 @@ import { useOpenSearchAnalytics } from "../hooks/useOpenSearchAnalytics"; export function Histogram() { const [interval, setInterval] = useState("hour"); const [inactiveGroups, setInactiveGroups] = useState([]); + const lastLegendClick: React.MutableRefObject<{ + key: string | null; + time: number | null; + }> = useRef({ key: null, time: null }); const { facetData, @@ -105,6 +109,10 @@ export function Histogram() { }); }, [histogramData]); + if (!timeData || !facetData) return null; + + const dateRangeLength = daysBetween(startDate, endDate); + function toggleGroup(key: string) { setInactiveGroups( inactiveGroups.includes(key) @@ -113,9 +121,24 @@ export function Histogram() { ); } - if (!timeData || !facetData) return null; + function toggleGroupSolo(key: string) { + setInactiveGroups( + inactiveGroups.length <= 1 ? eventKeys.filter((item) => item !== key) : [] + ); + } - const dateRangeLength = daysBetween(startDate, endDate); + function handleLegendClick(key: string) { + const now = Date.now(); + if ( + lastLegendClick.current.key === key && + now - lastLegendClick.current.time < 300 + ) { + toggleGroupSolo(key); + } else { + toggleGroup(key); + } + lastLegendClick.current = { key, time: now }; + } return (
@@ -173,7 +196,7 @@ export function Histogram() { timeStampToLabel(unixTime as number, interval) } /> - toggleGroup(item.dataKey)} /> + handleLegendClick(item.dataKey)} /> {eventKeys.map((item, idx) => ( Date: Fri, 19 Apr 2024 11:55:30 +0300 Subject: [PATCH 2/3] Add location to statistics facet filters --- src/finland/OpenSearchAnalyticsContext.tsx | 55 +++++++++++++++++++++- src/finland/components/EventBarChart.tsx | 10 +++- src/finland/components/FilterChips.tsx | 6 ++- src/finland/components/FilterInputs.tsx | 10 ++-- src/finland/components/Histogram.tsx | 4 ++ src/finland/finlandUtils.ts | 13 ++++- src/finland/tests/EventBarChart.test.tsx | 6 +++ src/finland/tests/FilterChips.test.tsx | 3 ++ src/finland/tests/FilterInputs.test.tsx | 8 ++++ src/finland/tests/FinlandStats.test.tsx | 6 +++ src/finland/tests/Histogram.test.tsx | 8 +++- 11 files changed, 117 insertions(+), 12 deletions(-) diff --git a/src/finland/OpenSearchAnalyticsContext.tsx b/src/finland/OpenSearchAnalyticsContext.tsx index 2ad9a1d..c16df26 100644 --- a/src/finland/OpenSearchAnalyticsContext.tsx +++ b/src/finland/OpenSearchAnalyticsContext.tsx @@ -1,9 +1,10 @@ import * as React from "react"; import { createContext, useEffect, useState } from "react"; -import { KeyValuePair } from "./finlandUtils"; +import { KeyValuePair, NameValuePair, readable } from "./finlandUtils"; const termsEndpoint = "/admin/events/terms"; const histogramEndpoint = "/admin/events/histogram"; const facetsEndpoint = "/admin/events/facets"; +const municipalityEndpoint = "/admin/municipalities"; type BucketItem = { key: string; @@ -28,12 +29,19 @@ type HistogramData = { export type FacetData = Record; +export type FilterToOptionsFunc = ( + filterKey: string, + buckets: BucketItem[] +) => NameValuePair[]; + export type OpenSearchAnalyticsContextType = { facetData?: FacetData; eventData?: TermBucketData; fetchEventData?: (params: KeyValuePair[]) => void; histogramData?: HistogramData; fetchHistogramData?: (params: KeyValuePair[]) => void; + filterToOptions?: FilterToOptionsFunc; + labelizeFilterChip: (item: KeyValuePair) => string; isReady?: boolean; }; @@ -55,6 +63,9 @@ export function OpenSearchAnalyticsContextProvider({ const [isReady, setIsReady] = useState(false); const [eventData, setEventData] = useState(null); const [histogramData, setHistogramData] = useState(null); + const [municipalityMapping, setMunicipalityMapping] = useState< + Record + >({}); useEffect(() => { async function fetchFacets() { @@ -70,7 +81,22 @@ export function OpenSearchAnalyticsContextProvider({ console.error("Error while fetching facets for statistics", err); } } + async function fetchMunicipalityMappings() { + try { + const response = await fetch(`${municipalityEndpoint}`); + const data = await response.json(); + if (data) { + setMunicipalityMapping(data); + } + } catch (err) { + console.error( + "Error while fetching municipality mapping for statistics", + err + ); + } + } fetchFacets(); + fetchMunicipalityMappings(); }, [library]); async function fetchEventData(selections?: KeyValuePair[]) { @@ -105,6 +131,31 @@ export function OpenSearchAnalyticsContextProvider({ } } + function filterToOptions(filterKey: string, buckets?: BucketItem[]) { + if (!buckets?.length) { + return []; + } + if (filterKey === "location") { + return buckets.map((item) => ({ + value: item.key, + name: municipalityMapping[item.key] || item.key, + })); + } + return buckets + .map((item) => ({ + value: item.key, + name: item.key, + })) + .sort((a, b) => a.name.localeCompare(b.name)); + } + + function labelizeFilterChip({ key, value }: KeyValuePair) { + if (key === "location") { + return `${readable(key)}: ${municipalityMapping[value] || value}`; + } + return `${readable(key)}: ${value}`; + } + return ( {children} diff --git a/src/finland/components/EventBarChart.tsx b/src/finland/components/EventBarChart.tsx index eb2d4c9..9f1516b 100644 --- a/src/finland/components/EventBarChart.tsx +++ b/src/finland/components/EventBarChart.tsx @@ -36,7 +36,13 @@ export function EventBarChart() { setTimeframeOffset, } = useFilters(); - const { facetData, eventData, fetchEventData } = useOpenSearchAnalytics(); + const { + facetData, + eventData, + fetchEventData, + filterToOptions, + labelizeFilterChip, + } = useOpenSearchAnalytics(); useEffect(() => { const selections: KeyValuePair[] = [...activeFilters]; @@ -67,12 +73,14 @@ export function EventBarChart() { setStartDate={setStartDate} endDate={endDate} setEndDate={setEndDate} + filterToOptions={filterToOptions} />
diff --git a/src/finland/components/FilterChips.tsx b/src/finland/components/FilterChips.tsx index 1e6783b..844c32e 100644 --- a/src/finland/components/FilterChips.tsx +++ b/src/finland/components/FilterChips.tsx @@ -1,16 +1,18 @@ import * as React from "react"; -import { KeyValuePair, readable } from "../finlandUtils"; +import { KeyValuePair } from "../finlandUtils"; type FilterChipsProps = { activeFilters: KeyValuePair[]; toggleFilter: (selection: KeyValuePair) => void; clearFilters: () => void; + labelize: (item: KeyValuePair) => string; }; export function FilterChips({ activeFilters, toggleFilter, clearFilters, + labelize, }: FilterChipsProps) { return (
@@ -22,7 +24,7 @@ export function FilterChips({ onClick={() => toggleFilter(item)} isSingle > - {readable(item.key)}: {item.value} + {labelize(item)} ))} void; endDate: string; setEndDate: (newDate: string) => void; + filterToOptions: FilterToOptionsFunc; }; export function FilterInputs({ @@ -20,15 +21,12 @@ export function FilterInputs({ setStartDate, endDate, setEndDate, + filterToOptions, }: FilterInputsProps) { return (
{filterKeys.map((key) => { - const options = - facetData[key]?.buckets.map((item) => ({ - value: item.key, - name: item.key, - })) || []; + const options = filterToOptions(key, facetData[key]?.buckets); const label = readable(key); return (
diff --git a/src/finland/components/Histogram.tsx b/src/finland/components/Histogram.tsx index 3de79b9..3a2ba25 100644 --- a/src/finland/components/Histogram.tsx +++ b/src/finland/components/Histogram.tsx @@ -42,6 +42,8 @@ export function Histogram() { facetData, histogramData, fetchHistogramData, + filterToOptions, + labelizeFilterChip, } = useOpenSearchAnalytics(); const { @@ -149,12 +151,14 @@ export function Histogram() { setStartDate={setStartDate} endDate={endDate} setEndDate={setEndDate} + filterToOptions={filterToOptions} />
diff --git a/src/finland/finlandUtils.ts b/src/finland/finlandUtils.ts index 68230ee..d3cc1af 100644 --- a/src/finland/finlandUtils.ts +++ b/src/finland/finlandUtils.ts @@ -27,12 +27,15 @@ export type EventKey = keyof IEvent; export type KeyValuePair = { key: string; value: string }; +export type NameValuePair = { name: string; value: string }; + export const eventTypes = { circulation_manager_check_out: "circulation_manager_check_out", circulation_manager_check_in: "circulation_manager_check_in", circulation_manager_fulfill: "circulation_manager_fulfill", circulation_manager_hold_place: "circulation_manager_hold_place", circulation_manager_hold_release: "circulation_manager_hold_release", + circulation_manager_new_patron: "circulation_manager_new_patron", distributor_check_out: "distributor_check_out", distributor_check_in: "distributor_check_in", distributor_hold_place: "distributor_hold_place", @@ -52,6 +55,7 @@ export const readableNames: Record = { [eventTypes.circulation_manager_fulfill]: "Toimitukset", [eventTypes.circulation_manager_hold_place]: "Varaukset, pyyntö", [eventTypes.circulation_manager_hold_release]: "Varaukset, nouto", + [eventTypes.circulation_manager_new_patron]: "Uudet asiakkaat", [eventTypes.distributor_check_out]: "Lainaukset", [eventTypes.distributor_check_in]: "Palautukset", [eventTypes.distributor_hold_place]: "Varaukset, pyyntö", @@ -71,6 +75,7 @@ export const readableNames: Record = { fiction: "Fiktio", genres: "Genre", audience: "Kohderyhmä", + location: "Sijainti", // Time intervals hour: "Tunti", day: "Päivä", @@ -80,7 +85,13 @@ export const readableNames: Record = { export const readable = (input: string): string => readableNames[input] || input; -export const filterKeys = ["publisher", "language", "audience", "genres"]; +export const filterKeys = [ + "publisher", + "language", + "audience", + "genres", + "location", +]; export const intervals = ["hour", "day", "month"]; export type Interval = "hour" | "day" | "month"; diff --git a/src/finland/tests/EventBarChart.test.tsx b/src/finland/tests/EventBarChart.test.tsx index 60309be..83e4e5b 100644 --- a/src/finland/tests/EventBarChart.test.tsx +++ b/src/finland/tests/EventBarChart.test.tsx @@ -57,6 +57,12 @@ jest.mock("../hooks/useOpenSearchAnalytics", () => ({ histogramData: histogramDataFixture.data, fetchHistogramData: jest.fn(() => null), isReady: true, + filterToOptions: jest.fn((_, buckets) => + buckets.map((item) => ({ + value: item.key, + name: item.key, + })) + ), })), })); diff --git a/src/finland/tests/FilterChips.test.tsx b/src/finland/tests/FilterChips.test.tsx index 7815f47..d8d7c07 100644 --- a/src/finland/tests/FilterChips.test.tsx +++ b/src/finland/tests/FilterChips.test.tsx @@ -22,6 +22,7 @@ describe("FilterChips", () => { activeFilters={activeFilters} toggleFilter={doNothing} clearFilters={doNothing} + labelize={(item) => `${item.key}: ${item.value}`} /> ); @@ -39,6 +40,7 @@ describe("FilterChips", () => { activeFilters={activeFilters} toggleFilter={toggleFilterMock} clearFilters={doNothing} + labelize={(item) => `${item.key}: ${item.value}`} /> ); @@ -57,6 +59,7 @@ describe("FilterChips", () => { activeFilters={activeFilters} toggleFilter={doNothing} clearFilters={clearFiltersMock} + labelize={(item) => `${item.key}: ${item.value}`} /> ); diff --git a/src/finland/tests/FilterInputs.test.tsx b/src/finland/tests/FilterInputs.test.tsx index d4ca443..1c10ad7 100644 --- a/src/finland/tests/FilterInputs.test.tsx +++ b/src/finland/tests/FilterInputs.test.tsx @@ -24,6 +24,7 @@ describe("FilterInputs", () => { setStartDate={doNothing} endDate="" setEndDate={doNothing} + filterToOptions={() => []} /> ); @@ -47,6 +48,12 @@ describe("FilterInputs", () => { setStartDate={doNothing} endDate="" setEndDate={doNothing} + filterToOptions={(_, buckets) => + buckets.map((item) => ({ + value: item.key, + name: item.key, + })) + } /> ); @@ -80,6 +87,7 @@ describe("FilterInputs", () => { setStartDate={setStartDateMock} endDate="2023-12-31" setEndDate={setEndDateMock} + filterToOptions={() => []} /> ); diff --git a/src/finland/tests/FinlandStats.test.tsx b/src/finland/tests/FinlandStats.test.tsx index 483afa9..abf2352 100644 --- a/src/finland/tests/FinlandStats.test.tsx +++ b/src/finland/tests/FinlandStats.test.tsx @@ -42,6 +42,12 @@ jest.mock("../hooks/useOpenSearchAnalytics", () => ({ histogramData: histogramDataFixture.data, fetchHistogramData: jest.fn(() => null), isReady: true, + filterToOptions: jest.fn((_, buckets) => + buckets.map((item) => ({ + value: item.key, + name: item.key, + })) + ), })), })); diff --git a/src/finland/tests/Histogram.test.tsx b/src/finland/tests/Histogram.test.tsx index 246a26e..a05aaf3 100644 --- a/src/finland/tests/Histogram.test.tsx +++ b/src/finland/tests/Histogram.test.tsx @@ -2,8 +2,8 @@ import * as React from "react"; import { render } from "@testing-library/react"; import { Histogram } from "../components/Histogram"; import { - facetDataFixture, eventDataFixture, + facetDataFixture, histogramDataFixture, } from "./fixtures"; @@ -57,6 +57,12 @@ jest.mock("../hooks/useOpenSearchAnalytics", () => ({ histogramData: histogramDataFixture.data, fetchHistogramData: jest.fn(() => null), isReady: true, + filterToOptions: jest.fn((_, buckets) => + buckets.map((item) => ({ + value: item.key, + name: item.key, + })) + ), })), })); From ce51c115e58c9d3a6e77056fd064ea200e9cd5a5 Mon Sep 17 00:00:00 2001 From: ttuovinen Date: Fri, 19 Apr 2024 15:28:41 +0300 Subject: [PATCH 3/3] Add loan duration facet to filters --- src/finland/OpenSearchAnalyticsContext.tsx | 25 ++++++++++++++++------ src/finland/finlandUtils.ts | 13 +++++++++++ src/finland/tests/EventBarChart.test.tsx | 12 ++++------- src/finland/tests/FilterInputs.test.tsx | 12 ++++------- src/finland/tests/FinlandStats.test.tsx | 8 ++----- src/finland/tests/Histogram.test.tsx | 16 ++++++-------- src/finland/tests/mocks.ts | 17 +++++++++++++++ 7 files changed, 65 insertions(+), 38 deletions(-) create mode 100644 src/finland/tests/mocks.ts diff --git a/src/finland/OpenSearchAnalyticsContext.tsx b/src/finland/OpenSearchAnalyticsContext.tsx index c16df26..c6f953a 100644 --- a/src/finland/OpenSearchAnalyticsContext.tsx +++ b/src/finland/OpenSearchAnalyticsContext.tsx @@ -1,12 +1,17 @@ import * as React from "react"; import { createContext, useEffect, useState } from "react"; -import { KeyValuePair, NameValuePair, readable } from "./finlandUtils"; +import { + KeyValuePair, + NameValuePair, + loanDurationOptions, + readable, +} from "./finlandUtils"; const termsEndpoint = "/admin/events/terms"; const histogramEndpoint = "/admin/events/histogram"; const facetsEndpoint = "/admin/events/facets"; const municipalityEndpoint = "/admin/municipalities"; -type BucketItem = { +export type BucketItem = { key: string; doc_count: number; }; @@ -132,14 +137,19 @@ export function OpenSearchAnalyticsContextProvider({ } function filterToOptions(filterKey: string, buckets?: BucketItem[]) { + if (filterKey === "duration") { + return [...loanDurationOptions]; // Spread to trigger SelectSearch re-render + } if (!buckets?.length) { return []; } if (filterKey === "location") { - return buckets.map((item) => ({ - value: item.key, - name: municipalityMapping[item.key] || item.key, - })); + return buckets + .map((item) => ({ + value: item.key, + name: municipalityMapping[item.key] || item.key, + })) + .sort((a, b) => a.name.localeCompare(b.name)); } return buckets .map((item) => ({ @@ -153,6 +163,9 @@ export function OpenSearchAnalyticsContextProvider({ if (key === "location") { return `${readable(key)}: ${municipalityMapping[value] || value}`; } + if (key === "duration") { + return `${readable(key)}: ${readable(value) || value}`; + } return `${readable(key)}: ${value}`; } diff --git a/src/finland/finlandUtils.ts b/src/finland/finlandUtils.ts index d3cc1af..2a41c3e 100644 --- a/src/finland/finlandUtils.ts +++ b/src/finland/finlandUtils.ts @@ -20,6 +20,7 @@ export interface IEvent { time: string; contributors: string[] | null; start: string; + duration: string | null; date?: string; } @@ -76,10 +77,14 @@ export const readableNames: Record = { genres: "Genre", audience: "Kohderyhmä", location: "Sijainti", + duration: "Laina-aika (palautukset)", // Time intervals hour: "Tunti", day: "Päivä", month: "Kuukausi", + // Loan duration options: + under_2h: "Alle 2h", + over_2h: "Yli 2h", }; export const readable = (input: string): string => @@ -91,6 +96,7 @@ export const filterKeys = [ "audience", "genres", "location", + "duration", ]; export const intervals = ["hour", "day", "month"]; @@ -134,6 +140,13 @@ export const timeframeOptions: Record = { }, }; +const loanDurations = ["under_2h", "over_2h"]; + +export const loanDurationOptions = loanDurations.map((key) => ({ + value: key, + name: readable(key), +})); + /* * General helper functions */ diff --git a/src/finland/tests/EventBarChart.test.tsx b/src/finland/tests/EventBarChart.test.tsx index 83e4e5b..6782946 100644 --- a/src/finland/tests/EventBarChart.test.tsx +++ b/src/finland/tests/EventBarChart.test.tsx @@ -6,6 +6,7 @@ import { eventDataFixture, histogramDataFixture, } from "./fixtures"; +import { mockFilterToOptions } from "./mocks"; /* Mock globals and dependencies */ @@ -57,16 +58,11 @@ jest.mock("../hooks/useOpenSearchAnalytics", () => ({ histogramData: histogramDataFixture.data, fetchHistogramData: jest.fn(() => null), isReady: true, - filterToOptions: jest.fn((_, buckets) => - buckets.map((item) => ({ - value: item.key, - name: item.key, - })) - ), + filterToOptions: jest.fn(mockFilterToOptions), })), })); -const eventTypesLenght = eventDataFixture.data.type.length; +const eventTypesLength = eventDataFixture.data.type.length; afterAll(() => { jest.resetAllMocks(); @@ -79,6 +75,6 @@ describe("EventBarChart", () => { const bars = document.querySelectorAll(".recharts-bar-rectangle"); // Check that there's as many bars as event types - expect(bars.length === eventTypesLenght).toBeTruthy(); + expect(bars.length === eventTypesLength).toBeTruthy(); }); }); diff --git a/src/finland/tests/FilterInputs.test.tsx b/src/finland/tests/FilterInputs.test.tsx index 1c10ad7..5a151e9 100644 --- a/src/finland/tests/FilterInputs.test.tsx +++ b/src/finland/tests/FilterInputs.test.tsx @@ -3,6 +3,7 @@ import { render, fireEvent, screen } from "@testing-library/react"; import { FilterInputs } from "../components/FilterInputs"; import { facetDataFixture } from "./fixtures"; import { filterKeys } from "../finlandUtils"; +import { mockFilterToOptions } from "./mocks"; function doNothing() { /* do nothing */ @@ -24,7 +25,7 @@ describe("FilterInputs", () => { setStartDate={doNothing} endDate="" setEndDate={doNothing} - filterToOptions={() => []} + filterToOptions={mockFilterToOptions} /> ); @@ -48,12 +49,7 @@ describe("FilterInputs", () => { setStartDate={doNothing} endDate="" setEndDate={doNothing} - filterToOptions={(_, buckets) => - buckets.map((item) => ({ - value: item.key, - name: item.key, - })) - } + filterToOptions={mockFilterToOptions} /> ); @@ -87,7 +83,7 @@ describe("FilterInputs", () => { setStartDate={setStartDateMock} endDate="2023-12-31" setEndDate={setEndDateMock} - filterToOptions={() => []} + filterToOptions={mockFilterToOptions} /> ); diff --git a/src/finland/tests/FinlandStats.test.tsx b/src/finland/tests/FinlandStats.test.tsx index abf2352..22e539c 100644 --- a/src/finland/tests/FinlandStats.test.tsx +++ b/src/finland/tests/FinlandStats.test.tsx @@ -7,6 +7,7 @@ import { facetDataFixture, histogramDataFixture, } from "./fixtures"; +import { mockFilterToOptions } from "./mocks"; /* Mock globals and dependencies */ @@ -42,12 +43,7 @@ jest.mock("../hooks/useOpenSearchAnalytics", () => ({ histogramData: histogramDataFixture.data, fetchHistogramData: jest.fn(() => null), isReady: true, - filterToOptions: jest.fn((_, buckets) => - buckets.map((item) => ({ - value: item.key, - name: item.key, - })) - ), + filterToOptions: jest.fn(mockFilterToOptions), })), })); diff --git a/src/finland/tests/Histogram.test.tsx b/src/finland/tests/Histogram.test.tsx index a05aaf3..c44c41d 100644 --- a/src/finland/tests/Histogram.test.tsx +++ b/src/finland/tests/Histogram.test.tsx @@ -6,6 +6,7 @@ import { facetDataFixture, histogramDataFixture, } from "./fixtures"; +import { mockFilterToOptions } from "./mocks"; /* Mock globals and dependencies */ @@ -57,16 +58,11 @@ jest.mock("../hooks/useOpenSearchAnalytics", () => ({ histogramData: histogramDataFixture.data, fetchHistogramData: jest.fn(() => null), isReady: true, - filterToOptions: jest.fn((_, buckets) => - buckets.map((item) => ({ - value: item.key, - name: item.key, - })) - ), + filterToOptions: jest.fn(mockFilterToOptions), })), })); -const eventTypesLenght = eventDataFixture.data.type.length; +const eventTypesLength = eventDataFixture.data.type.length; afterAll(() => { jest.resetAllMocks(); @@ -79,11 +75,11 @@ describe("Histogram", () => { const lines = document.querySelectorAll(".recharts-line"); // Check that there's as many bars as event types - for (let i = 0; i < eventTypesLenght; i++) { + for (let i = 0; i < eventTypesLength; i++) { expect(lines[i]).toBeInTheDocument(); } // ... but no more than that - expect(lines[eventTypesLenght]).toBeFalsy(); + expect(lines[eventTypesLength]).toBeFalsy(); }); it("toggles a line when clicking a legend", () => { @@ -92,6 +88,6 @@ describe("Histogram", () => { const lines = document.querySelectorAll(".recharts-legend-item"); // Check that there's as many lines as event types - expect(lines.length === eventTypesLenght).toBeTruthy(); + expect(lines.length === eventTypesLength).toBeTruthy(); }); }); diff --git a/src/finland/tests/mocks.ts b/src/finland/tests/mocks.ts new file mode 100644 index 0000000..3841b24 --- /dev/null +++ b/src/finland/tests/mocks.ts @@ -0,0 +1,17 @@ +import { BucketItem } from "../OpenSearchAnalyticsContext"; +import { loanDurationOptions } from "../finlandUtils"; + +export function mockFilterToOptions(filterKey: string, buckets?: BucketItem[]) { + if (filterKey === "duration") { + return [...loanDurationOptions]; + } + if (!buckets?.length) { + return []; + } + return buckets + .map((item) => ({ + value: item.key, + name: item.key, + })) + .sort((a, b) => a.name.localeCompare(b.name)); +}