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

+12 -2
View File
@@ -95,14 +95,24 @@ export function stringArraysEqual(
return a.every((value, index) => value === b[index]);
}
export function decisionApproachDefaultScopeChips(): string[] {
const chips = (
decisionApproachesMessages as { defaultScopeChips?: unknown }
).defaultScopeChips;
if (!Array.isArray(chips)) return [];
return chips.filter((value): value is string => typeof value === "string");
}
/**
* Offer the four sidebar labels as Applicable Scope chips without persisting
* them onto `applicableScope` (unchecked keys must not publish as defaults).
* Offer the signed-off deck chips, then this card's scopes, then the coverage
* checklist labels. Unchecked extras are display-only and must not publish
* as defaults.
*/
export function withDecisionApproachKeyResourceScopes(
scopes: readonly string[],
): string[] {
return uniquePreserveOrder([
...decisionApproachDefaultScopeChips(),
...scopes,
...decisionApproachKeyResourceLabels(),
]);
+73
View File
@@ -0,0 +1,73 @@
import type { GroupAnswers, RecommendationReason, TraitKey } from "./deckTypes";
export type RecommendationWhyCopy = {
why: {
fit: string;
fitWithAnswer: string;
opened: string;
added: string;
};
group: {
kindAndSize: string;
kindOnly: string;
sizeOnly: string;
kind: Record<string, string>;
size: Record<string, string>;
};
answerThirdPerson: Record<string, string>;
answerYouSaid: Record<string, string>;
};
export function formatGroupPhrase(
answers: GroupAnswers,
copy: RecommendationWhyCopy,
): string {
const kind = answers.mainKind ? copy.group.kind[answers.mainKind] : "";
const size = answers.size ? copy.group.size[answers.size] : "";
if (kind && size) {
return copy.group.kindAndSize
.replace("{kind}", kind)
.replace("{size}", size);
}
if (kind) return copy.group.kindOnly.replace("{kind}", kind);
if (size) return copy.group.sizeOnly.replace("{size}", size);
return "";
}
function answerPhrase(
key: TraitKey,
phrases: Record<string, string>,
): string {
return phrases[key] ?? key;
}
/**
* Why line for a recommended card in the compact seven.
* Near-universal cards keep their catalog description instead.
*/
export function formatRecommendationWhyLine(
reason: RecommendationReason,
answers: GroupAnswers,
copy: RecommendationWhyCopy,
): string {
if (reason.kind === "added") {
return copy.why.added.replace(
"{answer}",
answerPhrase(reason.answer, copy.answerYouSaid),
);
}
if (reason.kind === "opened") {
return copy.why.opened.replace(
"{answer}",
answerPhrase(reason.answer, copy.answerYouSaid),
);
}
const group = formatGroupPhrase(answers, copy);
if (!group) return "";
if (reason.answer) {
return copy.why.fitWithAnswer
.replace("{group}", group)
.replace("{answer}", answerPhrase(reason.answer, copy.answerThirdPerson));
}
return copy.why.fit.replace("{group}", group);
}