136 lines
4.0 KiB
TypeScript
136 lines
4.0 KiB
TypeScript
"use client";
|
|
|
|
import { useMemo } from "react";
|
|
import { mergeCompactCardIdsWithPinnedSelected } from "../../../../lib/create/methodCardDisplayOrder";
|
|
import { formatRecommendationWhyLine } from "../../../../lib/create/formatRecommendationWhyLine";
|
|
import {
|
|
deriveCompactCards,
|
|
groupAnswersForRecommendations,
|
|
type RecommendationSection,
|
|
} from "./useFacetRecommendations";
|
|
import { deckData } from "../../../../lib/create/deckRecommend";
|
|
import { useCreateFlow } from "../context/CreateFlowContext";
|
|
import { useMessages } from "../../../contexts/MessagesContext";
|
|
|
|
type MethodEntry = { id: string; label: string; supportText: string };
|
|
|
|
function orderByIds<T extends { id: string }>(
|
|
methods: readonly T[],
|
|
orderedIds: readonly string[],
|
|
): T[] {
|
|
const byId = new Map(methods.map((method) => [method.id, method]));
|
|
const ordered = orderedIds.flatMap((id) => {
|
|
const method = byId.get(id);
|
|
return method ? [method] : [];
|
|
});
|
|
const seen = new Set(ordered.map((method) => method.id));
|
|
return [...ordered, ...methods.filter((method) => !seen.has(method.id))];
|
|
}
|
|
|
|
/**
|
|
* Deck order and the compact stack come from the job rule. Compact shows
|
|
* at most seven recommended cards. Selected cards still pin into the stack.
|
|
*/
|
|
export function useMethodCardDeckOrdering(
|
|
section: RecommendationSection,
|
|
methods: readonly MethodEntry[],
|
|
selectedIds: readonly string[],
|
|
) {
|
|
const { state } = useCreateFlow();
|
|
const copy = useMessages().create.customRule.recommendations;
|
|
const compactLimit = deckData(section).config.displayLimit;
|
|
const answers = useMemo(
|
|
() => groupAnswersForRecommendations(state),
|
|
[state],
|
|
);
|
|
const deck = useMemo(
|
|
() => deriveCompactCards(section, answers, compactLimit),
|
|
[section, answers, compactLimit],
|
|
);
|
|
|
|
const rankedMethods = useMemo(
|
|
() => orderByIds(methods, deck.orderedIds),
|
|
[methods, deck.orderedIds],
|
|
);
|
|
|
|
const selectionShowcaseActive = selectedIds.length > 0;
|
|
const { recommendedIds } = deck;
|
|
|
|
const compactCardIds = useMemo(
|
|
() =>
|
|
mergeCompactCardIdsWithPinnedSelected(
|
|
rankedMethods.map((method) => method.id),
|
|
deck.compactCardIds,
|
|
selectedIds,
|
|
selectionShowcaseActive,
|
|
compactLimit,
|
|
),
|
|
[
|
|
rankedMethods,
|
|
deck.compactCardIds,
|
|
selectedIds,
|
|
selectionShowcaseActive,
|
|
compactLimit,
|
|
],
|
|
);
|
|
|
|
const compactIdSet = useMemo(
|
|
() => new Set(compactCardIds),
|
|
[compactCardIds],
|
|
);
|
|
|
|
const sampleCards = useMemo(
|
|
() =>
|
|
rankedMethods.map((entry) => {
|
|
const recommendation = deck.recommendedById.get(entry.id);
|
|
const whyLine =
|
|
recommendation && recommendation.tag !== "everyRuleHas"
|
|
? formatRecommendationWhyLine(recommendation.reason, answers, copy)
|
|
: "";
|
|
const alternativeId = recommendation?.alternative;
|
|
const alternativeMethod = alternativeId
|
|
? rankedMethods.find((method) => method.id === alternativeId) ??
|
|
methods.find((method) => method.id === alternativeId)
|
|
: undefined;
|
|
return {
|
|
id: entry.id,
|
|
label: entry.label,
|
|
supportText: entry.supportText,
|
|
compactSupportText:
|
|
whyLine && compactIdSet.has(entry.id) ? whyLine : undefined,
|
|
recommended: recommendedIds.has(entry.id),
|
|
alternative:
|
|
alternativeMethod && compactIdSet.has(entry.id)
|
|
? { id: alternativeMethod.id, label: alternativeMethod.label }
|
|
: undefined,
|
|
};
|
|
}),
|
|
[
|
|
answers,
|
|
compactIdSet,
|
|
copy,
|
|
deck.recommendedById,
|
|
methods,
|
|
rankedMethods,
|
|
recommendedIds,
|
|
],
|
|
);
|
|
|
|
const methodById = useMemo(
|
|
() => new Map(rankedMethods.map((entry) => [entry.id, entry])),
|
|
[rankedMethods],
|
|
);
|
|
|
|
return {
|
|
rankedMethods,
|
|
displayMethods: rankedMethods,
|
|
compactCardIds,
|
|
recommendedIds,
|
|
sampleCards,
|
|
methodById,
|
|
showDeckLine: !deck.fallback,
|
|
compactLimit,
|
|
recommendationsReady: true,
|
|
};
|
|
}
|