282 lines
7.8 KiB
JavaScript
282 lines
7.8 KiB
JavaScript
/**
|
|
* Fonctions utilitaires pour récupérer des données depuis WordPress REST API
|
|
* Compatible avec Next.js (client et serveur)
|
|
*/
|
|
|
|
const WORDPRESS_API_BASE = "https://deligraph.com/wp-json/wp/v2";
|
|
const PORTFOLIO_ENDPOINT = `${WORDPRESS_API_BASE}/portfolio`;
|
|
|
|
/**
|
|
* Construit une URL avec des paramètres de requête
|
|
* @param {string} baseUrl - URL de base
|
|
* @param {Object} params - Paramètres de requête
|
|
* @returns {string} URL complète avec paramètres
|
|
*/
|
|
function buildUrl(baseUrl, params = {}) {
|
|
const url = new URL(baseUrl);
|
|
Object.keys(params).forEach((key) => {
|
|
if (params[key] !== undefined && params[key] !== null) {
|
|
url.searchParams.append(key, params[key]);
|
|
}
|
|
});
|
|
return url.toString();
|
|
}
|
|
|
|
/**
|
|
* Récupère les informations d'un média WordPress par son ID
|
|
* @param {number} mediaId - ID du média WordPress
|
|
* @param {Object} fetchOptions - Options supplémentaires pour fetch
|
|
* @returns {Promise<string|null>} URL de l'image ou null si non trouvé
|
|
*/
|
|
export async function fetchMedia(mediaId, fetchOptions = {}) {
|
|
if (!mediaId) {
|
|
return null;
|
|
}
|
|
|
|
const url = `${WORDPRESS_API_BASE}/media/${mediaId}`;
|
|
|
|
try {
|
|
const response = await fetch(url, {
|
|
...fetchOptions,
|
|
});
|
|
|
|
if (!response.ok) {
|
|
if (response.status === 404) {
|
|
return null;
|
|
}
|
|
throw new Error(`Erreur HTTP: ${response.status} - ${response.statusText}`);
|
|
}
|
|
|
|
const data = await response.json();
|
|
// Retourner l'URL source de l'image
|
|
return data.source_url || null;
|
|
} catch (error) {
|
|
console.error(`Erreur lors de la récupération du média ID "${mediaId}":`, error);
|
|
return null; // Retourner null au lieu de throw pour éviter de casser le rendu
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère les posts de type portfolio depuis WordPress
|
|
* @param {Object} options - Options de récupération
|
|
* @param {number} options.perPage - Nombre de posts par page (défaut: 10)
|
|
* @param {number} options.page - Numéro de page (défaut: 1)
|
|
* @param {string} options.search - Terme de recherche
|
|
* @param {number} options.categories - ID de catégorie
|
|
* @param {string} options.order - Ordre de tri (asc/desc, défaut: desc)
|
|
* @param {string} options.orderby - Champ de tri (date, title, etc., défaut: date)
|
|
* @param {Object} options.fetchOptions - Options supplémentaires pour fetch (utile pour revalidate côté serveur)
|
|
* @returns {Promise<Array>} Tableau de posts portfolio
|
|
*/
|
|
export async function fetchPortfolioPosts(options = {}) {
|
|
const {
|
|
perPage = 10,
|
|
page = 1,
|
|
search,
|
|
categories,
|
|
order = "desc",
|
|
orderby = "date",
|
|
fetchOptions = {},
|
|
} = options;
|
|
|
|
const params = {
|
|
per_page: perPage,
|
|
page: page,
|
|
order: order,
|
|
orderby: orderby,
|
|
};
|
|
|
|
if (search) {
|
|
params.search = search;
|
|
}
|
|
|
|
if (categories) {
|
|
params.categories = categories;
|
|
}
|
|
|
|
const url = buildUrl(PORTFOLIO_ENDPOINT, params);
|
|
|
|
try {
|
|
const response = await fetch(url, {
|
|
...fetchOptions,
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`Erreur HTTP: ${response.status} - ${response.statusText}`);
|
|
}
|
|
|
|
const data = await response.json();
|
|
|
|
// Récupérer les images de couverture pour chaque post en parallèle
|
|
const postsWithImages = await Promise.all(
|
|
data.map(async (post) => {
|
|
if (post.featured_media) {
|
|
try {
|
|
const mediaUrl = await fetchMedia(post.featured_media, fetchOptions);
|
|
return { ...post, featuredImageUrl: mediaUrl };
|
|
} catch (error) {
|
|
console.error(`Erreur lors de la récupération de l'image pour le post ${post.id}:`, error);
|
|
return { ...post, featuredImageUrl: null };
|
|
}
|
|
}
|
|
return { ...post, featuredImageUrl: null };
|
|
}),
|
|
);
|
|
|
|
return {
|
|
posts: postsWithImages,
|
|
totalPages: parseInt(response.headers.get("X-WP-TotalPages") || "1", 10),
|
|
total: parseInt(response.headers.get("X-WP-Total") || "0", 10),
|
|
};
|
|
} catch (error) {
|
|
console.error("Erreur lors de la récupération des posts portfolio:", error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère un post portfolio spécifique par son slug
|
|
* @param {string} slug - Slug du post
|
|
* @param {Object} fetchOptions - Options supplémentaires pour fetch
|
|
* @returns {Promise<Object|null>} Post portfolio ou null si non trouvé
|
|
*/
|
|
export async function fetchPortfolioPostBySlug(slug, fetchOptions = {}) {
|
|
if (!slug) {
|
|
throw new Error("Le slug est requis");
|
|
}
|
|
|
|
const url = buildUrl(PORTFOLIO_ENDPOINT, { slug });
|
|
console.log("URL de recherche:", url);
|
|
|
|
try {
|
|
const response = await fetch(url, {
|
|
...fetchOptions,
|
|
});
|
|
|
|
console.log("Statut de la réponse:", response.status, response.statusText);
|
|
|
|
if (!response.ok) {
|
|
if (response.status === 404) {
|
|
console.log("Aucun post trouvé avec le paramètre slug, tentative avec fallback...");
|
|
// Fallback: récupérer tous les posts et filtrer par slug
|
|
return await fetchPortfolioPostBySlugFallback(slug, fetchOptions);
|
|
}
|
|
throw new Error(`Erreur HTTP: ${response.status} - ${response.statusText}`);
|
|
}
|
|
|
|
const data = await response.json();
|
|
console.log(
|
|
"Données reçues:",
|
|
Array.isArray(data) ? `${data.length} résultat(s)` : "Format inattendu",
|
|
data,
|
|
);
|
|
|
|
// L'API WordPress retourne un tableau même pour un seul résultat
|
|
if (Array.isArray(data)) {
|
|
if (data.length > 0) {
|
|
return data[0];
|
|
}
|
|
// Si le tableau est vide, essayer le fallback
|
|
console.log("Tableau vide, tentative avec fallback...");
|
|
return await fetchPortfolioPostBySlugFallback(slug, fetchOptions);
|
|
}
|
|
|
|
// Si ce n'est pas un tableau, retourner directement (cas où l'API retourne un objet unique)
|
|
return data;
|
|
} catch (error) {
|
|
console.error(`Erreur lors de la récupération du post portfolio "${slug}":`, error);
|
|
// En cas d'erreur, essayer le fallback
|
|
try {
|
|
return await fetchPortfolioPostBySlugFallback(slug, fetchOptions);
|
|
} catch {
|
|
throw error; // Relancer l'erreur originale
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fallback: récupère tous les posts et filtre par slug
|
|
* @param {string} slug - Slug du post
|
|
* @param {Object} fetchOptions - Options supplémentaires pour fetch
|
|
* @returns {Promise<Object|null>} Post portfolio ou null si non trouvé
|
|
*/
|
|
async function fetchPortfolioPostBySlugFallback(slug, fetchOptions = {}) {
|
|
console.log("Utilisation du fallback pour le slug:", slug);
|
|
try {
|
|
const allPosts = await fetchAllPortfolioPosts({ fetchOptions });
|
|
const post = allPosts.find((p) => p.slug === slug);
|
|
|
|
if (post) {
|
|
console.log("Post trouvé via fallback");
|
|
return post;
|
|
}
|
|
|
|
console.log("Aucun post trouvé avec le slug:", slug);
|
|
return null;
|
|
} catch (error) {
|
|
console.error("Erreur dans le fallback:", error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère un post portfolio par son ID
|
|
* @param {number} id - ID du post
|
|
* @param {Object} fetchOptions - Options supplémentaires pour fetch
|
|
* @returns {Promise<Object|null>} Post portfolio ou null si non trouvé
|
|
*/
|
|
export async function fetchPortfolioPostById(id, fetchOptions = {}) {
|
|
if (!id) {
|
|
throw new Error("L'ID est requis");
|
|
}
|
|
|
|
const url = `${PORTFOLIO_ENDPOINT}/${id}`;
|
|
|
|
try {
|
|
const response = await fetch(url, {
|
|
...fetchOptions,
|
|
});
|
|
|
|
if (!response.ok) {
|
|
if (response.status === 404) {
|
|
return null;
|
|
}
|
|
throw new Error(`Erreur HTTP: ${response.status} - ${response.statusText}`);
|
|
}
|
|
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error(`Erreur lors de la récupération du post portfolio ID "${id}":`, error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère tous les posts portfolio (sans pagination)
|
|
* @param {Object} options - Options de récupération (mêmes que fetchPortfolioPosts)
|
|
* @returns {Promise<Array>} Tableau de tous les posts portfolio
|
|
*/
|
|
export async function fetchAllPortfolioPosts(options = {}) {
|
|
const allPosts = [];
|
|
let page = 1;
|
|
let hasMore = true;
|
|
|
|
while (hasMore) {
|
|
const result = await fetchPortfolioPosts({
|
|
...options,
|
|
page,
|
|
perPage: 100, // Maximum recommandé par WordPress REST API
|
|
});
|
|
|
|
allPosts.push(...result.posts);
|
|
|
|
if (page >= result.totalPages) {
|
|
hasMore = false;
|
|
} else {
|
|
page++;
|
|
}
|
|
}
|
|
|
|
return allPosts;
|
|
}
|