Add optional cancellation message for notifications
This commit is contained in:
@@ -51,6 +51,9 @@ export function PlanDashboard({ plan, dict, settingsDict, lang }: PlanDashboardP
|
||||
const [sitterName, setSitterName] = useState("")
|
||||
const [bookingType, setBookingType] = useState<"SITTER" | "OWNER_HOME">("SITTER")
|
||||
const [isDialogOpen, setIsDialogOpen] = useState(false)
|
||||
const [isCancelDialogOpen, setIsCancelDialogOpen] = useState(false)
|
||||
const [bookingToCancel, setBookingToCancel] = useState<number | null>(null)
|
||||
const [cancelReason, setCancelReason] = useState("")
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
|
||||
const dateLocale = lang === "de" ? de : enUS
|
||||
@@ -92,14 +95,25 @@ export function PlanDashboard({ plan, dict, settingsDict, lang }: PlanDashboardP
|
||||
}
|
||||
}
|
||||
|
||||
const handleCancel = async (bookingId: number) => {
|
||||
if (!confirm(dict.cancelConfirm)) return
|
||||
const handleCancelClick = (bookingId: number) => {
|
||||
setBookingToCancel(bookingId)
|
||||
setCancelReason("")
|
||||
setIsCancelDialogOpen(true)
|
||||
}
|
||||
|
||||
const handleConfirmCancel = async () => {
|
||||
if (!bookingToCancel) return
|
||||
|
||||
setIsSubmitting(true)
|
||||
try {
|
||||
await deleteBooking(bookingId, plan.id, lang)
|
||||
await deleteBooking(bookingToCancel, plan.id, lang, cancelReason)
|
||||
toast.success(dict.cancelSuccess)
|
||||
setIsCancelDialogOpen(false)
|
||||
setBookingToCancel(null)
|
||||
} catch {
|
||||
toast.error(dict.cancelError)
|
||||
} finally {
|
||||
setIsSubmitting(false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,7 +182,7 @@ export function PlanDashboard({ plan, dict, settingsDict, lang }: PlanDashboardP
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-6 w-6 -mr-2 -mt-2 opacity-50 hover:opacity-100 text-destructive"
|
||||
onClick={() => handleCancel(booking.id)}
|
||||
onClick={() => handleCancelClick(booking.id)}
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
<span className="sr-only">Remove</span>
|
||||
@@ -245,6 +259,40 @@ export function PlanDashboard({ plan, dict, settingsDict, lang }: PlanDashboardP
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Cancellation Dialog */}
|
||||
<Dialog open={isCancelDialogOpen} onOpenChange={setIsCancelDialogOpen}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{dict.cancelTitle}</DialogTitle>
|
||||
<DialogDescription>
|
||||
{dict.cancelConfirm}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
{plan.webhookUrl && (
|
||||
<div className="grid gap-2 py-4">
|
||||
<Label htmlFor="reason">{dict.cancelMessageLabel}</Label>
|
||||
<Input
|
||||
id="reason"
|
||||
value={cancelReason}
|
||||
onChange={(e) => setCancelReason(e.target.value)}
|
||||
placeholder={dict.cancelMessagePlaceholder}
|
||||
autoFocus
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<DialogFooter>
|
||||
<Button variant="outline" onClick={() => setIsCancelDialogOpen(false)} disabled={isSubmitting}>
|
||||
{dict.cancel}
|
||||
</Button>
|
||||
<Button variant="destructive" onClick={handleConfirmCancel} disabled={isSubmitting}>
|
||||
{isSubmitting ? dict.saving : dict.cancelSubmit}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ export async function createBooking(planId: string, date: Date, name: string, ty
|
||||
revalidatePath(`/${lang}/dashboard/${planId}`)
|
||||
}
|
||||
|
||||
export async function deleteBooking(bookingId: number, planId: string, lang: string = "en") {
|
||||
export async function deleteBooking(bookingId: number, planId: string, lang: string = "en", reason?: string) {
|
||||
const dict = await getDictionary(lang as any)
|
||||
|
||||
const booking = await prisma.booking.findUnique({
|
||||
@@ -70,10 +70,12 @@ export async function deleteBooking(bookingId: number, planId: string, lang: str
|
||||
const planUrl = `${protocol}://${host}/${lang}/dashboard/${planId}`
|
||||
|
||||
const dateStr = booking.date.toLocaleDateString(lang)
|
||||
const messageDisplay = reason ? `\nMessage: ${reason}` : ""
|
||||
const message = dict.notifications.cancellation
|
||||
.replace("{name}", booking.sitterName || "Someone")
|
||||
.replace("{date}", dateStr)
|
||||
.replace("{url}", planUrl)
|
||||
.replace("{message}", messageDisplay)
|
||||
|
||||
await sendNotification(booking.plan.webhookUrl, message)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user