While onboarding wrote the main conversation, its sidebar row, project rows and Heute showed the server preview: nothing for a pending card (a card has no text of its own, so the row fell back to "Ready") and the English fallback of the closing note, even for a German user. Groups now carry `previewBlock` next to `preview`: the latest message when it is an onboarding card or note, validated with the same block schemas the messages use (now named exports). The web words it with the helpers that render the card and the note, so no copy is duplicated: the question while a card waits, the answer once given, and the closing note in the user's language and clock. A dismissed card keeps the plain preview, as the conversation no longer shows it. The field is left out for every other message, and mobile keeps using the plain `preview`. The chosen-answer lookup moves from the card into onboarding-copy so the card and the preview share it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRtGG9ARfqqhma3t85Ro2u
40 lines
1.2 KiB
TypeScript
40 lines
1.2 KiB
TypeScript
import type { Group } from "@rakazo/contracts";
|
|
import { IntakeBlockSchema } from "@rakazo/contracts";
|
|
import { ACTIVE_RUN_STATUSES } from "@rakazo/core";
|
|
|
|
export const activeRunStatuses = [...ACTIVE_RUN_STATUSES];
|
|
|
|
export const activeRunSelection = {
|
|
where: { status: { in: activeRunStatuses } },
|
|
orderBy: { createdAt: "desc" as const },
|
|
take: 1,
|
|
select: { status: true },
|
|
} as const;
|
|
|
|
export function previewFromBlocks(blocks: unknown): string {
|
|
const rows = Array.isArray(blocks) ? blocks : [];
|
|
for (const block of rows) {
|
|
if (
|
|
block &&
|
|
typeof block === "object" &&
|
|
"text" in block &&
|
|
typeof (block as { text?: unknown }).text === "string"
|
|
) {
|
|
return (block as { text: string }).text;
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
/**
|
|
* A group's preview of its latest message. An onboarding card or note comes along as
|
|
* `previewBlock`, so the web can word the preview in the user's language.
|
|
*/
|
|
export function groupPreview(blocks: unknown): Pick<Group, "preview" | "previewBlock"> {
|
|
const intake = IntakeBlockSchema.safeParse(Array.isArray(blocks) ? blocks[0] : undefined);
|
|
return {
|
|
preview: previewFromBlocks(blocks),
|
|
...(intake.success ? { previewBlock: intake.data } : {}),
|
|
};
|
|
}
|