import { onBeforeUnmount, ref, watch } from 'vue' import { onBeforeRouteLeave } from 'vue-router' export type BulkOperationType = 'enable' | 'disable' | 'delete' | 'update' export function useBulkOperation() { const isBulkOperating = ref(false) const bulkProgress = ref(0) const bulkTotal = ref(0) const bulkOperation = ref(null) const bulkWaiting = ref(false) function resetState() { isBulkOperating.value = false bulkOperation.value = null bulkProgress.value = 0 bulkTotal.value = 0 bulkWaiting.value = false } async function runBulk( operation: BulkOperationType, items: T[], fn: (item: T) => Promise, options?: { delayMs?: number; onComplete?: () => void }, ) { const delayMs = options?.delayMs ?? 250 isBulkOperating.value = true bulkOperation.value = operation bulkTotal.value = items.length bulkProgress.value = 0 try { for (const item of items) { await fn(item) bulkProgress.value++ if (delayMs > 0 && bulkProgress.value < items.length) { await new Promise((resolve) => setTimeout(resolve, delayMs)) } } } finally { options?.onComplete?.() resetState() } } async function runBulkWithWaiting( operation: BulkOperationType, total: number, fn: () => Promise, onComplete?: () => void, ) { isBulkOperating.value = true bulkOperation.value = operation bulkTotal.value = total bulkProgress.value = 0 bulkWaiting.value = true try { await fn() } finally { onComplete?.() resetState() } } function handleBeforeUnload(e: BeforeUnloadEvent) { if (isBulkOperating.value) { e.preventDefault() return '' } } if (typeof window !== 'undefined') { watch(isBulkOperating, (operating) => { if (operating) { window.addEventListener('beforeunload', handleBeforeUnload) } else { window.removeEventListener('beforeunload', handleBeforeUnload) } }) onBeforeUnmount(() => { window.removeEventListener('beforeunload', handleBeforeUnload) }) onBeforeRouteLeave(() => { if (isBulkOperating.value) { return window.confirm('A bulk operation is in progress. Are you sure you want to leave?') } return true }) } return { isBulkOperating, bulkProgress, bulkTotal, bulkOperation, bulkWaiting, runBulk, runBulkWithWaiting, } }