Block self-service payment and cancellation on closed/past registrations
Extends the earlier user-dashboard fix: canEditActive is renamed canModifyActive and now also gates the "Make payment" and "Cancel registration" actions, not just editing. Backend enforcement added to cancelRegistration and createYocoCheckout to block past-event self-service payment/cancellation server-side (cashup-closed events were already blocked via assertEventOpen; admins/supervisors are exempt from the past-date check, consistent with existing overrides). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -447,7 +447,9 @@ export default function UserDashboardPage() {
|
||||
const [editMinQty, setEditMinQty] = useState<Record<string, number>>({});
|
||||
const [editError, setEditError] = useState<string | null>(null);
|
||||
|
||||
const canEditActive = useMemo(() => {
|
||||
// Whether the active registration's event still permits self-service changes
|
||||
// (edit items, pay, cancel) — false once the event is past or its cashup is closed.
|
||||
const canModifyActive = useMemo(() => {
|
||||
if (!activeReg) return false;
|
||||
return !isEventOver(activeReg.event);
|
||||
}, [activeReg]);
|
||||
@@ -847,7 +849,7 @@ export default function UserDashboardPage() {
|
||||
<div>
|
||||
<div className="font-medium mb-1 flex items-center justify-between">
|
||||
<span>Registration items</span>
|
||||
{!editMode && canEditActive && (
|
||||
{!editMode && canModifyActive && (
|
||||
<button disabled={editLoading} onClick={beginEdit} className="px-2.5 py-1 text-xs bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50">Edit</button>
|
||||
)}
|
||||
</div>
|
||||
@@ -987,7 +989,7 @@ export default function UserDashboardPage() {
|
||||
onClick={() => router.push(`/dashboard/user/forms?registrationId=${encodeURIComponent(activeReg.id)}`)}
|
||||
>Attendee forms</button>
|
||||
)}
|
||||
{activeBill && activeBill.outstanding > 0 ? (
|
||||
{canModifyActive && activeBill && activeBill.outstanding > 0 ? (
|
||||
<button
|
||||
className="px-3 py-1.5 text-sm bg-green-600 text-white rounded hover:bg-green-700 shadow-sm focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-1"
|
||||
onClick={() => router.push(`/dashboard/user/pay?registrationId=${encodeURIComponent(activeReg.id)}`)}
|
||||
@@ -1007,8 +1009,8 @@ export default function UserDashboardPage() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Cancel registration — only shown when no payments have been made */}
|
||||
{activeReg.status !== 'cancelled' && (activeBill?.totalPaid ?? 0) === 0 && (
|
||||
{/* Cancel registration — only shown when no payments have been made and the event still permits changes */}
|
||||
{canModifyActive && activeReg.status !== 'cancelled' && (activeBill?.totalPaid ?? 0) === 0 && (
|
||||
<div className="pt-3 border-t mt-1">
|
||||
{!showCancelConfirm ? (
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user