57 lines
1.5 KiB
TypeScript
57 lines
1.5 KiB
TypeScript
import { ref } from 'vue'
|
|
import { useToast } from '@/composables/useToast'
|
|
|
|
export function mockPersistToggle(delayMs = 480): Promise<void> {
|
|
return new Promise((resolve) => {
|
|
window.setTimeout(resolve, delayMs)
|
|
})
|
|
}
|
|
|
|
export function useAsyncToggle(options: {
|
|
onPersist: (value: boolean) => Promise<void>
|
|
successMessage?: (value: boolean) => string
|
|
errorMessage?: string
|
|
confirmOff?: () => Promise<boolean>
|
|
}) {
|
|
const loadingId = ref<string | null>(null)
|
|
const errorId = ref<string | null>(null)
|
|
const toast = useToast()
|
|
|
|
async function toggle(id: string, current: boolean): Promise<boolean> {
|
|
if (loadingId.value) return current
|
|
|
|
const next = !current
|
|
|
|
if (!next && options.confirmOff) {
|
|
const confirmed = await options.confirmOff()
|
|
if (!confirmed) return current
|
|
}
|
|
|
|
loadingId.value = id
|
|
errorId.value = null
|
|
const previous = current
|
|
|
|
try {
|
|
await options.onPersist(next)
|
|
toast.success(options.successMessage?.(next) ?? (next ? 'وضعیت فعال شد.' : 'وضعیت غیرفعال شد.'))
|
|
return next
|
|
} catch {
|
|
errorId.value = id
|
|
toast.error(options.errorMessage ?? 'بهروزرسانی وضعیت انجام نشد.')
|
|
return previous
|
|
} finally {
|
|
loadingId.value = null
|
|
}
|
|
}
|
|
|
|
function isLoading(id: string) {
|
|
return loadingId.value === id
|
|
}
|
|
|
|
function hasError(id: string) {
|
|
return errorId.value === id
|
|
}
|
|
|
|
return { toggle, isLoading, hasError }
|
|
}
|