Files
2026-06-06 18:43:00 +08:00

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 };
}