import type { NoteVisibilityValue } from "./NoteVisibilitySelect.tsx"; /** * WHAT AN INTERNAL NOTE STILL NEEDS BEFORE IT CAN BE SAVED, in the author's words. * * THE BUTTON AND THE SENTENCE COME FROM ONE LIST, deliberately. A disabled control and a message * explaining it are two statements about the same rule, and two statements drift: the note composer * had the rule and not the message, so Save sat dead with no title, no message and no marker on the * control it was waiting for. An author could type a note, look at a greyed button, and have nothing * on screen tell them that choosing an audience was the missing step. * * The clinical note on the same encounter already does this properly - accepting a coded proposal * opens a form headed "STILL NEEDED 2" that names the outstanding fields rather than marking itself * invalid. Two note types, one screen, and only one of them said what it wanted. * * PHRASED AS THE THING, NOT THE FIELD. "Who can see it" is what the author is being asked for; * "visibility.mode" is what the code calls it, and nobody types a mode. */ /** No organization means no picker on screen, so there is no audience to ask for. */ export const newNoteRequirements = ( body: string, visibility: NoteVisibilityValue, hasOrg: boolean, ): readonly string[] => { const missing: string[] = []; if (body.trim().length === 0) { missing.push("something in the note"); } // With no picker rendered there is no choice to make, and requiring one would leave an org-less // author staring at a permanently disabled Save with nothing to click that would enable it. if (hasOrg && visibility.mode === "") { missing.push("who can see it"); } // Choosing "Specific role categories" and naming none is an audience of nobody, which is a // different mistake from not having chosen at all and reads better said separately. if (visibility.mode === "roles" && visibility.categoryLabels.length === 0) { missing.push("at least one role category"); } return missing; }; /** * The list read out loud: "a and b", "a, b and c". * * An Oxford-comma-free join because this is a sentence fragment under a button rather than prose, * and the list is never longer than three. */ export const describeRequirements = (missing: readonly string[]): string => { if (missing.length === 0) return ""; if (missing.length === 1) return missing[0]; return `${missing.slice(0, -1).join(", ")} and ${missing[missing.length - 1]}`; };