import { ref, shallowRef, type Ref } from 'vue' import { ApiError } from '@/api/client' import { errorMessage } from './format' // A view's data: what was loaded, whether it is loading, and why it failed. // A reload keeps the old data on screen until the new data is in. export function useLoad(fn: () => Promise) { const data = shallowRef() as Ref const loading = ref(false) const error = ref('') const status = ref(0) let seq = 0 async function load() { const mine = ++seq loading.value = true error.value = '' try { const value = await fn() if (mine === seq) { data.value = value status.value = 200 } } catch (e) { if (mine === seq) { error.value = errorMessage(e) status.value = e instanceof ApiError ? e.status : 0 } } finally { if (mine === seq) loading.value = false } } return { data, loading, error, status, load } } /** Runs an action and tracks whether it is running; returns whether it worked. */ export function useAction() { const busy = ref(false) const error = ref('') async function run(fn: () => Promise): Promise { busy.value = true error.value = '' try { await fn() return true } catch (e) { error.value = errorMessage(e) return false } finally { busy.value = false } } return { busy, error, run } }