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

+57
View File
@@ -224,3 +224,60 @@ export async function listProfileRulesForUser(
});
return combined.slice(0, cap);
}
export type StakeholderInviteView = {
ruleId: string;
title: string;
summary: string | null;
document: Record<string, unknown>;
updatedAt: string;
inviterEmail: string | null;
};
/**
* Published rule an accepted stakeholder may read with invited chrome.
* `userId` is set only after the invite link is used.
*/
export async function getAcceptedStakeholderInviteView(opts: {
userId: string;
ruleId: string;
}): Promise<StakeholderInviteView | null> {
if (!isDatabaseConfigured()) return null;
const userId = opts.userId.trim();
const ruleId = opts.ruleId.trim();
if (userId.length === 0 || ruleId.length === 0) return null;
try {
const row = await prisma.ruleStakeholder.findFirst({
where: { ruleId, userId },
select: {
invitedBy: { select: { email: true } },
rule: {
select: {
id: true,
title: true,
summary: true,
document: true,
updatedAt: true,
},
},
},
});
if (!row) return null;
const document =
row.rule.document !== null &&
typeof row.rule.document === "object" &&
!Array.isArray(row.rule.document)
? (row.rule.document as Record<string, unknown>)
: {};
return {
ruleId: row.rule.id,
title: row.rule.title,
summary: row.rule.summary,
document,
updatedAt: row.rule.updatedAt.toISOString(),
inviterEmail: row.invitedBy?.email ?? null,
};
} catch {
return null;
}
}
@@ -223,6 +223,25 @@ export const postRuleStakeholderBodySchema = z.object({
email: stakeholderEmailSchema,
});
export const makeCopyRuleBodySchema = z.object({
title: z
.string()
.max(48)
.transform((s) => s.trim())
.refine((s) => s.length > 0, { message: "title required" }),
});
export type MakeCopyRuleBody = z.infer<typeof makeCopyRuleBodySchema>;
export const resendExpiredStakeholderInviteBodySchema = z.object({
token: z.string().min(10).max(200),
email: stakeholderEmailSchema,
});
export type ResendExpiredStakeholderInviteBody = z.infer<
typeof resendExpiredStakeholderInviteBodySchema
>;
export type PostRuleStakeholderBody = z.infer<
typeof postRuleStakeholderBodySchema
>;