From 72fdd270964041e6a67208ff0a39ae528327846f Mon Sep 17 00:00:00 2001 From: kurt-croix Date: Thu, 30 Apr 2026 15:04:44 -0500 Subject: [PATCH] fix: defer AlertDialog open so DropdownMenu closes first Root cause: clicking Delete in DropdownMenu immediately set deletingReport, opening AlertDialog while DropdownMenu's DismissableLayer was still active. The two radix layers conflicted, leaving pointer-events blocked after close. Fix: setTimeout(0) on the onDelete callback so the DropdownMenu finishes its close animation before AlertDialog opens. Also simplifies back to direct fire-and-forget delete (no pendingDelete/useEffect needed). --- src/lib/constants.ts | 2 +- src/pages/ReportList.tsx | 31 ++++++++++--------------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/lib/constants.ts b/src/lib/constants.ts index 5298a9e..80e9719 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -1,6 +1,6 @@ // FtheRoads.com - Constants import yaml from 'js-yaml'; -// @ts-expect-error — Vite ?raw import returns file content as string +// @ts-ignore — Vite ?raw import returns file content as string import configRaw from '../../config.yaml?raw'; /** Nostr event kind for road hazard reports */ diff --git a/src/pages/ReportList.tsx b/src/pages/ReportList.tsx index aaf4480..0eaabe4 100644 --- a/src/pages/ReportList.tsx +++ b/src/pages/ReportList.tsx @@ -1,4 +1,4 @@ -import { useState, useMemo, useEffect } from 'react'; +import { useState, useMemo } from 'react'; import { useRoadReports } from '@/hooks/useRoadReports'; import { useDeleteReport, useEditReport } from '@/hooks/useReportMutations'; import { ReportCard } from '@/components/ReportCard'; @@ -39,20 +39,10 @@ export function ReportListPage() { const [editingReport, setEditingReport] = useState(null); const [deletingReport, setDeletingReport] = useState(null); - const [pendingDelete, setPendingDelete] = useState(null); const deleteReport = useDeleteReport(); const editReport = useEditReport(); - // Fire-and-forget delete after dialog closes - useEffect(() => { - if (pendingDelete) { - const report = pendingDelete; - setPendingDelete(null); - deleteReport(report).catch(console.error); - } - }, [pendingDelete, deleteReport]); - const filteredReports = useMemo(() => { if (!reports) return []; @@ -216,7 +206,12 @@ export function ReportListPage() { onClick={() => navigate(`/report/${report.id}`)} onShowOnMap={(lat, lng) => navigate(`/?lat=${lat}&lng=${lng}`)} onEdit={(r) => setEditingReport(r)} - onDelete={(r) => setDeletingReport(r)} + onDelete={(r) => { + // Defer so DropdownMenu finishes closing before AlertDialog opens. + // Without this, radix's DismissableLayer from the dropdown conflicts + // with the AlertDialog's layer, blocking pointer events after close. + setTimeout(() => setDeletingReport(r), 0); + }} /> )) )} @@ -231,14 +226,7 @@ export function ReportListPage() { /> {/* Delete Confirmation */} - { - if (!open) { - setDeletingReport(null); - } - }} - > + { if (!open) setDeletingReport(null); }}> Delete Report @@ -251,8 +239,9 @@ export function ReportListPage() { { if (deletingReport) { - setPendingDelete(deletingReport); + const report = deletingReport; setDeletingReport(null); + deleteReport(report).catch(console.error); } }} className="bg-red-500 hover:bg-red-600 text-white"