@mytec: iter9.1 ready for test

This commit is contained in:
2026-01-30 15:08:08 +02:00
parent 79d32c9d30
commit 7ad59df69d
5 changed files with 249 additions and 109 deletions

View File

@@ -3,6 +3,7 @@ import type { Site } from '@/types/index.ts';
import { useSitesStore } from '@/store/sites.ts';
import { useToastStore } from '@/components/ui/Toast.tsx';
import Button from '@/components/ui/Button.tsx';
import ConfirmDialog from '@/components/ui/ConfirmDialog.tsx';
import BatchEdit from './BatchEdit.tsx';
interface SiteListProps {
@@ -58,10 +59,49 @@ export default function SiteList({ onEditSite, onAddSite }: SiteListProps) {
setTimeout(() => setFlashIds(new Set()), 700);
}, []);
const handleDelete = async (id: string, name: string) => {
// Delete confirmation dialog state
const [deleteTarget, setDeleteTarget] = useState<{ id: string; name: string } | null>(null);
const handleDeleteConfirmed = useCallback(async () => {
if (!deleteTarget) return;
const { id, name } = deleteTarget;
// Snapshot the site data before deleting (for undo)
const siteData = sites.find((s) => s.id === id);
setDeleteTarget(null);
await deleteSite(id);
addToast(`"${name}" deleted`, 'info');
};
// Toast with undo action
if (siteData) {
addToast(`"${name}" deleted`, 'info', {
duration: 10000,
action: {
label: 'Undo',
onClick: async () => {
// Restore the deleted site
await useSitesStore.getState().addSite({
name: siteData.name,
lat: siteData.lat,
lon: siteData.lon,
height: siteData.height,
power: siteData.power,
gain: siteData.gain,
frequency: siteData.frequency,
antennaType: siteData.antennaType,
azimuth: siteData.azimuth,
beamwidth: siteData.beamwidth,
color: siteData.color,
visible: siteData.visible,
notes: siteData.notes,
equipment: siteData.equipment,
});
addToast(`"${name}" restored`, 'success');
},
},
});
}
}, [deleteTarget, sites, deleteSite, addToast]);
const allSelected = sites.length > 0 && selectedSiteIds.length === sites.length;
@@ -148,7 +188,7 @@ export default function SiteList({ onEditSite, onAddSite }: SiteListProps) {
<button
onClick={(e) => {
e.stopPropagation();
handleDelete(site.id, site.name);
setDeleteTarget({ id: site.id, name: site.name });
}}
className="px-2 py-1 text-xs text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 rounded min-w-[32px] min-h-[32px] flex items-center justify-center"
title="Delete site"
@@ -245,6 +285,18 @@ export default function SiteList({ onEditSite, onAddSite }: SiteListProps) {
})}
</div>
)}
{/* Delete confirmation dialog */}
{deleteTarget && (
<ConfirmDialog
title="Delete Site?"
message={`Are you sure you want to delete "${deleteTarget.name}"? This action can be undone for 10 seconds.`}
confirmLabel="Delete"
cancelLabel="Cancel"
danger
onConfirm={handleDeleteConfirmed}
onCancel={() => setDeleteTarget(null)}
/>
)}
</div>
);
}