62 lines
1.6 KiB
TypeScript
62 lines
1.6 KiB
TypeScript
"use client"
|
|
|
|
import { useState } from "react"
|
|
|
|
import { updateSaveTheDateSentAction } from "@/app/admin/guests/actions"
|
|
import { Checkbox } from "@/components/ui/checkbox"
|
|
|
|
interface SaveTheDateCheckboxProps {
|
|
invitationId: string
|
|
displayName: string
|
|
sent: boolean
|
|
}
|
|
|
|
export function SaveTheDateCheckbox({
|
|
invitationId,
|
|
displayName,
|
|
sent,
|
|
}: SaveTheDateCheckboxProps) {
|
|
const [checked, setChecked] = useState(sent)
|
|
const [error, setError] = useState<string | null>(null)
|
|
const [isSaving, setIsSaving] = useState(false)
|
|
|
|
async function updateSent(nextChecked: boolean) {
|
|
const previousChecked = checked
|
|
|
|
setChecked(nextChecked)
|
|
setError(null)
|
|
setIsSaving(true)
|
|
|
|
try {
|
|
const result = await updateSaveTheDateSentAction({ invitationId, sent: nextChecked })
|
|
|
|
if (!result.ok) {
|
|
setChecked(previousChecked)
|
|
setError(result.error)
|
|
}
|
|
} catch {
|
|
setChecked(previousChecked)
|
|
setError("Could not update save-the-date status.")
|
|
} finally {
|
|
setIsSaving(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-1">
|
|
<label className="flex items-center gap-2 text-sm">
|
|
<Checkbox
|
|
checked={checked}
|
|
disabled={isSaving}
|
|
onCheckedChange={(value) => void updateSent(value === true)}
|
|
aria-label={`Mark save-the-date as sent for ${displayName}`}
|
|
/>
|
|
<span className={checked ? "font-medium" : "text-muted-foreground"}>
|
|
{checked ? "Sent" : "Not sent"}
|
|
</span>
|
|
</label>
|
|
{error ? <p className="max-w-36 text-xs text-destructive">{error}</p> : null}
|
|
</div>
|
|
)
|
|
}
|