// Log the start of the fetching process
console.log("start fetching...");
// Define the base URL of the headless blog
const siteURL = "http://localhost/headless-blog";
// Define HTML tag IDs for post title, content, and date
const postTitleHtmltagID = "#documentation-section--result__post_title";
const postContentHtmltagID = "#documentation-section--result__post_content";
const postDateHtmltagID = "#documentation-section--result__post_date";
// Extract the slug from the current URL
const slug = getUrlParameter(window.location.href);
// Fetch the post data using the slug
const post = await fetchPost(siteURL, slug);
// Log the fetched post data
console.log(post);
// Update the header title with the post title
document.getElementById("headerTitle").textContent = `${post.title} | Optim Finance`;
// Create a new div element to hold the post content
const postDivHtmlTemplate = document.createElement("div");
postDivHtmlTemplate.innerHTML = post.content;
// Hide the preloader once the content is ready
document.querySelector("#preloader").classList.add('d-none');
// Append the post content to the designated HTML element
document.querySelector(postContentHtmltagID).append(postDivHtmlTemplate);
// Update the post title in the designated HTML element
document.querySelector(postTitleHtmltagID).textContent = post.title;
// Format and display the post publication date
document.querySelector(postDateHtmltagID).textContent = `Publié le ${convertDateFormat(post.date)}`;
// Log the completion of the fetching process
console.log("done");
// Function to extract the blog name from the URL
function getUrlParameter(url) {
const urlObject = new URL(url);
const path = urlObject.pathname;
const segments = path.split("/");
const blogName = segments[segments.length - 1];
return blogName;
}
// Asynchronous function to fetch the post data from the GraphQL API
async function fetchPost(siteURL, slug) {
const myQuery = `
query getPostBySlug {
postBy(slug: "${slug}") {
featuredImage {
node {
title
sourceUrl
}
}
date
title
content
tags {
nodes {
name
}
}
}
}
`;
// Send a POST request to the GraphQL endpoint
const res = await fetch(`${siteURL}/graphql`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
query: myQuery,
}),
});
// Parse the JSON response
const json = await res.json();
// Return the post data
return json.data.postBy;
}
// Function to create a template for displaying post tags
function template(tags) {
return `
<div class="detail d-flex justify-content-between align-items-center gap-3">
<ul class="list-unstyled mb-0 d-flex gap-2">
${tags.nodes
.map(({ name }) => {
return `<li><span class="bg-D5D6D7 fs-14px px-2 py-1">${name}</span></li>`;
})
.join(" ")}
</ul>
<div class="d-flex gap-4 justify-content-end align-items-center">
<a href="#" class="text-danger text-decoration-none inter-700 fs-14px d-flex justify-content-between align-items-center gap-2"><img src="assets/icon_share.svg" alt="" class="19px"> Partager</a>
<a href="#" class="text-primary text-decoration-none inter-700 fs-14px d-flex justify-content-between align-items-center gap-2"><img src="assets/icon_save.svg" alt="" class="19px"> Enregistrer</a>
</div>
</div>
`;
}
// Function to convert date string into a formatted string in French
function convertDateFormat(dateString) {
// Step 1: Parse the date string
const date = new Date(dateString);
// Step 2: Extract date components
const day = date.getDate();
const monthIndex = date.getMonth(); // 0-11
const year = date.getFullYear();
// Step 3: Format the month in French
const monthsInFrench = [
"Janvier", "Février", "Mars", "Avril", "Mai", "Juin",
"Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"
];
const month = monthsInFrench[monthIndex];
// Step 4: Format the time
let hours = date.getHours();
const minutes = date.getMinutes();
const ampm = hours >= 12 ? 'pm' : 'am';
hours = hours % 12; // Convert to 12-hour format
hours = hours ? hours : 12; // the hour '0' should be '12'
const formattedTime = `${hours}:${minutes < 10 ? '0' + minutes : minutes} ${ampm}`;
// Step 5: Construct the final string
return `${day} ${month} ${year} ${formattedTime}`;
}
Created
November 21, 2024 21:15
-
-
Save bitardev/2e13acbe8e143f1360915b5c63fed000 to your computer and use it in GitHub Desktop.
Fetch Posts/Post by Name From Wordpress REST API using GraphQL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| function generate_post_json($post_id) { | |
| // Check if this is an autosave, if so, return | |
| if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { | |
| return; | |
| } | |
| $data = array( | |
| 'cache_revalidation_number' => rand(1,100) | |
| ); | |
| // Define the path for the JSON file | |
| $json_file_path = get_template_directory() . '/post-data.json'; | |
| // Generate the JSON file | |
| file_put_contents($json_file_path, json_encode($data)); | |
| } | |
| add_action('save_post', 'generate_post_json'); | |
// Start fetching process
console.log("start fetching...");
// Define the URL of the site and the container for displaying results
const siteURL = "http://localhost/headless-blog";
const containerID = "#documentation-section--result__list";
// Define the URL for revalidation data
const revalidationURL = "http://localhost/headless-blog/wp-content/themes/twentytwentyfive/post-data.json";
// Fetch the revalidation number
const revalidation = await getRevalidationNumber(revalidationURL);
// Retrieve cached posts and revalidation number from local storage
const cachedPosts = localStorage.getItem("posts");
const cachedRevalidation = parseInt(localStorage.getItem("revalidation"));
let posts = [];
// Check if cached posts are valid
if (cachedPosts && cachedRevalidation === revalidation) {
// Use cached posts if revalidation number matches
posts = JSON.parse(cachedPosts);
console.log("cached posts => ", posts);
} else {
// Fetch fresh posts if cache is invalid
posts = await fetchPosts(siteURL);
const postsString = JSON.stringify(posts);
// Store fetched posts and revalidation number in local storage
localStorage.setItem("posts", postsString);
localStorage.setItem("revalidation", parseInt(revalidation));
console.log("fresh posts => ", posts);
}
// Render posts to the webpage
posts.posts.nodes.map((post) => {
const postTemplate = postTemplateCard(post);
const postDivHtmlTemplate = document.createElement('div');
postDivHtmlTemplate.innerHTML = postTemplate;
document.querySelector(containerID).append(postDivHtmlTemplate);
});
// Indicate that fetching is complete
console.log("fetching done...");
// Function to fetch posts from the GraphQL endpoint
async function fetchPosts(siteURL) {
const myQuery = `
query getAllPosts {
posts {
nodes {
slug
title
categories {
nodes {
name
slug
}
}
excerpt
featuredImage {
node {
title
sourceUrl
}
}
status
tags {
nodes {
name
}
}
date
}
}
}
`;
// Make a POST request to fetch posts
const res = await fetch(`${siteURL}/graphql`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
query: myQuery,
}),
});
// Parse the response JSON
const json = await res.json();
// Return the posts data
return {
posts: json.data.posts,
};
}
// Function to get the revalidation number from the specified URL
async function getRevalidationNumber(revalidationURL) {
const res = await fetch(`${revalidationURL}`, {
method: "GET",
headers: { "Content-Type": "application/json" },
});
// Parse the response JSON
const json = await res.json();
// Return the cache revalidation number
return json.cache_revalidation_number;
}
// Function to create a post template card
function postTemplateCard({
categories,
date,
excerpt,
featuredImage,
slug,
status,
tags,
title,
}) {
return `
<div class="documentation-section--result__list--item d-flex flex-column align-items-start gap-3">
<div class="background w-100">
<a href="blog/${slug}"><img src="${featuredImage.node.sourceUrl}" alt="${featuredImage.node.title}" class="w-100 border"></a>
</div>
<a href="blog/${slug}" class="fs-24px text-424242 text-decoration-none inter-700 d-flex justify-content-between flex-wrap gap-2 align-items-center">${title} <span class="fs-14px text-gray opacity-50 inter-400">${convertDateFormat(date)}</span></a>
<p class="fs-20px text-757575 inter-400">${excerpt}</p>
<div class="detail d-flex justify-content-between align-items-center gap-3">
<ul class="list-unstyled mb-0 d-flex gap-2">
${tags.nodes.map(({ name }) => `<li><span class="bg-D5D6D7 fs-14px px-2 py-1">${name}</span></li>`).join(" ")}
</ul>
<div class="d-flex gap-4 justify-content-end align-items-center">
<a href="#" class="text-danger text-decoration-none inter-700 fs-14px d-flex justify-content-between align-items-center gap-2"><img src="assets/icon_share.svg" alt="" class="19px"> Partager</a>
<a href="#" class="text-primary text-decoration-none inter-700 fs-14px d-flex justify-content-between align-items-center gap-2"><img src="assets/icon_save.svg" alt="" class="19px"> Enregistrer</a>
</div>
</div>
</div>
`;
}
// Function to convert date format to a more readable string
function convertDateFormat(dateString) {
const date = new Date(dateString);
const day = date.getDate();
const monthIndex = date.getMonth();
const year = date.getFullYear();
const monthsInFrench = [
"Janvier", "Février", "Mars", "Avril", "Mai", "Juin",
"Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"
];
const month = monthsInFrench[monthIndex];
let hours = date.getHours();
const minutes = date.getMinutes();
const ampm = hours >= 12 ? 'pm' : 'am';
hours = hours % 12;
hours = hours ? hours : 12;
const formattedTime = `${hours}:${minutes < 10 ? '0' + minutes : minutes} ${ampm}`;
return `${day} ${month} ${year} ${formattedTime}`;
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment