Show seven cards on the four method decks and open each as a routing overlay of its parts, so groups write from empty fields with Generate draft, search the full deck, and see unselected scope chips with enough contrast.

This commit is contained in:
adilallo committed 2026-11-05 22:43:30 -07:00
1 parent dea7dd7fbd
commit 46656f52d3
28 files changed
+1349 -318

No files matched your search

@@ -2,12 +2,15 @@
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 };
@@ -25,9 +28,8 @@ function orderByIds<T extends { id: string }>(
}
/**
* Deck order and the compact stack come from the job rule. Current screens
* show five cards; a deck screen passes seven. Selected cards still pin
* into the compact stack.
* 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,
@@ -35,13 +37,15 @@ export function useMethodCardDeckOrdering(
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, 5),
[section, answers],
() => deriveCompactCards(section, answers, compactLimit),
[section, answers, compactLimit],
);
const rankedMethods = useMemo(
@@ -59,25 +63,57 @@ export function useMethodCardDeckOrdering(
deck.compactCardIds,
selectedIds,
selectionShowcaseActive,
5,
compactLimit,
),
[
rankedMethods,
deck.compactCardIds,
selectedIds,
selectionShowcaseActive,
compactLimit,
],
);
const compactIdSet = useMemo(
() => new Set(compactCardIds),
[compactCardIds],
);
const sampleCards = useMemo(
() =>
rankedMethods.map((entry) => ({
id: entry.id,
label: entry.label,
supportText: entry.supportText,
recommended: recommendedIds.has(entry.id),
})),
[rankedMethods, recommendedIds],
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(
@@ -92,6 +128,8 @@ export function useMethodCardDeckOrdering(
recommendedIds,
sampleCards,
methodById,
showDeckLine: !deck.fallback,
compactLimit,
recommendationsReady: true,
};
}