49 lines
1.5 KiB
TypeScript
49 lines
1.5 KiB
TypeScript
import { ref, onMounted, onUnmounted, type Ref } from 'vue'
|
|
import axios from 'axios'
|
|
import { api } from '@/api'
|
|
import { SharedProps } from "@/Types/types"
|
|
import { usePage } from "@inertiajs/vue3"
|
|
|
|
interface UseApiResourceReturn<T> {
|
|
data: Ref<T | null>
|
|
loading: Ref<boolean>
|
|
error: Ref<string | null>
|
|
refresh: () => Promise<void>
|
|
}
|
|
|
|
export function useApiResource<T>(route: string, immediate = true): UseApiResourceReturn<T> {
|
|
const page = usePage<SharedProps>() // resolved when the composable runs, inside setup()
|
|
|
|
const data = ref<T | null>(null) as Ref<T | null>
|
|
const loading = ref(true)
|
|
const error = ref<string | null>(null)
|
|
|
|
let controller = new AbortController()
|
|
|
|
async function refresh() {
|
|
controller.abort()
|
|
controller = new AbortController()
|
|
loading.value = true
|
|
error.value = null
|
|
|
|
// build the url here too, so it always reflects current page props
|
|
const url = `${page.props.logo_api_url}${route}`
|
|
try {
|
|
const response = await api.get<T>(url, { signal: controller.signal })
|
|
data.value = response.data
|
|
} catch (e) {
|
|
if (!axios.isCancel(e)) {
|
|
error.value = 'Failed to load data'
|
|
console.error(e)
|
|
}
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
if (immediate) onMounted(refresh)
|
|
onUnmounted(() => controller.abort())
|
|
|
|
return { data, loading, error, refresh }
|
|
}
|