fix(ui): подтверждать удаление правил Filters
This commit is contained in:
1 parent
8412ba9bbe
commit
c4011cfaff
6 files changed
+154
-19
No files matched your search
@@ -32,6 +32,7 @@ import {
|
||||
import {
|
||||
Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetFooter,
|
||||
} from "@/components/ui/sheet"
|
||||
import { AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction } from "@/components/ui/alert-dialog"
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { toast } from "sonner"
|
||||
@@ -1356,6 +1357,10 @@ export default function FiltersPage() {
|
||||
const [copyOpen, setCopyOpen] = useState(false)
|
||||
const [applyBusy, setApplyBusy] = useState(false)
|
||||
const applyLock = useRef(false)
|
||||
const [pendingDelete, setPendingDelete] = useState<{ serverId: string; serverName: string; rule: FilterRule } | null>(null)
|
||||
const [deletePending, setDeletePending] = useState(false)
|
||||
const [deleteError, setDeleteError] = useState<string | null>(null)
|
||||
const deleteLock = useRef(false)
|
||||
const [liveStale, setLiveStale] = useState(false)
|
||||
const [historyOpen, setHistoryOpen] = useState(false)
|
||||
const [historyLoading, setHistoryLoading] = useState(false)
|
||||
@@ -1472,6 +1477,8 @@ export default function FiltersPage() {
|
||||
const handleSelectServer = useCallback((id: string) => {
|
||||
if (applyLock.current) return
|
||||
setSheetOpen(false)
|
||||
setPendingDelete(null)
|
||||
setDeleteError(null)
|
||||
setSelectedServerId(id)
|
||||
setSearch("")
|
||||
}, [])
|
||||
@@ -1632,8 +1639,36 @@ export default function FiltersPage() {
|
||||
}
|
||||
|
||||
const handleDelete = (id: string) => {
|
||||
if (mutationsLocked) return
|
||||
updateRules(selectedServerId, rules => rules.filter(r => r.id !== id))
|
||||
if (mutationsLocked || applyLock.current) return
|
||||
const rule = currentRules.find(r => r.id === id)
|
||||
if (!rule || !selectedServer) return
|
||||
setDeleteError(null)
|
||||
setPendingDelete({ serverId: selectedServerId, serverName: selectedServer.name, rule })
|
||||
}
|
||||
const confirmDelete = async () => {
|
||||
if (!pendingDelete || deleteLock.current) return
|
||||
if (mutationsLocked || applyLock.current) {
|
||||
setDeleteError("Дождитесь завершения операции или обновите данные")
|
||||
return
|
||||
}
|
||||
const current = rulesets.find(rs => rs.serverId === pendingDelete.serverId)?.rules
|
||||
if (!current?.some(r => r.id === pendingDelete.rule.id)) {
|
||||
setDeleteError("Правило отсутствует в текущем списке — обновите данные")
|
||||
return
|
||||
}
|
||||
deleteLock.current = true
|
||||
setDeletePending(true)
|
||||
setDeleteError(null)
|
||||
try {
|
||||
const result = await applyRules(pendingDelete.serverId, current.filter(r => r.id !== pendingDelete.rule.id))
|
||||
if (!result.ok) setDeleteError(result.error ?? "Не удалось удалить правило")
|
||||
else setPendingDelete(null)
|
||||
} catch (error) {
|
||||
setDeleteError(error instanceof Error ? error.message : "Не удалось удалить правило")
|
||||
} finally {
|
||||
deleteLock.current = false
|
||||
setDeletePending(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleCopyRules = useCallback(async (targetServerId: string, rules: FilterRule[], mode: CopyMode) => {
|
||||
@@ -1884,6 +1919,26 @@ export default function FiltersPage() {
|
||||
</div>
|
||||
</ServerRailLayout>
|
||||
|
||||
<AlertDialog open={!!pendingDelete} onOpenChange={open => {
|
||||
if (!open && !deleteLock.current) { setPendingDelete(null); setDeleteError(null) }
|
||||
}}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Удалить правило Filters?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
Community {pendingDelete?.rule.community} · {pendingDelete?.serverName}.
|
||||
Правило будет удалено из набора фильтров устройства.
|
||||
</AlertDialogDescription>
|
||||
{deletePending && <p role="status" className="text-sm text-muted-foreground">Ожидание подтверждения удаления…</p>}
|
||||
{deleteError && <p role="alert" className="text-sm text-destructive">{deleteError}</p>}
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel disabled={deletePending}>Отмена</AlertDialogCancel>
|
||||
<AlertDialogAction variant="destructive" disabled={deletePending || mutationsLocked} onClick={e => { e.preventDefault(); void confirmDelete() }}>Удалить</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
|
||||
<RuleSheet
|
||||
key={`${sheetOpen}-${sheetMode}-${editingId ?? "new"}-${selectedServerId}`}
|
||||
open={sheetOpen}
|
||||
|
||||
Reference in new issue
Block a user