Activity tab: confirm-dialog Cancel on registered/waitlisted class signups (cancelMySignup) and reserved equipment reservations (cancelReservation) via the existing actions. Reusable CancelAction (AlertDialog + toast + refresh). Buttons only shown on cancellable states; the actions still enforce ownership/space scoping server-side. 521 tests; build clean (UI not browser-tested from here).
64 lines
1.7 KiB
TypeScript
64 lines
1.7 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
import { useRouter } from 'next/navigation'
|
|
import { toast } from 'sonner'
|
|
import { Button } from '@/components/ui/button'
|
|
import {
|
|
AlertDialog,
|
|
AlertDialogTrigger,
|
|
AlertDialogContent,
|
|
AlertDialogHeader,
|
|
AlertDialogFooter,
|
|
AlertDialogTitle,
|
|
AlertDialogDescription,
|
|
AlertDialogAction,
|
|
AlertDialogCancel,
|
|
} from '@/components/ui/alert-dialog'
|
|
|
|
// Confirm-then-run wrapper for a self-serve cancel. The action returns the
|
|
// project-standard { error } | { data/success } shape.
|
|
export function CancelAction({
|
|
title,
|
|
description,
|
|
action,
|
|
successMessage,
|
|
}: {
|
|
title: string
|
|
description: string
|
|
action: () => Promise<{ error?: string } | Record<string, unknown>>
|
|
successMessage: string
|
|
}) {
|
|
const router = useRouter()
|
|
const [busy, setBusy] = useState(false)
|
|
|
|
async function run() {
|
|
setBusy(true)
|
|
const res = await action()
|
|
setBusy(false)
|
|
if (res && 'error' in res && res.error) return toast.error(res.error as string)
|
|
toast.success(successMessage)
|
|
router.refresh()
|
|
}
|
|
|
|
return (
|
|
<AlertDialog>
|
|
<AlertDialogTrigger asChild>
|
|
<Button size="sm" variant="outline" disabled={busy}>
|
|
{busy ? 'Cancelling…' : 'Cancel'}
|
|
</Button>
|
|
</AlertDialogTrigger>
|
|
<AlertDialogContent>
|
|
<AlertDialogHeader>
|
|
<AlertDialogTitle>{title}</AlertDialogTitle>
|
|
<AlertDialogDescription>{description}</AlertDialogDescription>
|
|
</AlertDialogHeader>
|
|
<AlertDialogFooter>
|
|
<AlertDialogCancel>Keep it</AlertDialogCancel>
|
|
<AlertDialogAction onClick={run}>Cancel it</AlertDialogAction>
|
|
</AlertDialogFooter>
|
|
</AlertDialogContent>
|
|
</AlertDialog>
|
|
)
|
|
}
|