feat: initial draft and components creation
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
"use server"
|
||||
|
||||
import { redirect } from "next/navigation"
|
||||
|
||||
import { replaceInvitationInteractions } from "@/lib/db/queries/interactions"
|
||||
import { getInvitationByToken, submitInvitationResponse } from "@/lib/db/queries/invitations"
|
||||
import { isRsvpClosed } from "@/lib/rsvp-deadline"
|
||||
import { interactionSubmissionSchema } from "@/lib/validation/interactions"
|
||||
import {
|
||||
mealPreferenceSchema,
|
||||
submitInvitationResponseSchema,
|
||||
} from "@/lib/validation/response"
|
||||
|
||||
function optionalString(formData: FormData, key: string) {
|
||||
return formData.get(key)?.toString() ?? ""
|
||||
}
|
||||
|
||||
function transportHelp(value: FormDataEntryValue | null) {
|
||||
if (value === "yes") return true
|
||||
if (value === "no") return false
|
||||
return null
|
||||
}
|
||||
|
||||
function toastRequest(formData: FormData) {
|
||||
if (!formData.has("wantsToast")) return null
|
||||
|
||||
const speakerName = optionalString(formData, "toastSpeakerName")
|
||||
if (!speakerName) return null
|
||||
|
||||
return {
|
||||
memberId: optionalString(formData, "toastMemberId") || null,
|
||||
speakerName,
|
||||
estimatedMinutes: optionalString(formData, "toastEstimatedMinutes"),
|
||||
}
|
||||
}
|
||||
|
||||
export async function submitRsvpAction(token: string, formData: FormData) {
|
||||
if (isRsvpClosed()) redirect(`/invite/${token}?error=closed`)
|
||||
|
||||
const invitation = await getInvitationByToken(token)
|
||||
if (!invitation) redirect(`/invite/${token}?error=invalid`)
|
||||
|
||||
const members = invitation.members.map((member) => {
|
||||
const attendingValue = formData.get(`attending-${member.id}`)
|
||||
if (attendingValue !== "yes" && attendingValue !== "no") {
|
||||
redirect(`/invite/${token}?error=generic`)
|
||||
}
|
||||
|
||||
const attending = attendingValue === "yes"
|
||||
const meal = mealPreferenceSchema.safeParse(
|
||||
formData.get(`meal-${member.id}`)?.toString() ?? "",
|
||||
)
|
||||
|
||||
return {
|
||||
memberId: member.id,
|
||||
attending,
|
||||
mealPreference: attending && meal.success ? meal.data : null,
|
||||
dietaryRestrictions: optionalString(formData, `dietary-${member.id}`),
|
||||
}
|
||||
})
|
||||
|
||||
const response = submitInvitationResponseSchema.safeParse({
|
||||
token,
|
||||
members,
|
||||
arrivalDate: formData.get("arrivalDate"),
|
||||
departureDate: formData.get("departureDate"),
|
||||
stayLocation: formData.get("stayLocation"),
|
||||
needsTransportHelp: transportHelp(formData.get("needsTransportHelp")),
|
||||
messageToCouple: formData.get("messageToCouple"),
|
||||
})
|
||||
const interactions = interactionSubmissionSchema.safeParse({
|
||||
invitationId: invitation.invitation.id,
|
||||
toastRequest: toastRequest(formData),
|
||||
})
|
||||
|
||||
if (!response.success || !interactions.success) {
|
||||
redirect(`/invite/${token}?error=generic`)
|
||||
}
|
||||
|
||||
await submitInvitationResponse(response.data)
|
||||
await replaceInvitationInteractions(interactions.data)
|
||||
redirect(`/invite/${token}?submitted=1`)
|
||||
}
|
||||
Reference in New Issue
Block a user