Send the invitation as a light letter that names the community, the inviter by email, and who can read the Rule.

This commit is contained in:
adilallo committed 2026-11-06 09:00:44 -07:00
1 parent 70ceb73104
commit 727a92a9ac
14 files changed
+534 -26

No files matched your search

+56
View File
@@ -0,0 +1,56 @@
import { parsePublishedDocumentForCommunityRuleDisplay } from "./publishedDocumentToDisplaySections";
import { RULE_SECTION_CATEGORY } from "./ruleSectionsFromMethodSelections";
import sharedTerms from "../../messages/en/create/sharedTerms.json";
const DESCRIPTION_MAX = 140;
/** Initials for the invite email disc when the group has no photo. */
export function communityInviteInitials(name: string): string {
const words = name
.trim()
.split(/\s+/)
.filter((word) => word.length > 0);
if (words.length === 0) return "·";
if (words.length === 1) {
const word = words[0] ?? "";
return word.slice(0, 2).toUpperCase();
}
const first = words[0]?.charAt(0) ?? "";
const second = words[1]?.charAt(0) ?? "";
return `${first}${second}`.toUpperCase();
}
/** Possessive for footer copy (`Share’s` / `Members’`). */
export function communityPossessive(name: string): string {
const trimmed = name.trim();
if (trimmed.length === 0) return "this community’s";
if (/s$/i.test(trimmed)) return `${trimmed}’`;
return `${trimmed}’s`;
}
/** Community description on the invite card, cut at 140 characters. */
export function clipCommunityInviteDescription(
raw: string | null | undefined,
): string {
const trimmed = typeof raw === "string" ? raw.trim() : "";
if (trimmed.length <= DESCRIPTION_MAX) return trimmed;
return trimmed.slice(0, DESCRIPTION_MAX).trimEnd();
}
/** Tag on the invite Rule card (`3 VALUES AND 6 CARDS`). Shared terms do not count. */
export function inviteRuleCountsLabel(document: unknown): string {
const sections = parsePublishedDocumentForCommunityRuleDisplay(document);
let values = 0;
let cards = 0;
for (const section of sections) {
const n = section.entries.length;
if (section.categoryName === RULE_SECTION_CATEGORY.values) {
values += n;
} else if (section.categoryName !== sharedTerms.sectionTitle) {
cards += n;
}
}
const valuePart = values === 1 ? "1 VALUE" : `${values} VALUES`;
const cardPart = cards === 1 ? "1 CARD" : `${cards} CARDS`;
return `${valuePart} AND ${cardPart}`;
}