feat: save the date tracking
Deploy On Server / Prepare Repository Remotely (push) Successful in 9s
Deploy On Server / Docker Compose Up (push) Successful in 17s
Deploy On Server / Prune Images (push) Successful in 3s
Deploy On Server / Remove .env File (push) Successful in 2s

This commit is contained in:
Raul Lugo
2026-08-11 23:18:23 +02:00
parent 5ff287a911
commit a4a77a3fa2
7 changed files with 186 additions and 0 deletions
+54
View File
@@ -16,6 +16,7 @@ export interface InvitationListItem {
contactPhone: string | null
maxPartySize: number
allowMemberEdits: boolean
saveTheDateSentAt: Date | null
membersCount: number
attendingCount: number
pendingCount: number
@@ -138,6 +139,58 @@ export async function deleteInvitationGroup(
})
}
export async function updateSaveTheDateSent({
invitationId,
sent,
adminEmail,
}: {
invitationId: string
sent: boolean
adminEmail: string
}) {
return db.transaction().execute(async (trx) => {
const invitation = await trx
.selectFrom("invitations")
.select(["id", "display_name", "save_the_date_sent_at"])
.where("id", "=", invitationId)
.executeTakeFirst()
if (!invitation) return null
const previousSent = invitation.save_the_date_sent_at !== null
const saveTheDateSentAt = sent ? new Date() : null
const updated = await trx
.updateTable("invitations")
.set({
save_the_date_sent_at: saveTheDateSentAt,
updated_at: new Date(),
})
.where("id", "=", invitationId)
.returning(["id", "save_the_date_sent_at"])
.executeTakeFirst()
if (!updated) return null
await trx
.insertInto("admin_audit_events")
.values({
admin_email: adminEmail,
action: sent ? "save_the_date.marked_sent" : "save_the_date.marked_unsent",
target_type: "invitation",
target_id: invitationId,
metadata: {
displayName: invitation.display_name,
previousSent,
newSent: sent,
},
})
.execute()
return updated
})
}
export async function listInvitations(): Promise<InvitationListItem[]> {
const invitations = await db
.selectFrom("invitations")
@@ -179,6 +232,7 @@ export async function listInvitations(): Promise<InvitationListItem[]> {
contactPhone: invitation.contact_phone,
maxPartySize: invitation.max_party_size,
allowMemberEdits: invitation.allow_member_edits,
saveTheDateSentAt: invitation.save_the_date_sent_at,
membersCount: invitationMembers.length,
attendingCount: invitationMembers.filter((member) => member.attending === true).length,
pendingCount: invitationMembers.filter((member) => member.attending === null).length,
+1
View File
@@ -26,6 +26,7 @@ export interface InvitationsTable {
contact_phone: string | null;
max_party_size: number;
allow_member_edits: boolean;
save_the_date_sent_at: NullableTimestamp;
notes: string | null;
created_at: Timestamp;
updated_at: Timestamp;
+6
View File
@@ -49,5 +49,11 @@ export const deleteInvitationSchema = z.object({
invitationId: z.uuid(),
})
export const updateSaveTheDateSentSchema = z.object({
invitationId: z.uuid(),
sent: z.boolean(),
})
export type CreateInvitationInput = z.infer<typeof createInvitationSchema>
export type DeleteInvitationInput = z.infer<typeof deleteInvitationSchema>
export type UpdateSaveTheDateSentInput = z.infer<typeof updateSaveTheDateSentSchema>