63 lines
2.1 KiB
JavaScript
63 lines
2.1 KiB
JavaScript
// resources/js/composables/usePageData.js
|
|
import { ref } from 'vue';
|
|
import axios from 'axios';
|
|
import { usePrefetchStore } from '../stores/prefetch';
|
|
|
|
export default function usePageData() {
|
|
const data = ref(null);
|
|
const loading = ref(false);
|
|
const error = ref(false);
|
|
const stale = ref(false);
|
|
const prefetchStore = usePrefetchStore();
|
|
|
|
/**
|
|
* Fetch page data with Cache-First strategy.
|
|
* Checks persistent prefetchStore before hitting network.
|
|
*/
|
|
const fetchPageData = async (url, payload = {}, method = 'GET') => {
|
|
loading.value = true;
|
|
error.value = false;
|
|
stale.value = false;
|
|
|
|
const cacheKey = `${method.toUpperCase()}:${url}:${JSON.stringify(payload)}`;
|
|
|
|
// 1. Try to get cached data first (Persistent & 6-month valid)
|
|
if (prefetchStore.hasCache(cacheKey)) {
|
|
data.value = prefetchStore.getCache(cacheKey);
|
|
stale.value = true;
|
|
loading.value = false; // We have SOMETHING to show immediately
|
|
}
|
|
|
|
try {
|
|
// 2. Fetch fresh data from network
|
|
let response;
|
|
if (method.toUpperCase() === 'POST') {
|
|
response = await axios.post(url, payload);
|
|
} else {
|
|
response = await axios.get(url, { params: payload });
|
|
}
|
|
|
|
if (response.data) {
|
|
// Adapt to backend format (Inertia-like or raw)
|
|
const freshData = response.data.props || response.data;
|
|
data.value = freshData;
|
|
|
|
// 3. Update persistent cache
|
|
prefetchStore.setCache(cacheKey, freshData);
|
|
stale.value = false;
|
|
}
|
|
} catch (err) {
|
|
console.warn(`[usePageData] Failed to fetch fresh data for ${url}:`, err);
|
|
if (!data.value) {
|
|
error.value = true;
|
|
}
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
|
|
return { data: data.value, error: error.value, stale: stale.value };
|
|
};
|
|
|
|
return { data, loading, error, stale, fetchPageData };
|
|
}
|