Show invited people the Rule, let them copy its cards for their community, and replace an expired invitation link.

This commit is contained in:
adilallo committed 2026-11-06 09:16:06 -07:00
1 parent 727a92a9ac
commit 3c984e00c5
37 files changed
+1962 -19

No files matched your search

+113
View File
@@ -561,6 +561,119 @@ export type DuplicateRuleResult =
| { ok: true; id: string; title: string }
| { ok: false; error: string; status: number };
export type MakeCopyRuleResult =
| {
ok: true;
id: string;
title: string;
summary: string | null;
document: Record<string, unknown>;
copiedFromTitle: string;
copiedNameHit: {
categoryName: string;
entryTitle: string;
} | null;
}
| { ok: false; error: string; status: number };
export async function makeCopyPublishedRule(
id: string,
title: string,
): Promise<MakeCopyRuleResult> {
try {
const res = await fetch(
`/api/rules/${encodeURIComponent(id)}/make-copy`,
{
method: "POST",
credentials: "include",
headers: jsonHeaders,
body: JSON.stringify({ title }),
},
);
const data = (await safeParseJsonResponse(res)) as {
rule?: {
id: string;
title: string;
summary?: string | null;
document?: Record<string, unknown>;
copiedFromTitle?: string;
copiedNameHit?: {
categoryName: string;
entryTitle: string;
} | null;
};
} | null;
const rule = data && typeof data === "object" ? data.rule : undefined;
const document = rule?.document;
if (
!res.ok ||
!rule ||
typeof rule.id !== "string" ||
typeof rule.title !== "string" ||
!document ||
typeof document !== "object" ||
Array.isArray(document)
) {
const fromBody =
data && typeof data === "object" ? readApiErrorMessage(data) : null;
const msg =
fromBody && fromBody !== "Request failed"
? fromBody
: PUBLISH_FAILED_FALLBACK;
return {
ok: false as const,
error: msg,
status: res.status,
};
}
return {
ok: true,
id: rule.id,
title: rule.title,
summary: typeof rule.summary === "string" ? rule.summary : null,
document,
copiedFromTitle:
typeof rule.copiedFromTitle === "string" ? rule.copiedFromTitle : "",
copiedNameHit: rule.copiedNameHit ?? null,
};
} catch {
return {
ok: false as const,
error: DRAFT_SAVE_NETWORK_ERROR,
status: 0,
};
}
}
export async function resendExpiredStakeholderInvite(
token: string,
email: string,
): Promise<{ ok: true } | { ok: false; error: string; retryAfterMs?: number }> {
try {
const res = await fetch("/api/invites/rule-stakeholder/resend", {
method: "POST",
credentials: "include",
headers: jsonHeaders,
body: JSON.stringify({ token, email }),
});
const data = await safeParseJsonResponse(res);
if (!res.ok) {
const fromBody =
data && typeof data === "object" ? readApiErrorMessage(data) : null;
return {
ok: false as const,
error: fromBody && fromBody !== "Request failed"
? fromBody
: DRAFT_SAVE_NETWORK_ERROR,
retryAfterMs: retryAfterFromResponse(res, data),
};
}
return { ok: true };
} catch {
return { ok: false as const, error: DRAFT_SAVE_NETWORK_ERROR };
}
}
export async function duplicatePublishedRule(
id: string,
): Promise<DuplicateRuleResult> {