| 1 | /** |
| 2 | * Workspace invitations, as the person invited sees them on /invitations |
| 3 | * and on the page for someone without a workspace. No Workers or React |
| 4 | * imports, so it can be tested under Node. |
| 5 | */ |
| 6 | |
| 7 | type Shown = { role: "owner" | "member"; expiresAt: string }; |
| 8 | |
| 9 | /** What follows the inviter's name: the role it joins with, and until when it works. */ |
| 10 | export function invitationLine(invitation: Shown, now = Date.now()): string { |
| 11 | const role = invitation.role === "owner" ? "an owner" : "a member"; |
| 12 | const days = Math.ceil((new Date(invitation.expiresAt).getTime() - now) / (24 * 60 * 60 * 1000)); |
| 13 | const until = |
| 14 | days <= 1 ? "It expires within a day." : `It works for ${days} more days.`; |
| 15 | return `invited you to join as ${role}. ${until}`; |
| 16 | } |
| 17 | |
| 18 | /** What the page says once an invitation was declined. */ |
| 19 | export function declinedLine(workspace: string | null | undefined): string { |
| 20 | const name = workspace?.trim(); |
| 21 | return name |
| 22 | ? `You declined the invitation to ${name}. Whoever sent it has been told.` |
| 23 | : "You declined the invitation. Whoever sent it has been told."; |
| 24 | } |